【问题标题】:Serilog not writing to File (.net core 2.2)Serilog 不写入文件(.net core 2.2)
【发布时间】:2019-02-15 18:28:48
【问题描述】:

我正在编写一个使用 Serilog 的 Web 服务。我在获取要写出的文件时遇到问题(但控制台日志记录有效)。我注意到根据thisthis pages 的解释,当.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 窗口中什么都没有显示,并且在我的机器上运行服务时没有创建文件。

我是否遗漏了一些明显的东西?

【问题讨论】:

标签: c# logging .net-core serilog


【解决方案1】:

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

显然这会阻止 Serilog 正确知道要写入哪些 Sink。

这是我更正后的 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}。显然,如果您将滚动间隔设置为天,它会解决这个问题......

【讨论】:

    【解决方案2】:

    appsettings.Development.jsonappsettings.json中的覆盖设置

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

    我花了将近一个小时来摸索为什么没有将日志写入文件,后来才注意到我的appsettings.Development.json 中只有Console sink(实际上删除了appsettings.json 中的File sink !)。

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

    ASP.NET Core 3.1

    程序.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 Core 2.2

    程序.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
                  }
                }
              ]
            }
          }
        ]
      }
    }
    

    【讨论】:

    • 很高兴我及时发现了这个。我现在正在将 Serilog 添加到我的项目中
    • 您是否有任何有用的涵盖 Serilog 的链接?我想有个清晰的认识。另外,您是否在控制器中使用 Log.Debug 或 _log.Logger.Debug?
    • @C.Ikongo Log.Debug 可以。
    • 什么是只读的 ILogger _log;做,为什么我看到它在网上被大量使用?
    • @C.Ikongo 您应该为此提出一个新问题。这就是 SO 的工作原理。
    【解决方案3】:

    这是我更正后的 JSON 设置:

    Startup类中:

    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
                  }
                }
              ]
            }
          }
        ]
      }
    }
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • Serilog.Sinks.Async 仅在您使用异步接收器时才需要,老实说,无论如何都不应该异步完成日志记录。日志记录应该足够快,以至于它可以在单个当前线程上发生。长日志操作应发送到以发布-订阅方式处理的队列。
      猜你喜欢
      • 2022-10-24
      • 2019-05-19
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      • 2019-09-19
      • 2017-06-12
      • 1970-01-01
      相关资源
      最近更新 更多