稍后在运行时创建serilog文件接收器-如何?

时间:2018-08-23 06:46:26

标签: serilog

我使用控制台,文件和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完成吗?

1 个答案:

答案 0 :(得分:0)

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

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

替换现有记录器

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

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)
{ ... }