Serilog 不输出日志到 txt 文件中 [英] Serilog does not output logs into the txt file

查看:93
本文介绍了Serilog 不输出日志到 txt 文件中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 dotnet worker 服务 (.net 5)我集成了 serilog 以及浓缩器和接收器.但由于某种原因,我的文件日志中没有看到任何输出.

Im using dotnet worker service (.net 5) I integrated serilog as well as enrichers and sinks. But for some reason I dont see any outputs into my files logs.

这是我的 appsettings.json

Here is my appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=.;Database=eeee;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "WorkerOptions": {
    "Batch": 5
  },
  "Serilog": {
    "Using": [],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
    "WriteTo": [
      { "Name": "Console" },
      {
        "Name": "File",
        "Args": {
          "path": "E:\\Logs\\log_.txt",
          "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
          "rollingInterval": "Day",
          "retainedFileCountLimit": 7
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "E:\\Logs\\log_.json",
          "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
          "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
          "rollingInterval": "Day",
          "retainedFileCountLimit": 7
        }
      }
    ]
  }
}

记录器的注册:

public class Program
{
    public static void Main(string[] args)
    {
            
        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .Build();

        Log.Logger = new LoggerConfiguration()
                            .ReadFrom.Configuration(configuration)
                            .CreateLogger();

        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
               
            .ConfigureServices((hostContext, services) =>
            {

                var configuration = new ConfigurationBuilder()
                                            .AddJsonFile("appsettings.json")
                                            .Build();

                var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
                optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
                services.AddScoped<ApplicationDbContext>(s => new ApplicationDbContext(optionsBuilder.Options));
                services.AddHostedService<Worker>();
            });
}

这是一个实现:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IServiceScopeFactory _serviceScopeFactory;
    private readonly IConfiguration _config;
    public Worker(ILogger<Worker> logger, IServiceScopeFactory serviceScopeFactory, IConfiguration config)
    {
        _config = config;
        _logger = logger;
        _serviceScopeFactory = serviceScopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
     _logger.LogInformation("Worker picked up {0} requests for dispatch at at: {time}", generatedRequests.Count(), DateTimeOffset.Now);
    }

当我通过 Kestrel 运行 worker 时,我可以在控制台日志中看到,但在我的 .txt 文件和 .json 文件中都看不到

And when I run the worker through Kestrel I can see in my console logs, but not in my .txt file nor .json file

更新 #1我尝试了下面的这个答案,但是在部署我的工作人员时仍然遇到问题,我没有看到任何日志.当我通过 service.exe 文件运行它或只是执行调试 (Kestrel) 日志文件时会生成.

UPDATE #1 I tried with this answer below, but I still have an issue when I deploy my worker, I do not see any logs. When I run it thrpugh service.exe fi;le or just do debugg (Kestrel) Logs files are generated.

这是更新的application.json:

Here is updated application.json:

"Serilog": {
  "Using": [],
  "MinimumLevel": {
    "Default": "Information",
    "Override": {
      "Microsoft": "Warning",
      "System": "Warning"
    }
  },
  "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
  "WriteTo": [
    { "Name": "Console" },
    {
      "Name": "File",
      "Args": {
        "path": ".\\Logs\\log_.txt",
        "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
        "rollingInterval": "Day",
        "retainedFileCountLimit": 7
      }
    },
    {
      "Name": "File",
      "Args": {
        "path": ".\\Logs\\log_.json",
        "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
        "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
        "rollingInterval": "Day",
        "retainedFileCountLimit": 7
      }
    }
  ]
}

这是 Program.cs

and this is the Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        var configuration = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json")
                    .Build();

        Log.Logger = new LoggerConfiguration()
                            .ReadFrom.Configuration(configuration)
                            .CreateLogger();

        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .UseWindowsService()
                    .ConfigureServices((hostContext, services) =>
                    {

                        var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
                        optionsBuilder.UseSqlServer(hostContext.Configuration.GetConnectionString("DefaultConnection"));
                        services.AddScoped<ApplicationDbContext>(s => new ApplicationDbContext(optionsBuilder.Options));
                        services.AddHostedService<Worker>();
                    })
                    .UseSerilog(); // no args
}

更新#2我像这样更新了程序类:

UPDATE#2 I updated Program class like this:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .UseWindowsService()
                    .ConfigureServices((hostContext, services) =>
                    {

                        var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
                        optionsBuilder.UseSqlServer(hostContext.Configuration.GetConnectionString("DefaultConnection"));
                        services.AddScoped<ApplicationDbContext>(s => new ApplicationDbContext(optionsBuilder.Options));
                        services.AddHostedService<Worker>();
                    })
                    .UseSerilog((hostContext, services, logger) => {
                        logger.ReadFrom.Configuration(hostContext.Configuration);
                    });
    }
}

我还在 appsettings.json 中放了一些简单的东西:

Also I put simple stuff in appsettings.json:

  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
    "WriteTo": [
      { "Name": "Console" },
      {
        "Name": "File",
        "Args": { "path": "Logs/log.txt" }
      },
      //{
      //  "Name": "File",
      //  "Args": {
      //    "path": ".\\Logs\\log_.txt",
      //    "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
      //    "rollingInterval": "Day",
      //    "retainedFileCountLimit": 7
      //  }
      //},
      {
        "Name": "File",
        "Args": {
          "path": ".\\Logs\\log_.json",
          "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
          "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
          "rollingInterval": "Day",
          "retainedFileCountLimit": 7
        }
      }
    ]
  }

这是在我启动 .exe 文件(控制台)时再次调用的 _logger 正在工作

Here is the also call of the _logger which is working, agaion when I start .exe file (console)

using Microsoft.Extensions.Logging;
...
private readonly ILogger<Worker> _logger;
...
_logger.LogInformation("Worker picked up {0} requests for dispatch at: {time}", generatedRequests.Count(), DateTimeOffset.Now);

更新#3我只是设置了记录 c:\\Logs\log.txt 的绝对路径,它部分工作 - 它创建了一个 txt 文件,但文件是空的.这是新的 appsettings.json:

UPDATE#3 I just setup absolute path for logging c:\\Logs\log.txt and it works partially - it creates a txt file, but file is empty. Here is the new appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=.;Database=svcProcessor_dev;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "WorkerOptions": {
    "Batch": 10,
    "Delay": 5000,
    "MaxAttempts":  3
  },
  "Serilog": {
    "Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
    "WriteTo": [
      { "Name": "Console" },
      {
        "Name": "File",
        "Args": { "path": "C:\\Logs\\log.txt" }
      }
      //{
      //  "Name": "File",
      //  "Args": {
      //    "path": "C:\\Logs\\log_.txt",
      //    "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
      //    "rollingInterval": "Day",
      //    "retainedFileCountLimit": 7
      //  }
      //}
      //{
      //  "Name": "File",
      //  "Args": {
      //    "path": "C:\\Logs\\log_.json",
      //    "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
      //    "outputTemplate": "{Timestamp:o} {Message}{NewLine:1}{Exception:1}",
      //    "rollingInterval": "Day",
      //    "retainedFileCountLimit": 7
      //  }
      //}
    ]
  }
}

更新#4

这是我的工人的最小例子工人示例

Here is the minimal example of my worker worker example

推荐答案

您没有添加将 Serilog 的 Logger 转换为 Microsoft.Extensions.Logging.ILogger.就目前而言,您只是在创建 Serilog 记录器,但并未实际使用它.您在控制台中看到的实际上是来自内置 Microsoft 记录器的日志,而不是来自 Serilog 的.

You aren't adding the infrastructure to convert Serilog's Logger into a Microsoft.Extensions.Logging.ILogger. As it stands, you are are just creating the Serilog Logger but not actually using it. What you're seeing in the console are actually the logs from the built-in Microsoft logger and not from Serilog.

幸运的是,Serilog 有一个从他们的记录器到 Microsoft 记录器接口和各种帮助程序包的适配器,具体取决于您的使用场景.您正在使用通用主机,因此首先添加 Serilog.Extensions.Hosting 打包 到您的项目中.然后调用UseSerilog 扩展方法.传递给此方法的委托接收 HostBuilderContext 的实例,您可以从中检索当前的 IConfiguration 以及 IServiceProvider>LoggingConfiguration 用于配置记录器:

Fortunately Serilog has an adapter from their logger to the Microsoft logger interfaces and various helper packages depending on your usage scenario. You're using the Generic Host so first add the Serilog.Extensions.Hosting package to your project. Then call the UseSerilog extension method. The delegate passed to this method receives an instance of the HostBuilderContext from which you can retrieve the current IConfiguration as well as the IServiceProvider and a LoggingConfiguration you use to configure the logger:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
   Host.CreateDefaultBuilder(args)              
       .ConfigureServices((hostContext, services) =>
        {
           /* elided */
        })
       .UseSerilog((hostContext, services, logger) => {
            logger.ReadFrom.Configuration(hostContext.Configuration);
        });

请注意,不再需要设置 Log.Logger 属性并直接从 Main 中构建 LoggerConfiguration.UseSerilog 方法将自动设置静态记录器——尽管您不需要它,但无论如何您都是通过 ILogger<> 进行记录的.

Note that there's no longer a need to set the Log.Logger property and build a LoggerConfiguration directly from within Main. The UseSerilog method will set the static logger automatically--though you won't need it, you're logging via ILogger<> anyways.

或者,您可以配置您当前使用的记录器方式(直接在 Main 中).如果你走这条路线,你会在没有任何参数的情况下调用 UseSerilog .这将依次使用静态记录器的当前配置.

Alternatively, you can configure the logger way you do currently (directly in Main). If you go this route you would call UseSerilog without any parameters. This will in turn use the current configuration of the static logger.

public static void Main(string[] args)
{
    var config = new ConfigurationBuilder()
                        .AddJsonFile("appsettings.json")
                        .Build();

    Log.Logger = new LoggingConfiguration()
                        .ReadFromConfiguration(config)
                        .CreateLogger();

    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
   Host.CreateDefaultBuilder(args)              
       .ConfigureServices((hostContext, services) =>
        {
           /* elided */
        })
       .UseSerilog(); // no args

我个人不喜欢这个选项,尤其是在使用 ReadFrom.Configuration 时,因为它需要你构建一个额外的配置对象.我更喜欢使用传入回调的那个,因为它将匹配主机使用的所有其他配置.

Personally I don't like this option, especially when using ReadFrom.Configuration as it requires you to build an extra configuration object. I'd prefer to use the one passed in to the callback since it will match all other configuration used by the Host.

您使用 aspnet-core 标记了您的问题,并参考了Kestrel";在你的问题中.但是,您演示的代码显示了一个非常基本的通用主机,而不是一个 Web 应用程序.如果这真的是一个网络应用程序,那么您将添加Serilog.AspNetCore 代替.该包隐含地引用了 Serilog.Extensions.Hosting 并包含了一些其他的点点滴滴,以便在网络应用程序中使用.

You tagged your question with aspnet-core and refer to "Kestrel" in your question. However the code you demonstrated shows a pretty basic Generic Host and not a web application. If this really is a web application then you would add the Serilog.AspNetCore package instead. That package implicitly references Serilog.Extensions.Hosting and includes some other bits and pieces for use from within a web application.

这篇关于Serilog 不输出日志到 txt 文件中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆