|
|
|
@ -0,0 +1,168 @@ |
|
|
|
|
|
|
|
using Common.Logging; |
|
|
|
|
|
|
|
using Serilog; |
|
|
|
|
|
|
|
using Serilog.Core; |
|
|
|
|
|
|
|
using Serilog.Events; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Common.Logger; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Implements a Logger that uses the Serilog package to create log entries and distributes them into different sinks. |
|
|
|
|
|
|
|
/// Implemented Sinks: File (rolling file), Debug (<see cref="System.Diagnostics.Debug"/>). |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public class SerilogLogger : Logging.ILogger |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
private readonly LoggingLevelSwitch loggingLevelSwitch; |
|
|
|
|
|
|
|
public event EventHandler<NewLogEntryEventArgs>? NewLogEntry; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Constructor of a Logger that uses the Serilog package to create log entries and distributes them into different sinks. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
/// <param name="logFilePath"> |
|
|
|
|
|
|
|
/// path where the logfile shall be created. |
|
|
|
|
|
|
|
/// rolling file is created with daily interval. date is automatically added to file name. |
|
|
|
|
|
|
|
/// Example: "C:/log/log-.txt" |
|
|
|
|
|
|
|
/// </param> |
|
|
|
|
|
|
|
/// <param name="logToDebug"> |
|
|
|
|
|
|
|
/// if true the log entries are written to <see cref="System.Diagnostics.Debug"/>. |
|
|
|
|
|
|
|
/// Minimum level is ignored for this log entries, therefore every log entry will be logged. |
|
|
|
|
|
|
|
/// </param> |
|
|
|
|
|
|
|
public SerilogLogger(string logFilePath, bool logToDebug) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// create logging level switch and initialized with lowest level |
|
|
|
|
|
|
|
this.loggingLevelSwitch = new LoggingLevelSwitch() { MinimumLevel = Serilog.Events.LogEventLevel.Verbose }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// create logger instance |
|
|
|
|
|
|
|
if (logToDebug) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Log.Logger = new LoggerConfiguration() |
|
|
|
|
|
|
|
.WriteTo.Debug() |
|
|
|
|
|
|
|
.WriteTo.File(logFilePath, |
|
|
|
|
|
|
|
rollingInterval: RollingInterval.Day, |
|
|
|
|
|
|
|
levelSwitch: loggingLevelSwitch, |
|
|
|
|
|
|
|
outputTemplate: "{Message:lj}") // outputTemplate = plain message, formatting is done inside log entry |
|
|
|
|
|
|
|
.CreateLogger(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Log.Logger = new LoggerConfiguration() |
|
|
|
|
|
|
|
.WriteTo.File(logFilePath, |
|
|
|
|
|
|
|
rollingInterval: RollingInterval.Day, |
|
|
|
|
|
|
|
levelSwitch: loggingLevelSwitch, |
|
|
|
|
|
|
|
outputTemplate: "{Message:lj}") // outputTemplate = plain message, formatting is done inside log entry |
|
|
|
|
|
|
|
.CreateLogger(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Initialize() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.Initialize(LogLevel.Trace); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Initialize(LogLevel minimumLogLevel) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.SetMinimumLogLevel(minimumLogLevel); |
|
|
|
|
|
|
|
// Nothing else to do for this logger |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void SetMinimumLogLevel(LogLevel newMinimumLogLevel) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.loggingLevelSwitch.MinimumLevel = this.ConvertGenericToSerilogLogLevel(newMinimumLogLevel); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private LogEventLevel ConvertGenericToSerilogLogLevel(LogLevel newMinimumLogLevel) => newMinimumLogLevel switch |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LogLevel.Undefined => LogEventLevel.Verbose, |
|
|
|
|
|
|
|
LogLevel.Trace => LogEventLevel.Verbose, |
|
|
|
|
|
|
|
LogLevel.Debug => LogEventLevel.Debug, |
|
|
|
|
|
|
|
LogLevel.Info => LogEventLevel.Information, |
|
|
|
|
|
|
|
LogLevel.Warn => LogEventLevel.Warning, |
|
|
|
|
|
|
|
LogLevel.Error => LogEventLevel.Error, |
|
|
|
|
|
|
|
_ => throw new NotImplementedException($"'{nameof(ConvertGenericToSerilogLogLevel)}()' does not contain an entry for {nameof(LogLevel)} {newMinimumLogLevel}"), |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void StopLogging() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Log.CloseAndFlush(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void CreateLogEntry(LogEntry logEntry) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var serilogEventLevel = this.ConvertGenericToSerilogLogLevel(logEntry.LogLevel); |
|
|
|
|
|
|
|
// formatting is done inside logEntry.ToString() method => therefore log plain message text with right category |
|
|
|
|
|
|
|
switch (serilogEventLevel) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case LogEventLevel.Verbose: |
|
|
|
|
|
|
|
Log.Verbose(logEntry.ToString()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case LogEventLevel.Debug: |
|
|
|
|
|
|
|
Log.Debug(logEntry.ToString()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case LogEventLevel.Information: |
|
|
|
|
|
|
|
Log.Information(logEntry.ToString()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case LogEventLevel.Warning: |
|
|
|
|
|
|
|
Log.Warning(logEntry.ToString()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case LogEventLevel.Error: |
|
|
|
|
|
|
|
Log.Error(logEntry.ToString()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case LogEventLevel.Fatal: |
|
|
|
|
|
|
|
Log.Error(logEntry.ToString()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new NotImplementedException($"'{nameof(CreateLogEntry)}()' does not contain an implementation for {nameof(LogEventLevel)} {serilogEventLevel}."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region Logging methods |
|
|
|
|
|
|
|
public void LogTrace(string message, string category = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.CreateLogEntry(new LogEntry { Category = category, LogLevel = LogLevel.Trace, Message = message }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void LogDebug(string message, string category = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.CreateLogEntry(new LogEntry { Category = category, LogLevel = LogLevel.Debug, Message = message }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void LogInfo(string message, string category = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.CreateLogEntry(new LogEntry { Category = category, LogLevel = LogLevel.Info, Message = message }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void LogWarn(string message, string category = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.CreateLogEntry(new LogEntry { Category = category, LogLevel = LogLevel.Warn, Message = message }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void LogError(string message, string category = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.CreateLogEntry(new LogEntry { Category = category, LogLevel = LogLevel.Error, Message = message }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void LogException(Exception exception, string category = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.CreateLogEntry(new LogEntry { Category = category, LogLevel = LogLevel.Error, Exception = exception }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void LogException(Exception exception, string message, string category = "") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.CreateLogEntry( |
|
|
|
|
|
|
|
new LogEntry |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Category = category, |
|
|
|
|
|
|
|
LogLevel = LogLevel.Error, |
|
|
|
|
|
|
|
Message = message, |
|
|
|
|
|
|
|
Exception = exception |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |