我将我的项目配置为使用依赖注入使用serilog进行日志记录。
我在类构造函数中使用以下架构:

namespace FlickPopper.API.Controllers {

    public class ValuesController : Controller {
        private ILogger<ValuesController> _logger;
        public MyClass(ILogger<ValuesController> logger) {
           _logger = logger;
        }
    }
}

通过这种方式,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" ]
    }

所以,日志看起来是这样的:
2018-01-26 22:20:08 [INF] [FlickPopper.API.Controllers.ValuesController] Get all values

有什么方法可以将sourcecontext属性格式化为只在日志中显示程序集名称,比如这样?
2018-01-26 22:20:08 [INF] [FlickPopper.API] Get all values

最佳答案

当您使用injectedILogger<T>时,引擎盖下的serilog记录器由实现ILoggerProvider接口的SerilogLoggerProvider创建。此接口只有一个方法:

public interface ILoggerProvider : IDisposable
{
    ILogger CreateLogger(string categoryName);
}

传递的categoryName用作消息格式的{SourceContext}属性的值。并且asp.net core将其作为完全限定名(例如FlickPopper.API.Controllers.ValuesController)传递。
因此,不应在serilog代码或配置中修复此字符串值,而应在asp.net核心日志基础结构中修复。
首先负责创建该值的类是Logger<T>类。Logger<T>的实例是在将ILogger<T>注入类时实例化的。以下是其构造函数的source code
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)));
    }

    //  ...
}

TypeNameHelper.GetTypeDisplayName(typeof(T))的调用返回完全限定名,然后传递给ILoggerFactory并最终传递给SerilogLoggerProvider
因此,如果您想更改该行为并调整传递给categoryNameILoggerFactory,您应该拥有自己的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);
    }
}

您还应该在服务注册中将ILogger<T>的标准实现替换为此实现:
services.AddSingleton(typeof(ILogger<>), typeof(LoggerEx<>));
现在LoggerEx<T>的实例将被注入控制器,并且{SourceContext}将具有您生成的值:
2018-01-27 09:54:21[inf][testproject.testapplication]您好!

10-06 05:47