一、.net mvc
serilog在mvc中配置比较简单,配置好后在项目入口处初始化一下就可以使用。
引入的包:多数情况下,sinks选择输出到文件或者数据库。具体的sinks可查看官网:https://github.com/serilog/serilog/wiki/Provided-Sinks
Serilog
//控制台输出
Serilog.Sinks.Console
//发送邮件
Serilog.Sinks.Email
//将日志写入到文件
Serilog.Sinks.File
//推送日志至数据库
Serilog.Sinks.MssqlServer
- 首先创建一个类,用来自定义配置serilog的消息模板、输出位置等
public class LogLevel
{
//增根据actionName分类存储日志
public static void InitLoggerDefaultWithName(string actionName)
{
string LogFilePath(string LogEvent) => System.Web.Hosting.HostingEnvironment.MapPath($@"~/LogLevel/{LogEvent}/{actionName}.log");
string SerilogOutputTemplate =
"{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" + $@"{actionName}" +
new string('-', 50);
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Debug() // 所有Sink的最小记录级别
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.File(LogFilePath("Debug"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(
LogFilePath("Information"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(
LogFilePath("Warning"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.File(LogFilePath("Error"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.File(LogFilePath("Fatal"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.CreateLogger();
}
public static void InitLoggerDefault()
{
string LogFilePath(string LogEvent) => System.Web.Hosting.HostingEnvironment.MapPath($@"~/LogLevel/{LogEvent}/log.log");
string SerilogOutputTemplate =
"{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" +
new string('-', 50);
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Debug() // 所有Sink的最小记录级别
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.File(LogFilePath("Debug"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(
LogFilePath("Information"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(
LogFilePath("Warning"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.File(LogFilePath("Error"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>
lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.File(LogFilePath("Fatal"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.CreateLogger();
}
}
- Global.aspx.cs中初始化
//初始化Serilog
LogLevel.InitLoggerDefaultWithName(MethodBase.GetCurrentMethod().Name);
- 使用的时候直接调用
Log.Information(msg, args)
。
二、.net core
.net core配置相对复杂一点,如果只有一个启动项,基本上配置与mvc相同。
引入的包:多数情况下,sinks选择输出到文件或者数据库。具体的sinks可查看官网:https://github.com/serilog/serilog/wiki/Provided-Sinks
Serilog.AspNetCore
//控制台输出
Serilog.Sinks.Console
//发送邮件
Serilog.Sinks.Email
//将日志写入到文件
Serilog.Sinks.File
//推送日志至数据库
Serilog.Sinks.MssqlServer
1.输出到控制台
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()//最小的记录等级
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)//对其他日志进行重写,除此之外,目前框架只有微软自带的日志组件
.WriteTo.Console()//输出到控制台
.CreateLogger();
Log.Information("info");
Log.Error("err");
CreateHostBuilder(args).Build().Run();
}
<font style="color:rgb(0, 0, 0);background-color:rgb(242, 244, 245);"> .WriteTo.Console(theme: SystemConsoleTheme.Colored)</font>
<font style="color:rgb(0, 0, 0);background-color:rgb(242, 244, 245);">.WriteTo.Console(theme: AnsiConsoleTheme.Code)</font>
.WriteTo.Console(theme: AnsiConsoleTheme.Code,
outputTemplate: "发生时间:{Timestamp: HH:mm:ss.fff} 事件级别:{Level} 详细信息:{Message}{NewLine}{Exception}")

"Serilog": {
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "发生时间:{Timestamp: HH:mm:ss.fff} 事件等级:{Level} 详细信息:{Message}{NewLine}{Exception}"
}
}
]
}
program.cs配置:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.ReadFrom.Configuration(new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build())
.CreateLogger();c
2.将日志写入到文件
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.ReadFrom.Configuration(new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build())
.WriteTo.File(Path.Combine("MyLogs", "log"), rollingInterval: RollingInterval.Day)//文件生成到当前路径 rollingInterval:RollingInterval.Day:按天生成文件
.CreateLogger();
"Serilog": {
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "发生时间:{Timestamp: HH:mm:ss.fff} 事件等级:{Level} 详细信息:{Message}{NewLine}{Exception}",
}
},
{
"Name": "File",
"Args": {
"path": "MyLogs/log.txt",
"rollingInterval": "Day",
"outputTemplate": "发生时间:{Timestamp: HH:mm:ss.fff} 事件等级:{Level} 详细信息:{Message}{NewLine}{Exception}"
}
}
]
}
将这句代码注释掉:.WriteTo.File(Path.Combine("MyLogs", "log"), rollingInterval: RollingInterval.Day)
。配置中有path。
3.将日志推送到数据库
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.ReadFrom.Configuration(new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build())
.WriteTo.MSSqlServer("Data Source=DESKTOP-4TU9A6M;Initial Catalog=CoreFrame;User ID=sa;Password=123456", "logs", autoCreateSqlTable: true, restrictedToMinimumLevel: LogEventLevel.Information)//从左至右四个参数分别是数据库连接字符串、表名、如果表不存在是否创建、最低等级。Serilog会默认创建一些列。
.CreateLogger();
4.发送邮件
如果对客户端授权码不熟悉的同学可移步此博客:https://www.cnblogs.com/zhangnever/p/11926020.html 发送成功!
.WriteTo.Email(new EmailConnectionInfo()
{
EmailSubject = "系统警告,请速速查看!",//邮件标题
FromEmail = "291***@qq.com",//发件人邮箱
MailServer = "smtp.qq.com",//smtp服务器地址
NetworkCredentials = new NetworkCredential("291***@qq.com", "###########"),//两个参数分别是发件人邮箱与客户端授权码
Port = 587,//端口号
ToEmail = "183***@163.com"//收件人
})

我们在用的时候可以直接在控制器中注入ILogger 例如微软的天气预报的控制器:
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.ReadFrom.Configuration(new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build())
.WriteTo.MSSqlServer("Data Source=DESKTOP-4TU9A6M;Initial Catalog=CoreFrame;User ID=sa;Password=123456", "logs", autoCreateSqlTable: true, restrictedToMinimumLevel: LogEventLevel.Information)//从左至右四个参数分别是数据库连接字符串、表名、如果表不存在是否创建、最低等级。Serilog会默认创建一些列。
.WriteTo.Email(new EmailConnectionInfo()
{
EmailSubject = "系统警告,请速速查看!",//邮件标题
FromEmail = "291***@qq.com",//发件人邮箱
MailServer = "smtp.qq.com",//smtp服务器地址
NetworkCredentials = new NetworkCredential("291***@qq.com", "###########"),//两个参数分别是发件人邮箱与客户端授权码
Port = 587,//端口号
ToEmail = "188***@163.com"//收件人
})
.CreateLogger();
Log.Information("info");
Log.Error("err");
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSerilog()//在宿主机启动的时候配置serilog,与微软ILogger进行整合
.UseStartup<Startup>();
});
}
最好配合过滤器一起使用,达到AOP的效果 请看此篇博客:https://www.yuque.com/schafferyy/net/yuqwge #### 5.个性化配置serilog 上述设计的都是最基本的配置信息,能用,但不是很好用。但是对于serilog的熟悉还是有帮助的,毕竟一步一个脚印嘛! 1. 基本配置类似于mvc,不同点在于增加了对于记录级别的重写:
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
} //直接在接口中使用: _logger.LogInformation("success");
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
csharp
public class LogConfig
{
//增根据actionName分类存储日志
public static void InitLoggerDefaultWithName(string actionName)
{
string LogFilePath(string LogEvent) => $@"D:/Logs/exam/{LogEvent}/{actionName}.log";
string SerilogOutputTemplate =
"{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" +
new string('-', 50);
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Information() // 所有Sink的最小记录级别
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(
LogFilePath("Information"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(
LogFilePath("Warning"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.File(
LogFilePath("Error"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.File(
LogFilePath("Fatal"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.CreateLogger();
}
public static void InitLoggerDefault()
{
string LogFilePath(string LogEvent) => $@"D:/Logs/exam/{LogEvent}/log.log";
string SerilogOutputTemplate =
"{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" +
new string('-', 50);
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Information() // 所有Sink的最小记录级别
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(
LogFilePath("Information"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(
LogFilePath("Warning"), rollingInterval: RollingInterval.Day,
outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.File(
LogFilePath("Error"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg =>lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.File(
LogFilePath("Fatal"),
rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.CreateLogger();
}
}
2. 在program.cs中初始化:
LogConfig.InitLoggerDefaultWithName(MethodBase.GetCurrentMethod().DeclaringType.Name);
- 还有一步就是与微软ILogger进行整合,在host后面,而不是在webBuilder后面:
return Host.CreateDefaultBuilder(args)
.UseSerilog()//在宿主机启动的时候配置serilog,与微软ILogger进行整合
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.Inject()
.UseStartup<Startup>();
});
- 使用:
Log.Information(msg, args)
。 - 设置请求管道:
如果日志中需要添加请求相关信息,可以在Startup.cs(用于配置中间件管道)中配置。RequestLoggingMiddleware被包含在Serilog.AspNetCore中,可以被用于为每个请求添加一个单一的“摘要”日志消息。如果您已经完成了上一节中的步骤,则添加这个中间件将变得很简单。在您的Startup类中,在您想要记录日志的位置使用UseSerilogRequestLogging()进行调用:
重要的是UseSerilogRequestLogging()调用应出现在诸如MVC之类的处理程序之前。 中间件不会对管道中出现在它之前的组件进行时间或日志记录。通过将UseSerilogRequestLogging()放在它们之后,可以将其用于从日志中排除杂乱的处理程序,例如UseStaticFiles()。 为了减少每个HTTP请求需要构造,传输和存储的日志事件的数量。 在同一事件上具有许多属性还可以使请求详细信息和其他数据的关联更加容易。 默认情况下,以下请求信息将作为属性添加:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSerilogRequestLogging(); // <-- Add this line
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
- 请求方法
- 请求路径
- 状态码
- 响应时间
与ASP.NET Core的中间件管道一样,顺序很重要。当请求到达RequestLoggingMiddleware中间件时,它将启动计时器,并将请求传递给后续中间件进行处理。当后面的中间件最终生成响应(或抛出异常),则响应通过中间件管道传递回到请求记录器,并在其中记录了结果并写入概要日志信息。 Serilog只能记录到达中间件的请求。在上面的例子中,我已经在StaticFilesMiddleware之后添加了RequestLoggingMiddleware 。因此如果请求被UseStaticFiles处理并使管道短路的话,日志将不会被记录。鉴于静态文件中间件非常嘈杂,而且通常这是人们期望的行为(静态文件进行短路,不需要进行记录),但是如果您也希望记录对静态文件的请求,则可以在管道中serilog中间件移动到更早的位置。 总结: 使用Serilog.AspNetCore的请求日志记录中间件来减少为每个ASP.NET Core请求生成的日志数,同时仍记录摘要数据。如果您已经在使用Serilog,则非常容易启用。只需在您的Startup.cs文件中调UseSerilogRequestLogging()。 当请求到达此中间件时,它将启动计时器。当后续的中间件生成响应(或引发异常)时,响应将通过中间件管道返回到请求记录器,记录器记录结果并编写摘要日志消息。 添加请求日志记录中间件之后,您可以过滤掉默认情况下在ASP.NET Core 3.0中生成的更多基础结构日志,而不会丢失有用的信息。
app.UseSerilogRequestLogging(options =>
{
// 自定义消息模板
options.MessageTemplate = "Handled {RequestPath}";
// 发出调试级别的事件,而不是默认事件
options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Debug;
//将其他属性附加到请求完成事件
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
};
});
具体请看:如何利用Serilog的RequestLogging来精简ASP.NET Core的日志输出。
了解更多可以查看:
https://github.com/serilog/serilog-aspnetcore https://github.com/mthamil/AspNetCore.Serilog.RequestLoggingMiddleware