我可以使用 Serilog 登录到单独的文件吗?

lon*_*nix 8 c# serilog asp.net-core

我的 ASP.NET Core 2.1 应用程序登录到 Serilog 文件接收器,所有“常见的东西”——即与应用程序相关的东西,如调试、监控、性能等。

但是,我们还需要将其他数据记录到单独的文件中。与应用程序无关,但与客户相关 - 应该进入数据库的那种东西。但是由于遗留原因,该系统上没有数据库,因此需要将数据保存到文件中。显然这不能写入同一个日志文件。

我可以只写一个FileStream. 但我更喜欢使用 Serilog 进行结构化日志记录。

那么有没有办法同时拥有两个记录器?将不同的数据记录到不同的文件接收器。

(如果是这样,我如何将它们注入我的类 - 现在我只注入ILogger<ClassName>.)

Nic*_*rdt 7

Serilog.Sinks.Map执行此操作,并包含一个文件日志记录示例:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Map("EventId", "Other", (name, wt) => wt.File($"./logs/log-{name}.txt"))
    .CreateLogger();
Run Code Online (Sandbox Code Playgroud)


Chr*_*ens 6

我设法做到这一点的最简单方法是实现一个新的独特接口,我可以将其传递给控制器​​使用的 DI 系统。
注意:在示例中我使用了Serilog.Sinks.RollingFileNuGet 包。使用您认为合适的任何其他水槽。我使用asp.net Core 2.1。

新界面

using Serilog;
using Serilog.Core;

public interface ICustomLogger
{
    ILogger Log { get; }
}

public class CustomLogger : ICustomLogger
{
    private readonly Logger _logger;

    public ILogger Log { get { return _logger; } }

    public CustomLogger( Logger logger )
    {
        _logger = logger;
    }
}
Run Code Online (Sandbox Code Playgroud)

在 Startup.cs 中的实现

using Serilog;
...
public void ConfigureServices( IServiceCollection services )
{
    ...

    ICustomLogger customLogger = new CustomLogger( new LoggerConfiguration()
        .MinimumLevel.Debug()
        .WriteTo.RollingFile( @"Logs\CustomLog.{Date}.log", retainedFileCountLimit: 7 )
        .CreateLogger() );
    services.AddSingleton( customLogger );

    ...
}
Run Code Online (Sandbox Code Playgroud)

在控制器中的使用

public class MyTestController : Controller
{
    private readonly ICustomLogger _customLogger;

    public MyTestController( ICustomLogger customLogger )
    {
        _customLogger = customLogger;
    }

    public IActionResult Index()
    {
        ...
        _customLogger.Log.Debug( "Serving Index" );
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)


dot*_*tep 4

你绝对可以做到。

  1. 您需要导入包Serilog.Sinks.File

  2. 然后你必须配置 Serilog。

    在program.cs中做以下事情。

    Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
            .Enrich.FromLogContext()
        .WriteTo.File(
            @"<<your log file path>>",
        fileSizeLimitBytes: 10000000,
        rollOnFileSizeLimit: true,
        shared: true,
        flushToDiskInterval: TimeSpan.FromSeconds(1))
            .CreateLogger();
    
    Run Code Online (Sandbox Code Playgroud)

在 buildWebHost 函数中添加 UseSerilog()。

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
        .UseSerilog() // <-- Add this line
        .Build();
Run Code Online (Sandbox Code Playgroud)

更新1

我使用了 EventId 属性。这只是演示如何根据 eventId 使用不同的文件,但根据您的要求,您必须实现自己的其他功能。

程序.cs

public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .WriteTo.Logger(cc => cc.Filter.ByIncludingOnly(WithProperty("EventId",1001)).WriteTo.File("Test1001.txt",flushToDiskInterval: TimeSpan.FromSeconds(1)))
                .WriteTo.Logger(cc => cc.Filter.ByIncludingOnly(WithProperty("EventId", 2001)).WriteTo.File("Test2001.txt", flushToDiskInterval: TimeSpan.FromSeconds(1)))
                .CreateLogger();

            CreateWebHostBuilder(args).Build().Run();
        }

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

        public static Func<LogEvent, bool> WithProperty(string propertyName, object scalarValue)
        {
            if (propertyName == null) throw new ArgumentNullException("propertyName");           
            ScalarValue scalar = new ScalarValue(scalarValue);
            return e=>
            {
                LogEventPropertyValue propertyValue;
                if (e.Properties.TryGetValue(propertyName, out propertyValue))
                {
                    var stValue = propertyValue as StructureValue;
                    if (stValue != null)
                    {
                        var value = stValue.Properties.Where(cc => cc.Name == "Id").FirstOrDefault();
                        bool result = scalar.Equals(value.Value);
                        return result;
                    }
                }
                return false;
            };
        }
    }
Run Code Online (Sandbox Code Playgroud)

我的 HomeController.cs

  public class HomeController : Controller
    {
        ILogger<HomeController> logger;
        public HomeController(ILogger<HomeController> logger)
        {
            this.logger = logger;
        }
        public IActionResult Index()
        {
            logger.Log(LogLevel.Information,new EventId(1001), "This is test 1");
            logger.Log(LogLevel.Information, new EventId(2001), "This is test 2");
            return View();
        } 
    }
Run Code Online (Sandbox Code Playgroud)

注意:最主要的是你必须使用某种类型的过滤器。