lon*_*nix 8 c# serilog asp.net-core
我的 ASP.NET Core 2.1 应用程序登录到 Serilog 文件接收器,所有“常见的东西”——即与应用程序相关的东西,如调试、监控、性能等。
但是,我们还需要将其他数据记录到单独的文件中。与应用程序无关,但与客户相关 - 应该进入数据库的那种东西。但是由于遗留原因,该系统上没有数据库,因此需要将数据保存到文件中。显然这不能写入同一个日志文件。
我可以只写一个FileStream. 但我更喜欢使用 Serilog 进行结构化日志记录。
那么有没有办法同时拥有两个记录器?将不同的数据记录到不同的文件接收器。
(如果是这样,我如何将它们注入我的类 - 现在我只注入ILogger<ClassName>.)
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)
我设法做到这一点的最简单方法是实现一个新的独特接口,我可以将其传递给控制器使用的 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)
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)
你绝对可以做到。
您需要导入包Serilog.Sinks.File
然后你必须配置 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)
注意:最主要的是你必须使用某种类型的过滤器。