简体   繁体   English

Serilog 没有 output 登录到txt文件

[英]Serilog does not output logs into the txt file

Im using dotnet worker service (.net 5) I integrated serilog as well as enrichers and sinks.我使用 dotnet worker 服务(.net 5)我集成了 serilog 以及丰富器和接收器。 But for some reason I dont see any outputs into my files logs.但由于某种原因,我在文件日志中看不到任何输出。

Here is my appsettings.json这是我的 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
        }
      }
    ]
  }
}

Registration of logger:记录仪注册:

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

and this is an implementation:这是一个实现:

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

And when I run the worker through Kestrel I can see in my console logs, but not in my.txt file nor.json file当我通过 Kestrel 运行工作程序时,我可以在控制台日志中看到,但在 my.txt 文件和 json 文件中看不到

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.更新#1我在下面尝试了这个答案,但是当我部署我的工作人员时我仍然遇到问题,我没有看到任何日志。 When I run it thrpugh service.exe fi;le or just do debugg (Kestrel) Logs files are generated.当我通过 service.exe 文件运行它时,或者只是进行调试(Kestrel)会生成日志文件。

Here is updated application.json:这是更新的应用程序。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
      }
    }
  ]
}

and this is the Program.cs这是 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
}

UPDATE#2 I updated Program class like this: UPDATE#2我像这样更新了程序 class:

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

Also I put simple stuff in appsettings.json:我还在 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
        }
      }
    ]
  }

Here is the also call of the _logger which is working, agaion when I start.exe file (console)当我 start.exe 文件(控制台)再次调用时,这也是正在工作的 _logger

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

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.更新#3我只是设置了记录c:\\Logs\log.txt的绝对路径,它部分工作 - 它创建一个 txt 文件,但文件为空。 Here is the new appsettings.json:这是新的 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
      //  }
      //}
    ]
  }
}

update#4更新#4

Here is the minimal example of my worker worker example这是我的工人工人示例的最小示例

You aren't adding the infrastructure to convert Serilog's Logger into a Microsoft.Extensions.Logging.ILogger .您没有添加将 Serilog 的Logger转换为Microsoft.Extensions.Logging.ILogger的基础结构。 As it stands, you are are just creating the Serilog Logger but not actually using it.就目前而言,您只是在创建 Serilog Logger,但并未实际使用它。 What you're seeing in the console are actually the logs from the built-in Microsoft logger and not from Serilog.您在控制台中看到的实际上是来自内置 Microsoft 记录器的日志,而不是来自 Serilog 的日志。

Fortunately Serilog has an adapter from their logger to the Microsoft logger interfaces and various helper packages depending on your usage scenario.幸运的是,根据您的使用场景,Serilog 有一个从他们的记录器到 Microsoft 记录器接口和各种帮助程序包的适配器。 You're using the Generic Host so first add the Serilog.Extensions.Hosting package to your project.您正在使用通用主机,因此首先将Serilog.Extensions.Hosting package添加到您的项目中。 Then call the UseSerilog extension method.然后调用UseSerilog扩展方法。 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:传递给此方法的委托接收HostBuilderContext的实例,您可以从中检索当前的IConfiguration以及用于配置记录器的IServiceProviderLoggingConfiguration

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

Note that there's no longer a need to set the Log.Logger property and build a LoggerConfiguration directly from within Main .请注意,不再需要直接从Main中设置Log.Logger属性和构建LoggerConfiguration The UseSerilog method will set the static logger automatically--though you won't need it, you're logging via ILogger<> anyways. UseSerilog方法将自动设置 static 记录器——尽管您不需要它,但无论如何您都是通过ILogger<>记录的。

Alternatively, you can configure the logger way you do currently (directly in Main ).或者,您可以配置当前执行的记录器方式(直接在Main中)。 If you go this route you would call UseSerilog without any parameters.如果您使用 go 这条路线,您将在没有任何参数的情况下调用UseSerilog This will in turn use the current configuration of the static logger.这将反过来使用 static 记录器的当前配置。

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

Personally I don't like this option, especially when using ReadFrom.Configuration as it requires you to build an extra configuration object.我个人不喜欢这个选项,尤其是在使用ReadFrom.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.我更喜欢使用传入回调的那个,因为它将匹配主机使用的所有其他配置。

ASP.NET Core ASP.NET核心

You tagged your question with aspnet-core and refer to "Kestrel" in your question.您用aspnet-core标记了您的问题,并在您的问题中引用了“Kestrel”。 However the code you demonstrated shows a pretty basic Generic Host and not a web application.但是,您演示的代码显示了一个非常基本的通用主机,而不是web 应用程序。 If this really is a web application then you would add the Serilog.AspNetCore package instead.如果这确实是 web 应用程序,那么您将添加Serilog.AspNetCore package That package implicitly references Serilog.Extensions.Hosting and includes some other bits and pieces for use from within a web application. package 隐式引用Serilog.Extensions.Hosting并包括在 web 应用程序中使用的其他一些零碎。

A couple of things I've seen when working with serilog(I apologize if they are mentioned above and I missed them).我在使用 serilog 时看到的几件事(如果上面提到了它们,我很抱歉,我错过了它们)。

The AppSettings will override one another if you have several per environment.如果每个环境有多个 AppSettings 将相互覆盖。 Sometimes depending on how you are logging your output you may want to consider changing the logging level.有时,根据您记录 output 的方式,您可能需要考虑更改记录级别。 Debug or Verbose调试或详细

One last thing is in your worker, instead of the ms logging extension switch it to using serilog, that should cause your logging to have to be done using _log.Information("SampleEntry") which is serilogs pipe最后一件事是在您的工作人员中,而不是将 ms 日志记录扩展切换为使用 serilog,这应该会导致您的日志记录必须使用 _log.Information("SampleEntry") 完成,即 serilogs pipe

And as mentioned above in the appsetting you'll want to have "Using": [ "Serilog.Sinks.File"] and maybe even "Serilog.Settings.Configuration" for custom config stuff正如上面在应用程序设置中提到的,您需要“使用”:[“Serilog.Sinks.File”],甚至可能有“Serilog.Settings.Configuration”用于自定义配置内容

For me, I was having a similar issue where my log file was not being written to in my.Net 5 application.对我来说,我遇到了类似的问题,我的日志文件没有被写入 my.Net 5 应用程序中。 As @pinkfloydx33 asked several times above, are you publishing this application as a single file application?正如@pinkfloydx33 上面多次询问的那样,您是否将此应用程序作为单文件应用程序发布? In my case, I am doing so.就我而言,我正在这样做。 In the link he shared and the reason he was asking, is because there is something specific you need to do in.Net 5 single file applications and that is the "Using" statement in your appsettings.json.在他分享的链接和他问的原因中,因为您需要在.Net 5 单文件应用程序中执行某些特定操作,那就是您的 appsettings.json 中的“使用”语句。 .Net 5 single file applications cannot resolve the namespaces for you so you must specify them in the "Using" statement. .Net 5 单文件应用程序无法为您解析命名空间,因此您必须在“Using”语句中指定它们。

Here is the article he shared: Serilog configuration这是他分享的文章: Serilog 配置

Once I simply added my using for "Serilog.Sinks.File" to my appsettings.json, my logger started writing to the file.一旦我简单地将我对“Serilog.Sinks.File”的使用添加到我的 appsettings.json,我的记录器就开始写入该文件。

Hope this helps somebody.希望这可以帮助某人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM