与 .NET 的其他日志库不同,与日志消息一起传递的参数不会破坏性地呈现为文本格式。相反,它们被保存为结构化数据,可以以文档形式写入 NoSQL 数据存储。
var input = new { Latitude = 25, Longitude = 134 };
var time = 34;
log.Information("Processed {@SensorInput} in {TimeMS:000} ms.", input, time);
和一些老的日志类库相比(如log4net),在使用Serilog时,你需要做的就是最大改变就是思考日志事件[log events],而不是日志消息[log message],一条事件[event]由以下几个内容组成:
您可以将日志事件格式化为控制台的可读文本
11:33:01 [INF] Hello, Serilog!
或者,您可以将相同的事件格式化为JSON并将其发送到远程日志服务器:
json {"@t":"2017-11-20T11:33:01.22138","@m":"Hello, Serilog!"}
Serilog速度很快,但始终构建和记录详细的日志事件会浪费CPU,磁盘和网络资源。为了管理这个,Serilog事件被赋予了多种级别。对应的有一个Log.*()方法来对应各个级别。
大多数的日志也是这样5级,只是有的名称叫的不同(NLog第1级叫Trace,其它的一致),每一级别对应一个写Log的函数:
log.Verbose("verbose");
log.Information("info");
log.Debug("debug");
log.Warning("warning");
log.Error("err");
log.Fatal("fatal");
另外,ILogger对象还有一个Dispose方法,用于关闭日志对象。
在开发过程中,可能会打开调试级别的事件:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug() // <- Set the minimum level
.WriteTo.Console()
.CreateLogger();
// In a tight loop...
Log.Debug("Processing item {ItemNumber} of {ItemCount}", itemNumber, itemCount);
在生成环境中,通常关闭调试的日志,并将最小的日志级别设置成Information,以便只记录重要的事件,在这篇文档中可以获得有关Serilog Logger Lever的更多信息
Tip: Serilog has special handling for Exception objects; methods like Log.Error() take the exception as the first parameter, e.g. [ 提示:Serilog对Exception对象有特殊的处理;] Log.Error(ex, "Task {TaskName} was canceled", task). [ Log.Error(例如,“任务{任务名称}被取消”,任务)。] Don’t include exceptions in the log message itself. [ 不要在日志消息本身中包含异常。]
Serilog的输出对象称之为Sink(水槽),github上提供了大量的第三方的可用sinks,这里简单的列举几个常用的:
如果我们已经知道如何使用Serilog调用消息模板和enrichment结构化日志的两个支柱,那么第三个支柱就是隐式事件类型的概念。
结构化日志适合有效处理大量日志数据。关于大型日志流的一个有趣的观察是,真实产生的事件比编写日志语句代码块时要多的多
Log.Debug("Processing item {ItemNumber} of {ItemCount}", itemNumber, itemCount);
这意味着,尽管生成了许多独特的消息字符串,如"Processing item 31 of 4159",但由此日志记录语句生成的每个事件共享相同的消息模板,即"Processing item {ItemNumber} of {ItemCount}"
Serilog及其许多sinks 利用这一事实从根本上改进了查询和过滤日志事件的体验。如果消息模板与事件一起保存,则下面的过滤器可以立即从嘈杂的日志记录语句中排除成千上万的事件,从而更容易看到否则会被淹没的有趣事件:
@MessageTemplate <> 'Processing item {ItemNumber} of {ItemCount}'
反转也适用 - 放大事件类型可以从单个日志记录语句中查找所有事件
如何利用此功能取决于您存储和搜索日志的位置。接下来我们会看看细节。
Tip:字符串链接,C#内插字符串,以及其他技术手段来预格式化传递给Serilog的消息内容,会取消此功能。详细请看 How (not) to parameterize Serilog events

public void ConfigureServices(IServiceCollection services){
//使用serilog替换自带的log实现
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(Configuration)
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console(new RenderedCompactJsonFormatter())
.WriteTo.File(formatter: new CompactJsonFormatter(), "logs/mylog.log", rollingInterval: RollingInterval.Day)
.CreateLogger();
services.AddControllersWithViews();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseSerilog(dispose: true);
public class HomeController : Controller
{ //构造函数注入
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
_logger.LogInformation("我能成功");
return View();
}
}