一个带有 Serilog 的记录器的多个过滤器

Multiple filters for one logger with Serilog

我正在尝试使用我的 ASP.NET 核心应用程序设置 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();

这仅为 "other" 和 "all" 创建日志文件。两者都包含来自控制器和服务的日志事件。

方法 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();

这仅为 "other" 和 "all" 创建日志文件。 "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();

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

需要做什么才能达到预期的目标(见本post的第二句)。

此致, 卡斯滕

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 来识别它们。

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

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

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();