Modules/Modules.Logging/LogConfig.vb
Digital Data - Marlon Schreiber 379a36fba2 MS Loggername changed
2018-08-17 12:00:50 +02:00

243 lines
9.2 KiB
VB.net

Imports System.IO
Imports NLog
Imports NLog.Config
Imports NLog.Targets
''' <summary>
''' 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: logPath, PathType
''' customLogPath, String (optional)
'''
''' PROPERTIES: LogFile, String (readonly)
''' LogPath, String (readonly)
''' Debug, Boolean
''' </summary>
Public Class LogConfig
Private Const KEEP_FILES_OPEN As Boolean = False
Private Const MAX_ARCHIVE_FILES_DEFAULT As Integer = 30
Private Const MAX_ARCHIVE_FILES_DEBUG_DETAIL As Integer = 1
Private Const ARCHIVE_EVERY As FileArchivePeriod = FileArchivePeriod.Day
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_BASE As String = "${longdate}|${logger}|${level:uppercase=true}"
Private Const LOG_FORMAT_DEFAULT As String = LOG_FORMAT_BASE & " >> ${message}"
Private Const LOG_FORMAT_EXCEPTION As String = LOG_FORMAT_BASE & " >> ${exception:format=Message}${newline}${exception:format=StackTrace}"
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
''' <summary>
''' Returns the path to the current default logfile
''' </summary>
''' <returns>Filepath to the logfile</returns>
Public ReadOnly Property LogFile As String
''' <summary>
''' Returns the path to the current log directory
''' </summary>
''' <returns>Directory path to the log directory</returns>
Public ReadOnly Property LogDirectory As String
''' <summary>
''' Determines if a debug log will be written
''' </summary>
''' <returns>True, if debug log will be written. False otherwise.</returns>
Public Property Debug As Boolean
Get
Return isDebug
End Get
Set(isDebug As Boolean)
Me.isDebug = isDebug
ReloadConfig(isDebug)
End Set
End Property
''' <summary>
''' 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`
''' </summary>
''' <param name="logPath">The basepath to write logs to. Can be AppData, CurrentDirectory or CustomPath.</param>
''' <param name="customLogPath">If `logPath` is set to custom, this defines the custom logPath</param>
Public Sub New(logPath As PathType, Optional customLogPath As String = Nothing)
Dim productName As String = My.Application.Info.ProductName
Dim companyName As String = My.Application.Info.CompanyName
If logPath = PathType.AppData Then
Dim appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
basePath = Path.Combine(appDataDir, companyName, productName)
ElseIf logPath = PathType.CurrentDirectory Then
Dim currentDirectory As String = My.Application.Info.DirectoryPath
basePath = Path.Combine(currentDirectory, "Log")
Else 'Custom Path
basePath = customLogPath
End If
' If directory does not exist, try to create it!
If Not Directory.Exists(basePath) Then
Try
Directory.CreateDirectory(basePath)
Catch ex As Exception
' If creation fails, use failSafe path
basePath = failSafePath
End Try
End If
' Try to create a file in `basePath` to check write permissions
Try
Dim fileAccessPath = Path.Combine(basePath, "accessTest.txt")
Using fs As FileStream = File.Create(fileAccessPath)
fs.WriteByte(0)
End Using
File.Delete(fileAccessPath)
Catch ex As UnauthorizedAccessException
' If creation fails, use failSafe path
basePath = failSafePath
End Try
' Create config object and initalize it
config = New LoggingConfiguration()
config.Variables("product") = productName
' Add default targets
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))
' Add default rules
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)
' Save config
LogManager.Configuration = config
' Save log paths for files/directory
LogDirectory = basePath
LogFile = GetCurrentLogFilePath()
End Sub
''' <summary>
''' Returns the full path of the current default log file.
''' </summary>
''' <returns>Full path of the current default log file</returns>
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
''' <summary>
''' Reconfigures and re-adds all loggers, optionally adding the debug rule.
''' </summary>
''' <param name="Debug">Adds the Debug rule if true.</param>
Private Sub ReloadConfig(Optional Debug As Boolean = False)
' Clear Logging Rules
config.LoggingRules.Clear()
' Add default targets and debug target
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)
If Debug Then
config.AddRuleForOneLevel(LogLevel.Debug, TARGET_DEBUG)
End If
' Reload all running loggers
LogManager.ReconfigExistingLoggers()
End Sub
#Region "Log Targets"
Private Function GetDefaultLogTarget(basePath As String) As FileTarget
Dim defaultLog As New FileTarget() With {
.FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT),
.Name = TARGET_DEFAULT,
.Layout = LOG_FORMAT_DEFAULT,
.MaxArchiveFiles = MAX_ARCHIVE_FILES_DEFAULT,
.ArchiveEvery = ARCHIVE_EVERY,
.KeepFileOpen = KEEP_FILES_OPEN
}
Return defaultLog
End Function
Private Function GetDefaultLogTargetWithExceptions(basePath As String) As FileTarget
Dim defaultLogWithExceptionData As New FileTarget() With {
.FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT),
.Name = TARGET_DEFAULT_EX,
.Layout = LOG_FORMAT_EXCEPTION,
.MaxArchiveFiles = MAX_ARCHIVE_FILES_DEFAULT,
.ArchiveEvery = ARCHIVE_EVERY,
.KeepFileOpen = KEEP_FILES_OPEN
}
Return defaultLogWithExceptionData
End Function
Private Function GetDetailLogTarget(basePath As String) As FileTarget
Dim detailLog As New FileTarget() With {
.FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DETAIL),
.Name = TARGET_DETAIL,
.Layout = LOG_FORMAT_DEFAULT,
.MaxArchiveFiles = MAX_ARCHIVE_FILES_DEBUG_DETAIL,
.ArchiveEvery = ARCHIVE_EVERY,
.KeepFileOpen = KEEP_FILES_OPEN
}
Return detailLog
End Function
Private Function GetDebugLogTarget(basePath As String) As FileTarget
Dim debugLog As New FileTarget() With {
.FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DEBUG),
.Name = TARGET_DEBUG,
.Layout = LOG_FORMAT_DEFAULT,
.MaxArchiveFiles = MAX_ARCHIVE_FILES_DEBUG_DETAIL,
.ArchiveEvery = ARCHIVE_EVERY,
.KeepFileOpen = KEEP_FILES_OPEN
}
Return debugLog
End Function
#End Region
End Class