I'm using Serilog. To avoid configuration in each microservice I create a private NuGet package with extension like
namespace DFX.Logging
{
public static class Extensions
{
public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder) =>
webHostBuilder.UseSerilog((context, loggerConfiguration) =>
{
var logLevel = context.Configuration.GetValue<string>("Serilog:MinimumLevel");
if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))
{
level = LogEventLevel.Information;
}
loggerConfiguration.Enrich
.FromLogContext()
.MinimumLevel.Is(level);
loggerConfiguration
.ReadFrom.Configuration(context.Configuration)
.WriteTo.Console(
theme: AnsiConsoleTheme.Code,
outputTemplate: "[{Timestamp:yy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}");
});
}
}
in controller (or somewhere else) I create logger
private readonly ILogger _logger = Log.ForContext<Application>();
for that I need to add using using Serilog;
. I want to avoid it and use only my namespace using DFX.Logging;
. How can I rich that? What I have tried so far:
namespace DFX.Logging
{
// custom wrapper
public static class Log
{
public static ILogger ForContext<TSource>()
{
return (ILogger)Serilog.Log.ForContext<TSource>();
}
}
public interface ILogger : Serilog.ILogger
{
}
}
Then the code compile successfully but at the runtime I got
'Unable to cast object of type 'Serilog.Core.Logger' to type 'DFX.Logging.ILogger'.'
I realize that I can't cast Serilog.Core.Logger
to my logger because Serilog.Core.Logger
not implement DFX.Logging.ILogger
, but how it can be implemented?
The short answer is: You can't. At least not as easily as how you are thinking.
If you really want to go this route, some options could be:
LoggerProxy
class that implements your ILogger
interface, and wraps an instance of Serilog's ILogger
by ... writing the C# codeLoggerProxy
(a.k.a. LoggerInterceptor
) class that gets generated during runtime, using something like Castle.DynamicProxy or LinFu.DynamicProxy