为 Serilog 创建包装器
Create a wrapper for Serilog
我正在使用 Serilog。为了避免在每个微服务中进行配置,我创建了一个扩展名为
的私有 NuGet 包
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}");
});
}
}
在控制器(或其他地方)我创建记录器
private readonly ILogger _logger = Log.ForContext<Application>();
为此我需要使用 using Serilog;
添加。我想避免它并只使用我的命名空间 using DFX.Logging;
。我怎么才能富有呢?到目前为止我尝试了什么:
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
{
}
}
然后代码编译成功但是在运行时我得到了
'Unable to cast object of type 'Serilog.Core.Logger' to type
'DFX.Logging.ILogger'.'
我意识到我无法将 Serilog.Core.Logger
转换为我的记录器,因为 Serilog.Core.Logger
未实现 DFX.Logging.ILogger
,但如何实现?
简短的回答是:你不能。至少不像你想的那么容易。
如果你真的想走这条路,一些选择可能是:
- 创建您自己的实现您的
ILogger
接口的静态 LoggerProxy
class,并通过...编写 C# 代码
- 创建一个在运行时生成的动态
LoggerProxy
(a.k.a. LoggerInterceptor
) class,使用类似 Castle.DynamicProxy or LinFu.DynamicProxy
- 修改Serilog的代码实现你的接口,重新编译
- 通过 .NET IL Weaving 修改 Serilog 的程序集,例如,使用 Fody 扩展来实现您的接口
如果您不想依赖自己的日志代理,可以使用具有 serilog 实现的点网日志扩展。
https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger
https://github.com/serilog/serilog-extensions-logging
我正在使用 Serilog。为了避免在每个微服务中进行配置,我创建了一个扩展名为
的私有 NuGet 包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}");
});
}
}
在控制器(或其他地方)我创建记录器
private readonly ILogger _logger = Log.ForContext<Application>();
为此我需要使用 using Serilog;
添加。我想避免它并只使用我的命名空间 using DFX.Logging;
。我怎么才能富有呢?到目前为止我尝试了什么:
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
{
}
}
然后代码编译成功但是在运行时我得到了
'Unable to cast object of type 'Serilog.Core.Logger' to type 'DFX.Logging.ILogger'.'
我意识到我无法将 Serilog.Core.Logger
转换为我的记录器,因为 Serilog.Core.Logger
未实现 DFX.Logging.ILogger
,但如何实现?
简短的回答是:你不能。至少不像你想的那么容易。
如果你真的想走这条路,一些选择可能是:
- 创建您自己的实现您的
ILogger
接口的静态LoggerProxy
class,并通过...编写 C# 代码 - 创建一个在运行时生成的动态
LoggerProxy
(a.k.a.LoggerInterceptor
) class,使用类似 Castle.DynamicProxy or LinFu.DynamicProxy - 修改Serilog的代码实现你的接口,重新编译
- 通过 .NET IL Weaving 修改 Serilog 的程序集,例如,使用 Fody 扩展来实现您的接口
如果您不想依赖自己的日志代理,可以使用具有 serilog 实现的点网日志扩展。
https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger https://github.com/serilog/serilog-extensions-logging