Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
587 views
in Technique[技术] by (71.8m points)

c# - Multiple filters for one logger with Serilog

I am trying to setup Serilog with my ASP.NET Core application. I'd like to have one log file for all controllers, one for all services, one for the rest and ideally one which contains everything. Every controller is inheriting BaseController and every service BaseService. The controller and the service I am calling are writing a trace log event.

The logger and the service are retrieved via dependy injection. The service looks like the controller (regarding the logger).

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;
    }
}

Approach 1 (working with the base clases only)

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

This creates the log files for "other" and "all" only. Both contain the log events from controller and service.

Approach 2 (working with the concrete classes)

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

This creates the log files for "other" and "all" only. "all" contains the log events from controller and service.

Approach 3 (working with the user classes only)

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

This creates all the log files and every file contains the expected messages.

What needs to be done to achieve the desired goal (see second sentence of this post).

Best regards, Carsten

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Serilog will also do this as you describe, by filtering by namespace:

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

If the controllers and services aren't identifiable by namespace, you can write a lambda function in place of isController or isService to identify them.

(Your scenario might be better suited to a logging format that permits easier filtering, so that you can selectively view controller events, service events and so-on by filtering after the fact. Check out the other Serilog provided sinks for some options.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...