I am working on a WPF application and can sucessfully setup serilog and access it's static method by placing it inside App.xaml.cs,
However I am wanting to also log inside the various referenced class libraries in the project.
As I can't reference the main application from the class library itself, due to a circular dependency, what is the best way to perform logging in these class libraries?
public class LogManager : IMLogManager
{
#region Constructor
public LogManager()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console(LogEventLevel.Debug, OutputTemplate, theme: AnsiConsoleTheme.Code)
.WriteTo.Async(a => a.File("./log/log.log",
LogEventLevel.Debug,
OutputTemplate,
rollingInterval: RollingInterval.Day,
encoding: Encoding.UTF8,
buffered: true,
rollOnFileSizeLimit: true))
.CreateLogger();
}
#endregion
#region Private properties
/// <summary>
/// Template ghi log.
/// </summary>
public static string OutputTemplate =>
"[{Timestamp:dd-MM-yyyy HH:mm:ss.fff} {Level:u3}] source {SourceContext} ::: {Message:lj}{NewLine}{Exception}{NewLine}";
#endregion
#region Private methods
private static string FormatMessage(string message,
string memberName = "",
string filePath = "",
int lineNumber = 0)
=> $"in method [{Path.GetFileNameWithoutExtension(filePath)} > {memberName}]\r\n\tat {filePath}:{lineNumber}\r\n{message}";
#endregion
#region Private fields
#endregion
#region Implementation of IMLogManager
/// <summary>
/// Write app log.
/// </summary>
/// <param name="level"></param>
/// <param name="message"></param>
/// <param name="exception"></param>
/// <param name="memberName"></param>
/// <param name="filePath"></param>
/// <param name="lineNumber"></param>
public void WriteLog(LogEventLevel level,
string message,
Exception exception = null,
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0)
{
switch (level)
{
case LogEventLevel.Verbose:
Log.Verbose(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Debug:
Log.Debug(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Information:
Log.Information(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Warning:
Log.Warning(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Error:
Log.Error(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Fatal:
Log.Fatal(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
default:
throw new ArgumentOutOfRangeException(nameof(level), level, null);
}
}
public void WriteLog<T>(LogEventLevel level,
string message,
Exception exception = null,
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0) where T : class
{
var log = Log.ForContext<T>()
.ForContext("MemberName", memberName)
.ForContext("FilePath", filePath)
.ForContext("FileName", Path.GetFileNameWithoutExtension(filePath))
.ForContext("LineNumber", lineNumber);
switch (level)
{
case LogEventLevel.Verbose:
log.Verbose(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Debug:
log.Debug(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Information:
log.Information(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Warning:
log.Warning(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Error:
log.Error(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
case LogEventLevel.Fatal:
log.Fatal(exception, FormatMessage(message, memberName, filePath, lineNumber));
break;
default:
throw new ArgumentOutOfRangeException(nameof(level), level, null);
}
}
public void CloseAndFlush()
{
Log.CloseAndFlush();
}
#endregion
}