Imports System.IO
Imports NLog
Imports NLog.Config
Imports NLog.Targets
'''
''' MODULE: Logger
'''
''' VERSION: 0.0.0.1
'''
''' DATE: 13.08.2018
'''
''' DESCRIPTION: Module that writes file-logs to different locations:
''' local application data, the current directory or a custom path.
''' Files and directories will be automatically created.
'''
''' Three different logfiles will be generated
'''
''' DEPENDENCIES: NLog, >= 4.5.8
'''
''' PARAMETERS: product, String
''' logPath, PathType
''' customLogPath, String (optional)
'''
''' PROPERTIES: LogFile, String (readonly)
''' LogPath, String (readonly)
''' Debug, Boolean
'''
Public Class Logger
Private Const FILE_NAME_FORMAT_DEFAULT As String = "${shortdate}-${var:product}.log"
Private Const FILE_NAME_FORMAT_DETAIL As String = "${shortdate}-${var:product}-Detail.log"
Private Const FILE_NAME_FORMAT_DEBUG As String = "${shortdate}-${var:product}-Debug.log"
Private Const TARGET_DEFAULT As String = "default"
Private Const TARGET_DEFAULT_EX As String = "defaultEx"
Private Const TARGET_DETAIL As String = "detail"
Private Const TARGET_DEBUG As String = "debug"
Private Const LOG_FORMAT_DEFAULT As String = "${longdate}|${level:uppercase=true}|${logger}|${message}"
Private Const LOG_FORMAT_EXCEPTION As String = LOG_FORMAT_DEFAULT & "|${exception:format=message}|${exception:format=toString}"
Private config As LoggingConfiguration
Private isDebug As Boolean = False
Private ReadOnly failSafePath As String = Path.GetTempPath()
Private ReadOnly basePath As String = failSafePath
Public Enum PathType As Integer
AppData = 0
CurrentDirectory = 1
CustomPath = 2
End Enum
'''
''' Returns the path to the current default logfile
'''
''' Filepath to the logfile
Public ReadOnly Property LogFile As String
'''
''' Returns the path to the current log directory
'''
''' Directory path to the log directory
Public ReadOnly Property LogDirectory As String
'''
''' Determines if a debug log will be written
'''
''' True, if debug log will be written. False otherwise.
Public Property Debug As Boolean
Get
Return isDebug
End Get
Set(isDebug As Boolean)
Me.isDebug = isDebug
ReloadConfig(isDebug)
End Set
End Property
'''
''' Initializes a new Logger for a specific `Product`.
'''
''' logPath configurations:
''' - AppData: writes to local application data directory
''' - CurrentDirectory: writes to `Log` directory relative to the current directory
''' - CustomPath: writes to custom path specified in `customLogPath`
'''
''' An name that identifies the Logs
''' The basepath to write logs to. Can be AppData, CurrentDirectory or CustomPath.
''' If `logPath` is set to custom, this defines the custom logPath
Public Sub New(product As String, logPath As PathType, Optional customLogPath As String = Nothing)
If logPath = PathType.AppData Then
Dim appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
basePath = Path.Combine(appDataDir, "Digital Data", product)
ElseIf logPath = PathType.CurrentDirectory Then
Dim currentDirectory As String = Environment.CurrentDirectory
basePath = Path.Combine(currentDirectory, "Log")
Else 'Custom Path
basePath = customLogPath
End If
config = New LoggingConfiguration()
config.Variables("product") = product
config.AddTarget(TARGET_DEFAULT_EX, GetDefaultLogTargetWithExceptions(basePath))
config.AddTarget(TARGET_DEFAULT, GetDefaultLogTarget(basePath))
config.AddTarget(TARGET_DETAIL, GetDetailLogTarget(basePath))
config.AddTarget(TARGET_DEBUG, GetDebugLogTarget(basePath))
LogDirectory = basePath
LogFile = GetCurrentLogFilePath()
AddDefaultLogTargets()
LogManager.Configuration = config
End Sub
'''
''' Returns the full path of the current default log file.
'''
''' Full path of the current default log file
Private Function GetCurrentLogFilePath()
Dim logEventInfo As New LogEventInfo() With {.TimeStamp = Date.Now}
Dim target As FileTarget = config.FindTargetByName(TARGET_DEFAULT)
Dim fileName As String = target.FileName.Render(logEventInfo)
Return fileName
End Function
'''
''' Reconfigures and re-adds all loggers, optionally adding the debug rule.
'''
''' Adds the Debug rule if true.
Private Sub ReloadConfig(Optional Debug As Boolean = False)
' Clear Logging Rules
config.LoggingRules.Clear()
' Add default targets and debug target
AddDefaultLogTargets()
If Debug Then
config.AddRuleForOneLevel(LogLevel.Debug, TARGET_DEBUG)
End If
' Reload all running loggers
LogManager.ReconfigExistingLoggers()
End Sub
'''
''' Adds default rules
'''
Private Sub AddDefaultLogTargets()
config.AddRuleForOneLevel(LogLevel.Error, TARGET_DEFAULT_EX)
config.AddRuleForOneLevel(LogLevel.Fatal, TARGET_DEFAULT_EX)
config.AddRuleForOneLevel(LogLevel.Warn, TARGET_DEFAULT)
config.AddRuleForOneLevel(LogLevel.Info, TARGET_DETAIL)
End Sub
#Region "Log Targets"
Private Function GetDefaultLogTarget(basePath As String) As FileTarget
Dim defaultFilePath As String = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT)
Dim defaultLog As New FileTarget() With {
.Name = TARGET_DEFAULT,
.FileName = defaultFilePath,
.Layout = LOG_FORMAT_DEFAULT,
.MaxArchiveFiles = 30,
.KeepFileOpen = Constants.KEEP_FILES_OPEN
}
Return defaultLog
End Function
Private Function GetDefaultLogTargetWithExceptions(basePath As String) As FileTarget
Dim defaultFilePath As String = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT)
Dim defaultLogWithExceptionData As New FileTarget() With {
.Name = TARGET_DEFAULT_EX,
.FileName = defaultFilePath,
.Layout = LOG_FORMAT_EXCEPTION,
.MaxArchiveFiles = 30,
.KeepFileOpen = Constants.KEEP_FILES_OPEN
}
Return defaultLogWithExceptionData
End Function
Private Function GetDetailLogTarget(basePath As String) As FileTarget
Dim detailFilePath As String = Path.Combine(basePath, FILE_NAME_FORMAT_DETAIL)
Dim detailLog As New FileTarget() With {
.Name = TARGET_DETAIL,
.FileName = detailFilePath,
.Layout = LOG_FORMAT_DEFAULT,
.MaxArchiveFiles = 1,
.KeepFileOpen = Constants.KEEP_FILES_OPEN
}
Return detailLog
End Function
Private Function GetDebugLogTarget(basePath As String) As FileTarget
Dim debugFilePath As String = Path.Combine(basePath, FILE_NAME_FORMAT_DEBUG)
Dim debugLog As New FileTarget() With {
.Name = TARGET_DEBUG,
.FileName = debugFilePath,
.Layout = LOG_FORMAT_DEFAULT,
.MaxArchiveFiles = 1,
.KeepFileOpen = Constants.KEEP_FILES_OPEN
}
Return debugLog
End Function
#End Region
End Class