简体   繁体   English

不能为 serilog 配置自定义接收器

[英]Сan't configure a custom sink for a serilog

I can't connect the custom sink to the logger via the configuration file.我无法通过配置文件将自定义接收器连接到记录器。 I tried under.Net 5 and.Net Core 3.1.我在.Net 5 和.Net Core 3.1 下试过。

I studied the documentation: https://github.com/serilog/serilog-settings-configuration#using-section-and-auto-discovery-of-configuration-assemblies我研究了文档: https://github.com/serilog/serilog-settings-configuration#using-section-and-auto-discovery-of-configuration-assemblies

I also saw responses to an identical request.我还看到了对相同请求的回复。 https://stackoverflow.com/a/50118486/13151982 https://stackoverflow.com/a/24922105/13151982 https://stackoverflow.com/a/50118486/13151982 https://stackoverflow.com/a/24922105/13151982

But for some reason, this does not work for me.但出于某种原因,这对我不起作用。

To reproduce the problem, I made a minimalistic application.为了重现这个问题,我制作了一个简约的应用程序。 Also does not work, as in my main project.也不起作用,就像在我的主要项目中一样。

SampleApp.csproj:示例应用程序.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
    <PackageReference Include="Serilog.Extensions.Hosting" Version="4.1.2" />
    <PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
  </ItemGroup>

  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

Simple custom sink:简单的定制水槽:

    public class SerilogCounterSink : ILogEventSink
    {
        private static int i = 0;

        public void Emit(LogEvent logEvent)
        {
            i++;
        }
    }

Configuration:配置:

var builder = new ConfigurationBuilder();
            ConfigSetup(builder);

            // defining Serilog configs
            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(builder.Build())
                .Enrich.FromLogContext()
                .WriteTo.Console()
                //.WriteTo.Sink(new SerilogCounterSink())  //works if uncomment this line
                .CreateLogger();
            
            // Initiated the denpendency injection container 
            var host = Host.CreateDefaultBuilder()
                        .ConfigureServices((context, services) => {
                            services.AddTransient<IDataService, DataService>();
                        })
                        .UseSerilog()
                        .Build();

Configuration via file:通过文件配置:

"Serilog": {
    "Using": [ "SampleApp" ],
    "WriteTo": [
      { "Name": "SerilogCounterSink" },
      { "Name": "Console" },
      {
        "Name": "File",
        "Args": { "path": "Logs/log.txt" }
      }
    ],
    "MinimalLevel": {
      "Default": "Information",
      "Override": {
        "System": "Warning",
        "Microsoft": "Information"
      }
    }
  }

I tried like this:我试过这样的:

    "WriteTo": [
      { "Name": "SampleApp.SerilogCounterSink" },

    "WriteTo": [
      { "Name": "SerilogCounter" },

    "WriteTo": [
      { "Name": "SampleApp.SerilogCounter" },

As a result, when writing结果,写的时候

_log.LogInformation("test");

I do not get into the SerilogCounterSink.Emit (put a breakpoint there).我没有进入 SerilogCounterSink.Emit(在那里放置一个断点)。 If i uncomment a line of code where a custom sink is added programmatically, then everything works - I get into the method.如果我取消注释以编程方式添加自定义接收器的代码行,那么一切正常 - 我进入该方法。

The Serilog configuration extension doesn't create instances of the sinks directly. Serilog 配置扩展不会直接创建接收器的实例。 All it does is to try to call a method .WriteTo.NameOfTheSinkYouDefinedInTheConfig() , if that exists - so for that to work, you need to provide this method yourself.它所做的只是尝试调用一个方法.WriteTo.NameOfTheSinkYouDefinedInTheConfig() ,如果存在的话——所以要让它起作用,你需要自己提供这个方法。

If you look at the source code of any of the official sinks, you'll notice that they are always declared as internal classes rather than public classes, and the way to hook sinks into the Serilog configuration is by creating an extension method to the LoggerSinkConfiguration class where you instantiate the sink yourself and add it to the pipeline.如果你查看任何官方接收器的源代码,你会注意到它们总是被声明为internal类而不是public类,将接收器挂接到 Serilog 配置的方法是通过创建LoggerSinkConfiguration的扩展方法class 您自己实例化接收器并将其添加到管道中的位置。

In your case, it would be something like this:在您的情况下,它将是这样的:

public static class SerilogCounterLoggerConfigurationExtensions
{
    public static LoggerConfiguration SerilogCounterSink(
        this LoggerSinkConfiguration sinkConfiguration)
    {
        return sinkConfiguration.Sink(new SerilogCounterSink(), LevelAlias.Minimum,
            levelSwitch: null);
    }
}

Now that the extension method is available, the configuration extension will be able to call it the same way you would do in code:现在扩展方法可用了,配置扩展将能够像在代码中那样调用它:

Log.Logger = new LoggerConfiguration()
    .WriteTo.SerilogCounterSink() // <<<<<<<<<<<<<<
    .CreateLogger();

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

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