【问题标题】:Multiple filters for one logger with Serilog使用 Serilog 为一个记录器提供多个过滤器
【发布时间】:2016-12-10 03:59:11
【问题描述】:

我正在尝试使用我的 ASP.NET Core 应用程序设置 Serilog。我想为所有控制器创建一个日志文件,为所有服务创建一个日志文件,为其余的一个日志文件,理想情况下,一个包含所有内容的日志文件。每个控制器都继承BaseController 和每个服务BaseService。我正在调用的控制器和服务正在编写跟踪日志事件。

通过依赖注入检索记录器和服务。该服务看起来像控制器(关于记录器)。

public class UsersController: BaseController
{
    private UserService service { get; }

    public UsersController(ILogger<UsersController> logger, UserService userService) : base(logger)
    {
        service = userService;
    }
}

public abstract class BaseController: Controller
{
    protected readonly ILogger<BaseController> Logger;

    public BaseController(ILogger<BaseController> logger)
    {
        Logger = logger;
    }
}

方法 1(仅使用基类)

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .WriteTo.Logger(l => l
        .MinimumLevel.Verbose()

        .WriteTo.Logger(l2 => l2
            .WriteTo.Logger(l3 => l3
                .Filter.ByIncludingOnly(Matching.FromSource<BaseController>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log"))
            .WriteTo.Logger(l3 => l3
                .Filter.ByIncludingOnly(Matching.FromSource<BaseService>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log"))
            .WriteTo.Logger(l3 => l3
                .Filter.ByExcluding(Matching.FromSource<BaseController>())
                .Filter.ByExcluding(Matching.FromSource<BaseService>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log"))
        )

        .WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log"))
    .CreateLogger();

这只会为“其他”和“全部”创建日志文件。两者都包含来自控制器和服务的日志事件。

方法 2(使用具体类)

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .WriteTo.Logger(l => l
        .MinimumLevel.Verbose()

        .WriteTo.Logger(l2 => l2
            .WriteTo.Logger(l3 => l3
                .Filter.ByIncludingOnly(Matching.FromSource<BaseController>())
                .Filter.ByIncludingOnly(Matching.FromSource<PrivilegeGroupsController>())
                .Filter.ByIncludingOnly(Matching.FromSource<PrivilegesController>())
                .Filter.ByIncludingOnly(Matching.FromSource<UsersController>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log"))
            .WriteTo.Logger(l3 => l3
                .Filter.ByIncludingOnly(Matching.FromSource<BaseService>())
                .Filter.ByIncludingOnly(Matching.FromSource<PrivilegeGroupService>())
                .Filter.ByIncludingOnly(Matching.FromSource<PrivilegeService>())
                .Filter.ByIncludingOnly(Matching.FromSource<UserService>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log"))
            .WriteTo.Logger(l3 => l3
                .Filter.ByExcluding(Matching.FromSource<BaseController>())
                .Filter.ByExcluding(Matching.FromSource<UsersController>())
                .Filter.ByExcluding(Matching.FromSource<PrivilegeGroupsController>())
                .Filter.ByExcluding(Matching.FromSource<PrivilegesController>())
                .Filter.ByExcluding(Matching.FromSource<BaseService>())
                .Filter.ByExcluding(Matching.FromSource<UserService>())
                .Filter.ByExcluding(Matching.FromSource<PrivilegeGroupService>())
                .Filter.ByExcluding(Matching.FromSource<PrivilegeService>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log"))
        )

        .WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log"))
    .CreateLogger();

这只会为“其他”和“全部”创建日志文件。 "all" 包含来自控制器和服务的日志事件。

方法 3(仅使用用户类)

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .WriteTo.Logger(l => l
        .MinimumLevel.Verbose()

        .WriteTo.Logger(l2 => l2
            .WriteTo.Logger(l3 => l3
                .Filter.ByIncludingOnly(Matching.FromSource<UsersController>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log"))
            .WriteTo.Logger(l3 => l3
                .Filter.ByIncludingOnly(Matching.FromSource<UserService>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log"))
            .WriteTo.Logger(l3 => l3
                .Filter.ByExcluding(Matching.FromSource<UsersController>())
                .Filter.ByExcluding(Matching.FromSource<UserService>())
                .MinimumLevel.Verbose()
                .WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log"))
        )

        .WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log"))
    .CreateLogger();

这将创建所有日志文件,并且每个文件都包含预期的消息。

为实现预期目标需要做什么(参见本文的第二句)。

最好的问候, 卡斯滕

【问题讨论】:

    标签: c# logging serilog


    【解决方案1】:

    Serilog 也将按照您的描述通过命名空间过滤来执行此操作:

    var isController = Matching.FromSource("MyApp.Controllers");
    var isService = Matching.FromSource("MyApp.Services");
    
    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Verbose()
        .WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log")
        .WriteTo.Logger(l => l
            .Filter.ByIncludingOnly(isController)
            .WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log"))
        .WriteTo.Logger(l => l
            .Filter.ByIncludingOnly(isService)
            .WriteTo.RollingFile("d:/logs/recon-api-service-{Date}.log"))
        .WriteTo.Logger(l => l
            .Filter.ByExcluding(e => isController(e) || iService(e))
            .WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log"))
        .CreateLogger();
    

    如果控制器和服务无法通过命名空间识别,您可以编写一个 lambda 函数来代替 isControllerisService 来识别它们。

    (您的场景可能更适合允许更轻松过滤的日志记录格式,以便您可以通过过滤事后来选择性地查看控制器事件、服务事件等。查看其他 Serilog provided sinks 一些选项。)

    【讨论】:

    • 所以......从假期回来:您的建议与我的第一种方法完全一样(它为“all”和“other”创建日志文件,并且都包含所有消息)。一些完整性检查代码:var isController = Matching.FromSource("ReconAPI.Controllers");namespace ReconAPI.Controllers
    • .Filter.ByExcluding(e =&gt; isController(e) || iService(e)) 中放置一个断点并检查事件可能有助于深入了解它。您的活动是否正确标记为SourceContext
    • 我只使用了Log.Logger。使用Log.ForContext&lt;T&gt;()帮助了很多,现在消息出现在它们应该出现的位置。非常感谢!
    • 太棒了。很高兴听到它:-)
    • @NicholasBlumhardt 你会如何在 json 文件中使用这种方法 .Filter.ByExcluding() 来排除微软日志?
    【解决方案2】:

    问题已经回答了。但如果你想将不同的级别记录到不同的文件中,你可以使用以下配置:

    var conn = configuration.GetSection("ConnectionStrings:SqlConn").Value;
    var serilogLogger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .WriteTo.Console()
                .WriteTo.MSSqlServer(conn, new MSSqlServerSinkOptions { TableName = "ErrorLogs", AutoCreateSqlTable = true }, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Warning)
                .WriteTo.MSSqlServer(conn, new MSSqlServerSinkOptions { TableName = "InfoLogs", AutoCreateSqlTable = true }, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information)
                .CreateLogger();
    

    【讨论】:

      猜你喜欢
      • 2019-08-17
      • 1970-01-01
      • 2012-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多