Serilog是.NET Core中常用的结构化日志类库,透过logging API可以轻松的记录应用程式中对象属性,方便快速进行logging内容进行查询与分析,并将其记录内容通过指定方式输出。

今天,介绍一个Nuget包​ ​Serilog.Expressions​ ​,它可以更容易地控制Serilog事件如何格式化输出。

功能介绍

Serilog.Expressions包含用于文本格式化的​ ​ExpressionTemplate​ ​​类。​ ​ExpressionTemplate​ ​​实现了​ ​ITextFormatter​ ​,因此它可以与任何基于文本的Serilog接收器一起工作,包括控制台、文件、调试窗口和电子邮件。

1.使用参数

ExpressionTemplate ​中可以使用下列参数:

  • SourceContext - ILogger< T > 中T对应的类型名
  • @t - 事件时间
  • @m - 格式化后的消息
  • @mt - 原始的消息模板
  • @l - 事件级别
  • @x - 异常
  • @p - 传入参数的字典
  • @i - 事件Id
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new ExpressionTemplate("[{@t:HH:mm:ss} {@l:u3} {SourceContext}] {@m}\n{@x}"))
.CreateLogger();
Log.Information("公众号“My IO”!");

使用表达式自定义Serilog输出格式_子字符串

2.使用函数

ExpressionTemplate ​中可以使用下列函数:

Function

Description

​Coalesce(p0, p1, [..pN])​

返回第一个定义的非空参数。

​Concat(s0, s1, [..sN])​

连接两个或多个字符串。

​Contains(s, t)​

测试字符串“s”是否包含子字符串“t”。

​ElementAt(x, i)​

按名称“i”检索“x”的属性,或按数字索引“i”检索“x”的数组元素。

​EndsWith(s, t)​

测试字符串“s”是否以子字符串“t”结尾。

​IndexOf(s, t)​

返回字符串“s”中子字符串“t”的第一个索引,如果子字符串未出现,则返回-1。

​IndexOfMatch(s, p)​

返回字符串“s”中正则表达式“p”的第一个匹配项的索引,如果正则表达式不匹配,则返回-1。

​IsMatch(s, p)​

测试正则表达式“p”是否与字符串“s”匹配。

​IsDefined(x)​

如果表达式“x”有值,包括“null”,则返回“true”;如果“x”未定义,则返回“false”。

​LastIndexOf(s, t)​

返回字符串“s”中子字符串“t”的最后一个索引,如果子字符串未出现,则返回-1。

​Length(x)​

返回字符串或数组的长度。

​Now()​

返回“DateTimeOffset.Now”。

​Rest()​

在“ExpressionTemplate”中,返回一个对象,该对象包含模板或事件消息中未引用的事件属性。

​Round(n, m)​

将数字“n”四舍五入到“m”小数位。

​StartsWith(s, t)​

测试字符串“s”是否以子字符串“t”开头。

​Substring(s, start, [length])​

返回从“start”到字符串结尾的字符串“s”的子字符串,或返回“length”字符的子字符串.

​TagOf(o)​

返回捕获对象的“TypeTag”字段。

​ToString(x, [format])​

将“x”转换为字符串,如果“x”是“IFormattable”,则应用格式字符串“format”。

​TypeOf(x)​

返回一个描述“x”类型的字符串:如果“x”是标量且非空,或是“array”、“object”、“dictionary”、“null”或“undefined”,则返回.NET类型名。

​Undefined()​

显式Undefined的值。

​UtcDateTime(x)​

将“DateTime”或“DateTimeOffset”转换为UTC“DateTime”。

Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new ExpressionTemplate("{IndexOf(@m,'My IO')}"))
.CreateLogger();
Log.Information("公众号“My IO”!");

使用表达式自定义Serilog输出格式_字符串_02

3.条件语句

可以使用​ ​{#if <表达式>}​ ​​和​ ​{#end}​ ​​有条件地显示输出。条件​ ​{#if}​ ​​也支持​ ​{#else if <表达式>}​ ​​和 ​ ​{#else}​ ​。例如,如果日志包含密码则不输出,避免泄露敏感数据:

Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new ExpressionTemplate("{#if @p['Password'] is not null } 不输出敏感数据 {#else} {@m} {#end}\n"))
.CreateLogger();

var user = new { Name = "张三", Password = "xxx" };
Log.Information("登录信息:{@Name} {@Password}", user.Name,user.Password);
Log.Information("登录信息:{@Name} ", user.Name);

使用表达式自定义Serilog输出格式_子字符串_03

4.循环

使用​ ​{#each}​ ​为@p这样的对象的所有成员重复执行。

Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new ExpressionTemplate("{#each name, value in @p} {name} = {value}\n{#end}"))
.CreateLogger();

var user = new { Name = "张三", Password = "xxx" };
Log.Information("登录信息:{@Name} {@Password}", user.Name,user.Password);

使用表达式自定义Serilog输出格式_子字符串_04

结论

这里只是介绍了​ ​Serilog.Expressions​ ​部分常用功能,更多内容可以去https://github.com/serilog/serilog-expressions了解。