创建返回 Serilog LoggerConfiguration 的方法(Asp.Net Core 2.0)

Posted

技术标签:

【中文标题】创建返回 Serilog LoggerConfiguration 的方法(Asp.Net Core 2.0)【英文标题】:Creating method to return Serilog LoggerConfiguration (Asp.Net Core 2.0) 【发布时间】:2018-05-16 08:10:36 【问题描述】:

我最初使用 Serilog 的一个日志文件,我是通过这样做来完成的

var slc = new SerilogSubLoggerConfiguration();   
configuration.GetSection("Serilog:SubLogger").Bind(slc);

然后在Program.cs的Main方法中配置SubLogger

 Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .WriteTo.Logger(logger => logger.Filter.
                ByIncludingOnly(lvl => lvl.Level == slc.Level).WriteTo.RollingFile(slc..PathFormat))
            .CreateLogger();

我已经开始使用现在在 appsettings 文件中定义的三个单独的日志。 这将创建具有一个属性的类,即 Serilog 配置列表

 public class SerilogSubLoggerConfigurations

    public List<SerilogSubLoggerConfiguration> SubLoggers  get; set; 


var slcs = configuration.GetSection("Serilog").Get<SerilogSubLoggerConfigurations>();

现在我有了 SubLogger 配置列表,我需要创建记录器,并添加所有这些子记录器。每个 SubLogger 都需要自己的

.WriteTo.Logger(logger => logger.Filter.
                ByIncludingOnly(lvl => lvl.Level == slc.Level).WriteTo.RollingFile(slc..PathFormat))

Log.Logger 调用中的行,因此我需要遍历 SubLoggers。 我的目的是写一个方法来做到这一点。

public static LoggerConfiguration GetLoggerConfiguration(IConfiguration config, SerilogSubLoggerConfigurations slcs)
    
        var lc = new LoggerConfiguration();
        lc.ReadFrom.Configuration(config);

        foreach (var cfg in slcs.SubLoggers)
        
            lc.WriteTo.Logger(logger => logger.Filter
                                       .ByIncludingOnly(lvl => lvl.Level == cfg.Level).WriteTo
                                       .RollingFile(cfg.PathFormat));
        

        lc.CreateLogger();
        return lc;
    

然后在 Main 方法中使用它

Log.Logger = GetLoggerConfiguration(configuration, slcs);

但这是错误的,

无法将类型“Serilog.LoggerConfiguration”隐式转换为“Serilog.ILogger”

我尝试将方法更改为 ILogger 并返回 ILogger,但 ILogger 不包含 WriteTo 和 ReadFrom 方法,所以这是不行的。 我尝试将返回的 LoggerConfiguration 转换为 ILogger,但这也不起作用,并且许多其他迭代也失败了。

必须有办法做到这一点。任何帮助表示赞赏。

更新:

 public static int Main(string[] args)
    
        var currentEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.currentEnv.json", optional: true)
            .AddEnvironmentVariables()
            .Build();

        var slcs = configuration.GetSection("Serilog").Get<SerilogSubLoggerConfigurations>();
        Log.Logger = BuildLogger(configuration, slcs);
        Log.Information(Appname != null ? $"AppnameLogDelimeterLogger created." : "Logger created.");

        try
        
            Log.Information(Appname != null ? $"AppnameLogDelimeterStarting web host" : "Starting web host.");
            BuildWebHost(args).Run();
            return 0;
        
        catch (Exception ex)
        
            Log.Fatal(ex,
                Appname != null
                    ? $"AppnameLogDelimeterWeb Host terminated unexpectedly"
                    : "Web Host terminated unexpectedly");
            return 1;
        
        finally
        

            Log.Information(Appname != null ? $"AppnameLogDelimeterFlushing log and closing it." : "Flushing log and closing it.");
            Log.CloseAndFlush();
        
    

【问题讨论】:

【参考方案1】:

我尝试将方法更改为 ILogger 并返回 ILogger, 但 ILogger 不包含 WriteTo 和 ReadFrom 方法,因此 是不行的。

Serilog 引导的顺序如下:

    您创建Serilog.LoggerConfiguration 对象的实例并使用代码调用 (WriteTo.RollingFile()) 或配置文件 (ReadFrom.Configuration()) 进行设置。 然后在构建 Serilog 配置后,您可以使用 LoggerConfiguration.CreateLogger() 调用创建一个记录器。

因此,在您完成加载配置之前,您无法记录任何消息(您还没有 Logger 实例)。但是在你构建了一个记录器之后,调用WriteToReadFrom 方法是没有意义的,因为记录器已经构建并且对源配置的更改不会影响任何事情。

因此,您可以将 GetLoggerConfiguration() 方法更改为:

public static Serilog.ILogger BuildLogger(IConfiguration config, SerilogSubLoggerConfigurations slcs)

    var lc = new LoggerConfiguration();
    lc.ReadFrom.Configuration(config);

    foreach (var cfg in slcs.SubLoggers)
    
        lc.WriteTo.Logger(logger => logger.Filter
            .ByIncludingOnly(lvl => lvl.Level == cfg.Level).WriteTo
            .RollingFile(cfg.PathFormat));
    

    //  Apply any additional changes to lc configuration here

    //  Finally build a logger
    return lc.CreateLogger();


static void Main(string[] args)

    //  ...
    var logger = BuildLogger(configuration, subLoggerConfigurations);

    //  No any changes could be made to logging configuration at this point.
    //  Just log what you need.

    logger.Information("Test info message");

【讨论】:

@CodeFuller...因为我不是专业程序员,所以我不明白为什么 lc.CreateLogger();返回 lc;与 return lc.CreateLogger() 有什么不同;因为我曾尝试将我的方法设为静态 ILogger,但在返回 lc 时出现错误; 另外,既然你是Serilog的专家,为什么Main中的这段代码要try-catch-finally; finally Log.Information(Appname != null ? $"AppnameLogDelimeter刷新日志并关闭它。" : "刷新日志并关闭它。"); Log.CloseAndFlush();在我的 Main 方法中,当应用程序关闭时不产生日志消息?记录器似乎没有在应用程序关闭时处理? Log.Information() 方法仅在您设置 Log.Logger 属性时有效:Log.Logger = BuildLogger(configuration, subLoggerConfigurations); Log.Information() 调用在应用程序的任何地方都有效。我只是想知道为什么当应用程序关闭时我没有收到日志已关闭和刷新的日志消息。关于我对 return lc 的第一条评论的任何想法; 关于第一条评论,lc.CreateLogger(); return lc;返回LoggerConfiguration类型的对象,你实际上并没有使用LoggerCreateLogger()调用创建的对象。

以上是关于创建返回 Serilog LoggerConfiguration 的方法(Asp.Net Core 2.0)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .Net Framework 中使用 Serilog 为每个 API 创建日志文件?

使用Serilog将程序结束时创建的日志文件通过电子邮件发送出去

Serilog Net Core 3.1 不创建任何日志文件

Serilog:记录到不同的文件

serilog应用在docker容器中,日志文件目录不会自动创建,需要手动创建目录,或者创建镜像的时候就包含进去

Serilog 异步 CPU 使用率高达 100%