.net Core 和 Serilog 电子邮件接收器 - json 配置

.net Core and Serilog Email sink - json config

我正在使用 .net Core 2.0 和 Serilog 电子邮件接收器。我在使用 appsettings.json 配置电子邮件接收器时遇到问题。 program.cs 中的相同配置有效,而 appsetting.json 中的配置无效。

设置系统 (ReadFrom.Configuration()) 实际上只尝试调用它可以发现的方法和扩展方法,并传递来自配置文件

不幸的是,它暂时只支持basic类型(可转换to/fromstring和一些更具体的情况)因此,参数无法提供类型 EmailConnectionInfo

不过,作为一种解决方法,如果您只需要传递几个参数,您可以创建自己的扩展方法来接受您需要的参数并从配置系统中调用它。

对于您的情况,您需要执行以下操作:

首先,定义一个extension method EmailCustom(...)可以插入WriteTo(类型Serilog.Configuration.LoggerSinkConfiguration)和returns一个LoggerConfiguration.

这看起来像(未测试,没有使用等 :P):

namespace Serilog{
    public static class MyCustomExtensions
    {
        public static LoggerConfiguration EmailCustom(this LoggerSinkConfiguration sinkConfiguration, string param1, int param2, LogEventLevel restrictedToMinimumLevel){
            // the actual call to configure the Email sink, passing in complex parameters
            return sinkConfiguration.Email(... ... , restrictedToMinimumLevel , EmailConnectionInfo(){
            Foo = "bar",
            Baz = param1,
            Qux = param2,
            }
            );
        }
    }
}

从那时起,您应该能够编写如下 C# 代码:

new LoggerConfiguration()
    .WriteTo.EmailCustom(param1: "my param1", param2: 42)
   // ...
    .CreateLogger();

一旦你有了这个工作,你实际上可以在 json 中定义那个方法调用,感谢 Serilog.Settings.Configuration 在那种情况下,它看起来像

{
"Serilog": {
    "Using" : ["TheNameOfTheAssemblyThatContainsEmailCustom"],
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "EmailCustom",
        "Args": {
          "param1": "my param1",
          "param2": 42,
          "restrictedToMinimumLevel": "Verbose"
        }
      }]
    }
}

此策略也可以应用于 Serilog 的其他接收器和其他配置部分。


您可以在这里找到更多关于配置系统的信息:

对于像我这样难以理解字里行间事物的其他人,这里是使用 tsimbalar 提供的框架的完整答案,该框架用于使用 SendGrid 发送电子邮件的解决方案。

我将以下 class 添加到我项目的根目录 ("MyApp")。这从 ReadFrom.Configuration(configuration).CreateLogger(); 自动调用。由于应用程序设置中的 WriteTo EmailCustom。

using System;
using System.Net;
using Serilog;
using Serilog.Configuration;
using Serilog.Events;
using Serilog.Sinks.Email;

namespace TrackumApi
{
    public static class SerilogEmailExtension
    {
        public static LoggerConfiguration EmailCustom(this LoggerSinkConfiguration sinkConfiguration,
            string fromEmail,
            string toEmail,
            string enableSsl,
            string mailSubject,
            string isBodyHtml,
            string mailServer,
            string networkCredentialuserName,
            string networkCredentialpassword,
            string smtpPort,
            string outputTemplate,
            string batchPostingLimit,
            string periodMinutes,
            string restrictedToMinimumLevel)
        {
            return sinkConfiguration.Email(new EmailConnectionInfo
            {
                FromEmail = fromEmail,
                ToEmail = toEmail,
                EnableSsl = GetBoolean(enableSsl),
                EmailSubject = mailSubject,
                IsBodyHtml = GetBoolean(isBodyHtml),
                MailServer = mailServer,
                NetworkCredentials = new NetworkCredential(networkCredentialuserName, networkCredentialpassword),
                Port = GetInt(smtpPort)
            }, outputTemplate, GetLevel(restrictedToMinimumLevel), 
                GetInt(batchPostingLimit), TimeSpan.FromMinutes(GetInt(periodMinutes))
            );
        }

      //The system hated converting the string inputs inline so I added the conversion methods:

        private static int GetInt(string instring)
        {
            return int.TryParse(instring, out var result) ? result : 0;
        }

        private static bool GetBoolean(string instring)
        {
            return bool.TryParse(instring, out var result) && result;
        }

        private static LogEventLevel GetLevel(string restrictedtominimumlevel)
        {
            return Enum.TryParse(restrictedtominimumlevel, true,
                out LogEventLevel level) ? level : LogEventLevel.Warning;
        }
    }
}

在我的原始 post 中,我修改了我的 Program.cs 但事实证明这不是必需的。然而,在任何其他代码之前添加 Serilog.Debugging.SelfLog 仍然是无价的:

        Serilog.Debugging.SelfLog.Enable(Console.Out);
        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true)
            .Build();

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

最后我修改了 appsettings.json 如下(请原谅额外的内容,但我认为这也可能对某些人有所帮助):

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",

  "Serilog": {
    "Using": [ "Serilog", "Serilog.Sinks.Console", "Serilog.Sinks.File", "MyApp" ],
    "MinimumLevel": {
      "Default": "Verbose",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning",
        "Microsoft.AspNetCore.Authentication": "Information"
      }
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
          "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "C:\Temp\Logs\MyApp.log",
          "fileSizeLimitBytes": 1000000,
          "rollOnFileSizeLimit": "true",
          "shared": "true",
          "flushToDiskInterval": 3,
          "outputTemplate": "[{Timestamp:MM/dd/yy HH:mm:ss} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
          "restrictedToMinimumLevel": "Verbose"
        }
      },
      {
        "Name": "EmailCustom",
        "Args": {
          "fromEmail": "no-reply@mydomain.com",
          "toEmail": "me@mydomain.com",
          "enableSsl": false,
          "mailSubject": "MyApp Message",
          "isBodyHtml": true,
          "mailServer": "smtp.sendgrid.net",
          "networkCredentialuserName": "mysendgridusername",
          "networkCredentialpassword": "mysendgridpassword",
          "smtpPort": 587,
          "outputTemplate": "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}",
          "batchPostingLimit": 10,
          "periodMinutes": 5,
          "restrictedToMinimumLevel": "Verbose"
        }
      }
    ],
    "Enrich": [ "FromLogContext" ],
    "Properties": {
      "Application": "MyApp"
    }
  }

}

HTH!