mni*_*eto 4 c# serilog .net-core asp.net-core-2.0
我将我的项目配置为使用Serilog使用依赖注入进行日志记录.我在类构造函数中使用以下模式:
namespace FlickPopper.API.Controllers {
public class ValuesController : Controller {
private ILogger<ValuesController> _logger;
public MyClass(ILogger<ValuesController> logger) {
_logger = logger;
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,serilog创建了记录器调用 Log.ForContext<classname>
我的设置是:
"Serilog": {
"WriteTo": [
{
"Name": "RollingFile",
"Args": {
"pathFormat": "Logs\\log-{Date}.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext" ]
}
Run Code Online (Sandbox Code Playgroud)
所以,日志看起来像这样:
2018-01-26 22:20:08 [INF] [FlickPopper.API.Controllers.ValuesController] Get all values
Run Code Online (Sandbox Code Playgroud)
格式化SourceContext属性以仅显示日志中的程序集名称,这是什么方式?
2018-01-26 22:20:08 [INF] [FlickPopper.API] Get all values
Run Code Online (Sandbox Code Playgroud)
当您使用注入时ILogger<T>,引擎盖下的Serilog记录器由实现接口的SerilogLoggerProvider创建ILoggerProvider.这个接口有唯一的方法:
public interface ILoggerProvider : IDisposable
{
ILogger CreateLogger(string categoryName);
}
Run Code Online (Sandbox Code Playgroud)
传递categoryName用作{SourceContext}消息格式的属性值.ASP.NET Core将其作为完全限定名称传递(例如FlickPopper.API.Controllers.ValuesController).
所以这个字符串值应该不是在Serilog代码或配置中修复,而是在ASP.NET Core日志记录基础结构中修复.
首先创建该值的负责类是Logger<T>class.的情况下,Logger<T>当你注入被实例化ILogger<T>到您的类.这是它的构造函数的源代码:
public class Logger<T> : ILogger<T>
{
public Logger(ILoggerFactory factory)
{
if (factory == null)
{
throw new ArgumentNullException(nameof(factory));
}
_logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T)));
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
该调用TypeNameHelper.GetTypeDisplayName(typeof(T))返回完全限定的名称,然后传递给ILoggerFactory并最终传递给SerilogLoggerProvider.
因此,如果您想要更改该行为并调整categoryName传递给ILoggerFactory,那么您应该拥有自己的实现,ILogger<T>从而进行必要的调用ILoggerFactory.CreateLogger().这并不困难,因为Logger<T>课程非常薄,并且基于Microsoft.Extensions.Logging.Logger实施.这是Logger<T>除了生成记录器类别名称的一行之外的类的副本:
public class LoggerEx<T> : ILogger<T>
{
private readonly ILogger _logger;
public LoggerEx(ILoggerFactory factory)
{
if (factory == null)
{
throw new ArgumentNullException(nameof(factory));
}
_logger = factory.CreateLogger(typeof(T).Assembly.GetName().Name);
}
IDisposable ILogger.BeginScope<TState>(TState state)
{
return _logger.BeginScope(state);
}
bool ILogger.IsEnabled(LogLevel logLevel)
{
return _logger.IsEnabled(logLevel);
}
void ILogger.Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
_logger.Log(logLevel, eventId, state, exception, formatter);
}
}
Run Code Online (Sandbox Code Playgroud)
您还应该ILogger<T>在服务注册中替换此标准实现:
services.AddSingleton(typeof(ILogger<>), typeof(LoggerEx<>));
现在,实例LoggerEx<T>将注入控制器并{SourceContext}具有您构建的值:
2018-01-27 09:54:21 [INF] [TestProject.TestApplication]你好!
我遇到了类似的问题,但我只想包含类/接口名称。
我通过创建自定义丰富器解决了这个问题。
// Create logger
var logger = new LoggerConfiguration()
// ...
.Enrich.With(new SourceContextEnricher())
// ...
.CreateLogger();
public class SourceContextEnricher : ILogEventEnricher {
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) {
if (logEvent.Properties.TryGetValue("SourceContext", out var property)) {
var scalarValue = property as ScalarValue;
var value = scalarValue?.Value as string;
if (value?.StartsWith("FlickPopper.API.") ?? false) {
var lastElement = value.Split(".").LastOrDefault();
if (!string.IsNullOrWhiteSpace(lastElement)) {
logEvent.AddOrUpdateProperty(new LogEventProperty("SourceContext", new ScalarValue(lastElement)));
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2317 次 |
| 最近记录: |