Forum Discussion
MarkusWipp
2 years agoContributor
Hi all,
I share my solution to it (this still logs to the standard OS logs):
You can put it into an extender business rule as a separate namespace in this case.
Namespace Common.Logging
Public Interface ILogging
Sub LogTrace(message As String)
Sub LogDebug(message As String)
Sub LogError(message As String)
Sub LogMessage(message As String)
End Interface
Public Enum LogLevel
LogTrace = 4
LogDebug = 3
LogMessage = 2
LogError = 1
End Enum
Public Class OneStreamLogging
Inherits DefaultLogging
Public Const defaultMessageHeading = "OneStreamLogging Messages"
Private si As SessionInfo
Private userInLoggingGroup As Boolean
Private collectLogs As Boolean
Private collectedLogs As New Text.StringBuilder()
Private messageHeading As String
Public Sub New(ByVal si As SessionInfo, Optional logLevel As LogLevel = LogLevel.LogError, Optional withTiming As Boolean = False, Optional collectLogs As Boolean = False, Optional messageHeading As String = defaultMessageHeading)
MyBase.New(logLevel, withTiming)
Me.si = si
Me.collectLogs = collectLogs
Me.userInLoggingGroup = BRApi.Security.Authorization.IsUserInGroup(si, si.UserName, "ALLC_LoggingEnabledUsers", False)
Me.messageHeading = messageHeading
End Sub
Protected Overrides Sub WriteMessage(loglevel As LogLevel, message As String)
If loglevel.Equals(LogLevel.LogError) Then
If collectLogs Then
collectedLogs.AppendLine($"{loglevel}: {message}")
Else
BRApi.ErrorLog.LogError(si, New XFException(message))
End If
Else
If userInLoggingGroup Then
If collectLogs Then
collectedLogs.AppendLine($"{loglevel}: {message}")
Else
If messageHeading.Equals(defaultMessageHeading) Then
BRApi.ErrorLog.LogMessage(si, message)
Else
BRApi.ErrorLog.LogMessage(si, Me.messageHeading, message)
End If
End If
End If
End If
End Sub
Public Sub LogCollectedLogs()
If collectedLogs.Length > 0 Then
If messageHeading.Equals(defaultMessageHeading) Then
BRApi.ErrorLog.LogMessage(si, collectedLogs.ToString())
Else
BRApi.ErrorLog.LogMessage(si, Me.messageHeading, collectedLogs.ToString())
End If
End If
End Sub
End Class
Public Class DefaultLogging
Implements ILogging
Private desiredLogLevel As LogLevel
Private withTiming As Boolean
Private elapsedTime As New Stopwatch()
Public Sub New(Optional logLevel As LogLevel = LogLevel.LogError, Optional withTiming As Boolean = False)
Me.desiredLogLevel = logLevel
Me.withTiming = withTiming
If Me.withTiming Then
elapsedTime.Start()
End If
Me.LogTrace("Initialized Logger")
End Sub
Public Sub LogTrace(message As String) Implements ILogging.LogTrace
Log(LogLevel.LogTrace, "TRACE", message)
End Sub
Public Sub LogDebug(message As String) Implements ILogging.LogDebug
Log(LogLevel.LogDebug, "DEBUG", message)
End Sub
Public Sub LogError(message As String) Implements ILogging.LogError
Log(LogLevel.LogError, "ERROR", message)
End Sub
Public Sub LogMessage(message As String) Implements ILogging.LogMessage
Log(LogLevel.LogMessage, "MESSAGE", message)
End Sub
Private Sub Log(loglevel As LogLevel, levelname As String, message As String)
If (loglevel <= Me.desiredLogLevel) Then
Dim stackframe As New Diagnostics.StackFrame(2)
Dim baseFormat = $"{levelname}: {stackframe.GetMethod().DeclaringType.Namespace}:{stackframe.GetMethod().DeclaringType.Name}:{stackframe.GetMethod().Name}: "
If withTiming Then
Dim ts As TimeSpan = elapsedTime.Elapsed
Dim formattedElapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
WriteMessage(loglevel, $"{baseFormat}: {formattedElapsedTime}: {message}")
Else
WriteMessage(loglevel, $"{baseFormat}: {message}")
End If
End If
End Sub
Protected Overridable Sub WriteMessage(loglevel As LogLevel, message As String)
Console.WriteLine(message)
End Sub
End Class
End Namespace
and then use e.g. like this from other BRs (of course you have to reference the above Business Rule
Imports Common.Logging
Namespace OneStream.BusinessRule.Extender.Test
Public Class MainClass
Public Function Main(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As DashboardStringFunctionArgs) As Object
Dim logger As OneStreamLogging = New OneStreamLogging(si, LogLevel.LogDebug, True, True, $"Test Logging")
Try
logger.LogMessage("This is a message")
logger.LogDebug("This is a debug message")
logger.LogTrace("This is a trace massage")
logger.LogError("This is an error message")
Catch ex As Exception
Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
Finally
logger.LogCollectedLogs()
End Try
End Function
End Class
End Namespace
This allows you the follwoing:
- can be used outside onestream and logs to the console
- only log for users in security group ALLC_LoggingEnabledUsers
- only log messages up to e certain log-level
- collect logs during an execution and only log everything at once on the end
- logs additional useful information / timing / stack trace /etc.
Hope that is useful to some of you
Markus
Related Content
- 2 months ago
- 7 months ago
- 2 years ago
- 9 months ago
- 7 months ago