Serilog 不写入文件(.net 核心 2.2)

Serilog not writing to File (.net core 2.2)

我正在编写一个使用 Serilog 的 Web 服务。我在写出文件时遇到问题(但控制台日志记录有效)。我注意到根据 this and this 页面的解释,当 .net core 2.0 出来时设置发生了变化。

但是,现在,我看不到 任何 日志记录(也许在过去,默认的 M$ 记录器实际上就是我所看到的)。

program.cs 的设置方式如下:

public class Program
    {
        public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
            .AddUserSecrets<Startup>()
            .Build();

        public static int Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(Configuration.GetSection("Serilog"))
                .CreateLogger();

            try
            {
                Log.Information("Starting webhost...");
                BuildWebHost(args).Run();
                return 0;
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Host terminated unexpectedly");
                return 1;
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                   .UseStartup<Startup>()
                   .UseConfiguration(Configuration)
                   .UseSerilog()
                   .Build();
    }

我的 appsettings.json 在根目录中有这个部分:

"Serilog": {
    "Using" : ["Serilog.Sinks.Console", "Serilog.Sinks.File"], 
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      },
      "Enrich" :  ["FromLogContext"],
      "WriteTo":  [
        {"Name": "Console" },
        {"Name": "Debug" },
        {"Name": "File", "Args":  {"path": "%LogDir%\sampleapp\log-{Date}.txt", "rollingInterval":  "Day", "shared": true }  }
      ] 
    },
    "Properties": {
      "Application": "sampleapp"
    }
  },

请注意,%LogDir% 是我机器上的一个环境变量,在其他应用程序中解析得很好。该路径已创建,并且 Logs 文件夹对此应用程序使用的凭据具有完全 RW 权限。

我这样调用日志...

    private readonly ILogger<PartnerController> _logger;
    private readonly IPartnerDao _partnerDao;

    public PartnerController(ILogger<PartnerController> logger, IPartnerDao partnerDao)
    {
        _logger = logger;
        _partnerDao = partnerDao;
    }

    [HttpGet]
    [Route("{titleCode}")]
    public async Task<IActionResult> Get(string titleCode)
    {
        _logger.LogInformation("Test logging");
    }

然而,ASP.NET Core Web Server window 中没有任何显示,当 运行 服务时,我的机器上没有创建文件。

我是不是遗漏了什么明显的东西?

原来我错误地从文档中复制了一些 JSON。很难说,但在最初的问题中,我实际上在 MinimumLevel 部分中嵌入了 EnrichWriteToProperties 部分。

显然这会阻止 Serilog 正确地知道要写入哪些接收器。

这是我更正的设置 JSON:

"Serilog": {
    "Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": ["FromLogContext"],
    "WriteTo": [
      { "Name": "Console" },
      { "Name": "Debug" },
      {
        "Name": "File",
        "Args": {
          "path": "%LogDir%\sampleapp\log-.txt",
          "rollingInterval": "Day",
          "shared": true
        }
      }
    ],
    "Properties": {
      "Application":  "sampleapp" 
    } 
  },

请注意,我还从文件名中删除了 {Date}。显然,如果您将滚动间隔设置为一天,它会解决这个问题....

appsettings.Development.json 覆盖appsettings.json

中的设置

我再说一遍,appsettings.Development.json 中的配置将 优先于 而不是 appsettings.json。我知道这听起来很明显,但我敢打赌将来有人会像我一样忽略这一点。

我花了将近一个小时挠头为什么没有日志被写入文件,后来才注意到我的 appsettings.Development.json 中只有 Console sink(有效地删除了我的 File 陷入 appsettings.json 啊!)。

这里是一个正确的配置示例(根据您的需要修改):

ASP.NET核心3.1

Program.cs

using Microsoft.AspNetCore.Hosting;
using Serilog;
using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog.Core;

namespace My.App
{
    public class Program
    {
        private static bool IsDevelopment =>
            Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";

        public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", false, true)
            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
            .AddEnvironmentVariables()
            .Build();

        public static Logger Logger { get; } = new LoggerConfiguration()
            .ReadFrom.Configuration(Configuration)
            .Enrich.FromLogContext()
            .CreateLogger();

        public static int Main(string[] args)
        {
            Log.Logger = Logger;

            try
            {
                Log.Information("Starting...");
                var host = CreateHostBuilder(args).Build();                      
                host.Run();                        
                return 0;
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Host terminated unexpectedly");
                return 1;
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            var host = Host.CreateDefaultBuilder(args)
                .UseSerilog()
                .UseServiceProviderFactory(
                    new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder
                        .UseContentRoot(Directory.GetCurrentDirectory())
                        .UseIISIntegration()
                        .UseStartup<Startup>();
                });

            return host;
        }
    }
}

ASP.NET核心2.2

Program.cs

public class Program
{
    public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
        .AddEnvironmentVariables()
        .Build();

    public static void Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(Configuration)
            .Enrich.FromLogContext()
            .CreateLogger();

        try
        {
            Log.Information("Starting...");
            CreateWebHostBuilder(args).Run();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IWebHost CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseSerilog()
            .Build();
}

appsettings.json

{  
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
  }
}

appsettings.Development.json

{
  "Serilog": {
    "WriteTo": [
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "Console"
            },
            {
              "Name": "Debug"
            },
            {
              "Name": "DiagnosticTrace"
            },
            {
              "Name": "File",
              "Args": {
                "path": "/home/log/api-log-.txt",
                "rollingInterval": "Day",
                "retainedFileCountLimit": 7,
                "buffered": true
              }
            }
          ]
        }
      }
    ]
  }
}

appsettings.Production.json

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information"
    },
    "WriteTo": [
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "ApplicationInsights",
              "Args": {
                "restrictedToMinimumLevel": "Information",
                "telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
              }
            },
            {
              "Name": "Email",
              "Args": {
                "EmailConnectionInfo": {
                  "EmailSubject": "PRODUCTION error logs",
                  "FromEmail": "xxxxxxx",
                  "ToEmail": "xxxxxxx",
                  "MailServer": "xxxx",
                  "NetworkCredentials": {
                    "username": "xxxxxx",
                    "password": "xxxxxx",
                    "domain": "xxxxx"
                  },
                  "Port": 25
                },
                "restrictedToMinimumLevel": "Error"
              }
            },
            {
              "Name": "File",
              "Args": {
                "path": "/home/log/api-log-.txt",
                "rollingInterval": "Day",
                "retainedFileCountLimit": 15,
                "buffered": true
              }
            }
          ]
        }
      }
    ]
  }
}

这是我更正的设置 JSON:

启动 class:

Log.Logger = new LoggerConfiguration()
                         .ReadFrom.Configuration(config)
                         .Enrich.With<EventTypeEnricher>()
                         .CreateLogger();

appsettings.json

{
  "Serilog": {
    "Using": [
      "Serilog.Sinks.Console",
      "Serilog.Sinks.Seq",
      "Serilog.Sinks.Async",
      "Serilog.Sinks.File",
      "Serilog.Sinks.Debug"
    ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [
      "FromLogContext",
      "WithMachineName"
    ],
    "Properties": {
      "ApplicationName": "AppSim Crawler"
    },
    "WriteTo": [
      {
        "Name": "Seq",
        "Args": {
          "serverUrl": "http://localhost:5341",
          "apiKey": "none"
        }
      },
      {
        "Name": "Debug",
        "Args": {
          "outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}"
        }
      },
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "Console",
              "Args": {
                "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
                "outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <c:[%COMPUTERNAME%]> <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}"
              }
            }
          ]
        }
      },
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "File",
              "Args": {
                "path": "C:/appsim/logs/appSimCrawler.log",
                "outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <s:[{SourceContext}]>  <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}",
                "rollingInterval": "Day",
                "retainedFileCountLimit": 30,
                "shared": true,
                "rollOnFileSizeLimit": true
              }
            }
          ]
        }
      }
    ]
  }
}

对我来说,serilog 没有写入日志文件,因为我缺少许多 nuget 包之一 (Serilog.Sinks.Async)。因此,除了确保您在 appsettings.json 中的配置是正确的 - 并且您为开发与生产使用了正确的文件外,还有:

我建议再次查看文档或教程,并确保添加说明中说明的每个 nuget 包。