【问题标题】:Creating a serilog file sink later at runtime - how?稍后在运行时创建一个 serilog 文件接收器 - 如何?
【发布时间】:2018-08-23 06:46:25
【问题描述】:

我使用控制台、文件和 Graylog 接收器在服务器端为我的所有 .NETCore 服务使用 Serilog。我也喜欢在我的 Windows 胖客户端(WPF 应用程序)中使用它。

我有一个问题,因为我没有看到,我如何在用户成功登录后添加另一个文件接收器。我需要一个存储在全局 AppData (Environment.SpecialFolder.CommonApplicationData) 文件夹中的应用程序日志和另一个 User-log 用户 子文件夹 例如像这样:

var appName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
AppDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), appName);
Directory.CreateDirectory(AppDataDir);
AppLogDir = Path.Combine(AppDataDir, $@"Logs");
Directory.CreateDirectory(AppLogDir);

Log.Logger = new LoggerConfiguration()
    .ReadFrom.AppSettings()
    .Enrich.WithExceptionDetails()
    .Enrich.FromLogContext()
    .Enrich.WithProcessName()
    .Enrich.WithThreadId()
    .Enrich.WithAssemblyName()
    .WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] " +
                                     "ThreadId: [{ThreadId}] {Message:lj}{NewLine}{Exception}")
    .WriteTo.File(Path.Combine(AppLogDir, $"{appName}-.log"), rollOnFileSizeLimit: true,
        fileSizeLimitBytes: 1048576, retainedFileCountLimit: 30,
        outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] " +
                        "[ThreadId: {ThreadId}] {Message:lj}{NewLine}{Exception}")
    .CreateLogger();

然后在我的LoginViewModel 中,在成功 登录并且在配置初始应用程序记录器很久之后,我知道用户名并且可以为该用户创建一个文件夹并在那里放一个日志文件:

var userLogDir = Path.Combine(AppDataDir, userName); // <-- userName comes from login token
Directory.CreateDirectory(userLogDir);

现在出现了棘手的问题:如何将文件接收器添加到我的现有记录器配置?我需要类似的东西:

var loggerConfig = Log.GetLoggerConfiguration();  //<--- This is missing, at least I could not find it!
loggerConfig.WriteTo.File(Path.Combine(userLogDir, $"{appName}-{userName}-.log"), rollOnFileSizeLimit: true,
        fileSizeLimitBytes: 10485760, retainedFileCountLimit: 30,
        outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] " +
                        "[ThreadId: {ThreadId}] {Message:lj}{NewLine}{Exception}")

知道如何使用 Serilog 实现这一点吗?

【问题讨论】:

    标签: c# .net-core serilog graylog


    【解决方案1】:

    我知道这是旧的,但我想我会回答这个问题,因为我只需要在我的一个项目中做类似的事情(在运行时更改记录器)。

    原来有几种方法可以做到这一点,主要的事情(至少在前两种中)是将记录器配置与记录器本身分离。这允许您存储配置以供以后使用,如果您想稍后简单地添加到接收器而不是重新开始。

    替换现有记录器

    第一种方法完全用新的记录器替换了记录器

    var logfilepath = GetLogFilePath(Assembly.GetEntryAssembly());
    var loggerConfig = new LoggerConfiguration()
      .WriteTo.RollingFile(logfilepath);
      
    Log.Logger= loggerConfig.CreateLogger();
      
    Log.Debug("It works!");
    
    
    //Somewhere later in the program
    Log.Debug("Setting up database with {ConnectionString}", connectionString);
    
    
    loggerConfig = loggerConfig.WriteTo.MSSqlServer(
        connectionString: "Server=localhost;Database=LogDb;Integrated Security=SSPI;",
        sinkOptions: new MSSqlServerSinkOptions { TableName = "LogEvents" });
    
    Log.Logger = loggerConfig.CreateLogger(); //Replace the old logger with the new one
    

    创建新记录器并将所有事件也发送到旧记录器

    下一个示例展示了我们创建一个新的记录器,然后将所有事件也传递给旧记录器,有效地允许我们添加。如果您走这条路,请务必牢记 Logger 的生命周期。

    Log.Debug("Setting up database with {ConnectionString}", connectionString);
    
    var loggerConfig = new LoggerConfiguration()
      .WriteTo.Sink((ILogEventSink)Log.Logger) //Here we're passing in the old logger
      .WriteTo.MSSqlServer(
        connectionString: "Server=localhost;Database=LogDb;Integrated Security=SSPI;",
        sinkOptions: new MSSqlServerSinkOptions { TableName = "LogEvents" });
    
    Log.Logger = loggerConfig.CreateLogger();
    

    跟上配置

    以这种方式设置记录器时,我们可以轻松地将配置添加到 DI 容器中:

    IServiceCollection

    services.AddSingleton(loggerConfig);

    团结

    container.RegisterInstance(loggerConfig);

    这使我们能够在应用程序生命的后期访问我们的配置,并且在很大程度上使我们不必再次重新配置所有接收器、浓缩器等。

    奖金

    另外,我遇​​到的另一件事是,我们也可以在运行时从 dll 加载接收器(Serilog >=3.0)。正如this issue 中所述,我们可以在运行时使用 ConfigurationAssemblySource 从程序集中加载配置。

    public static LoggerConfiguration Configuration(
        this LoggerSettingsConfiguration settingConfiguration,
        IConfiguration configuration,
        ConfigurationAssemblySource configurationAssemblySource)
    { ... }
    

    【讨论】:

    • 我不确定我是否做错了什么,但创建第二个记录器似乎不再起作用。即使我使用新的LoggerConfiguration,我也会收到异常CreateLogger() was previously called and can only be called once. 我认为它与this issue 有关。我不确定是否有解决方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-07
    相关资源
    最近更新 更多