Serilog 记录日志
Serilog 记录日志
Serilog是.net里面非常不错的记录日志的库,另外一个我认为比较好的Log库是NLog。
在我个人的asp.net web api 2 基础框架(Github地址)里,我原来使用的是NLog,但是由于好奇心,我决定使用Serilog代替Nlog。
安装:
首先安装 Serilog,通过Package Manager Console或者Nuget管理窗口进行安装:
PM> Install-Package Serilog
然后安装 Serilog的Sinks,所谓Sink就是记录Log的途径,比如在控制台输出,在Debug窗口输出,输出到文件,输出到数据库等等。
这里有一个列表,列出了所有的Sink:https://github.com/serilog/serilog/wiki/Provided-Sinks
由于我使用的是asp.net web api 2.2 (.Net Framework 4.6+),所以我的项目里面暂时不需要用到Console,所以不安装官方教程的Serilog.Sinks.Literate。
但是我需要在VS的Debug窗口显示Log,所以安装Serilog.Sinks.Debug
通过Package Manager Console或者Nuget管理窗口进行安装:
PM> Install-Package Serilog.Sinks.Debug
我还需要输出到文件和Sql Server数据库,所以再安装Serilog.Sinks.RollingFile 和 Serilog.Sinks.MSSqlServer
通过Package Manager Console或者Nuget管理窗口进行安装:
PM> Install-Package Serilog.Sinks.RollingFile
PM> Install-Package Serilog.Sinks.MSSqlServer
这些都安装完了之后,我们开始配置。
配置:
在Web项目里,我建立了一个配置类:

public class SerilogConfiguration
{
public static void CreateLogger()
{
// 这一部分是配置Sql Server的Sink
const string connectionString = AppSettings.DefaultConnection; // 数据库连接字符串
const string tableName = "Logs"; // 表名
var columnOptions = new ColumnOptions // 自定义字段
{
AdditionalDataColumns = new Collection<DataColumn>
{
new DataColumn {DataType = typeof (string), ColumnName = "User"},
new DataColumn {DataType = typeof (string), ColumnName = "Class"},
}
};
// Sql Server的表中加入Json格式Log Event的数据字段
columnOptions.Store.Add(StandardColumn.LogEvent);
// 输出模板,Sql Server不能用这个
const string outputTemplate = "[{Timestamp:HH:mm:ss.FFF} {Level}] {Message} ({SourceContext:l}){NewLine}{Exception}";
Serilog.Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose() // 所有Sink的最小记录级别
.Enrich.WithProperty("SourceContext", null) //加入属性SourceContext,也就运行时是调用Logger的具体类
.Enrich.FromLogContext() //动态加入属性,主要是针对上面的自定义字段User和Class,当然也可以随时加入别的属性。
.WriteTo.Debug(
outputTemplate: outputTemplate) // 写到VS Output 窗口
.WriteTo.RollingFile("logs\\{Date}.log", shared: true, restrictedToMinimumLevel: LogEventLevel.Debug,
outputTemplate: outputTemplate) // 写到文件,每天一个,最小记录级别是Debug,文件格式是 yyyyMMdd.log
// 记录到Sql Server,最小级别是Information
.WriteTo.MSSqlServer(connectionString, tableName, columnOptions: columnOptions, autoCreateSqlTable: true, restrictedToMinimumLevel: LogEventLevel.Information)
.CreateLogger();
}
}

配置创建完之后赋值给Serilog.Log.Logger,它是一个静态变量。
要在进行IOC配置之前调用这个配置类。
注意,记录到Sql server那行配置,我设定的是自动创建表autoCreateSqlTable: true,但是如果创建后,这部分配置(Sql Server Sink)有更改,就需要把生成的表删掉,再让它重新自动建立一个,否则就无法再记录到Sql Server里面了。
Serilog的级别一共有6个,Verbose - Debug - Information - Warning - Error - Fatal,详见其文档。
配置IOC
因为我的框架都是使用依赖注入模式的,所以Serilog配置完之后,我们要进行IOC的配置,我使用的是Autofac(非常好的库),它可以自动Dispose配置的类,如果这个类实现了IDisposable接口的话,例如Serilog。
首先安装Serilog的Autofac集成库:
PM> Install-Package AutofacSerilogIntegration
然后到AutofacWebapiConfig.cs进行配置:
builder.RegisterLogger(autowireProperties: true);
非常的简单,就一句话。
依赖注入
配置完IOC,我们可以注入Serilog的ILogger进行使用,我们把它注入到Service层的CommonService里而不是所有的Controller里,这样就不用改太多代码。

namespace LegacyApplication.Services.Core
{
public interface ICommonService
{
IUploadedFileRepository UploadedFileRepository { get; }
IDepartmentRepository DepartmentRepository { get; }
ILogger Log { get; }
} public class CommonService : ICommonService
{
public IUploadedFileRepository UploadedFileRepository { get; }
public IDepartmentRepository DepartmentRepository { get; }
public ILogger Log { get; } public CommonService(
IUploadedFileRepository uploadedFileRepository,
IDepartmentRepository departmentRepository,
ILogger log)
{
UploadedFileRepository = uploadedFileRepository;
DepartmentRepository = departmentRepository;
Log = log;
}
}
}

然后在所有Controller的父类里,就可以获取到ILogger了。
在这个Controller父类(ApiControllerBase.cs)里,继续封装一些Log的方法,以便所有的派生Controller可以简单的使用:

#region Logging
[NonAction]
protected void LogByLevel(LogEventLevel level, string msg)
{
using (LogContext.PushProperty("Class", GetType().FullName)) // 对应于自定义的字段,对Sql server起作用, IDisposable
using (LogContext.PushProperty("User", CurrentUserName))
{
Log.Write(level, $"{msg} (by {CurrentUserName}, at {Now:yyyy-MM-dd HH:mm:ss.FFF})");
}
}
[NonAction]
protected void LogVerbose(string msg)
{
LogByLevel(LogEventLevel.Verbose, msg);
}
[NonAction]
protected void LogDebug(string msg)
{
LogByLevel(LogEventLevel.Debug, msg);
}
[NonAction]
protected void LogInformation(string msg)
{
LogByLevel(LogEventLevel.Information, msg);
}
[NonAction]
protected void LogWarning(string msg)
{
LogByLevel(LogEventLevel.Warning, msg);
}
[NonAction]
protected void LogError(string msg)
{
LogByLevel(LogEventLevel.Error, msg);
}
[NonAction]
protected void LogFatal(string msg)
{
LogByLevel(LogEventLevel.Fatal, msg);
}
#endregion

其中:
using (LogContext.PushProperty("Class", GetType().FullName))
using (LogContext.PushProperty("User", CurrentUserName))
这部分是针对Serilog的Sql Server配置的自定义字段部分。
全局异常记录
针对asp.net web api 2,我使用了自定义的全局异常记录类:MyExceptionLogger.cs
GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new MyExceptionLogger());
GlobalConfiguration.Configuration.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());

namespace LegacyStandalone.Web.MyConfigurations.Exceptions
{
public class MyExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
#if DEBUG
Trace.TraceError(context.ExceptionContext.Exception.ToString());
#endif
using (LogContext.PushProperty("Class",
context.ExceptionContext.ControllerContext.ControllerDescriptor.ControllerType))
using (LogContext.PushProperty("User",
context.RequestContext.Principal.Identity.Name))
{
LogException(context.ExceptionContext.Exception);
}
} private void LogException(Exception ex)
{
if (ex != null)
{
LogException(ex.InnerException);
Serilog.Log.Logger.Error(ex.ToString());
}
}
}
}

在这里我使用的是静态版本的Serilog的Logger。
问题
经使用测试,输出到Debug窗口和Sql Server数据库是没有问题的,但是在asp.net web api 2项目的开发环境里一直无法输出到文件,我新建立了一个web api项目也是如此,但是在控制台应用却没有问题,今天晚些时候我将继续研究并解决这个问题。
Serilog 记录日志的更多相关文章
- 在asp.net web api 2 使用 Serilog 记录日志
Serilog是.net里面非常不错的记录日志的库,另外一个我认为比较好的Log库是NLog. 在我个人的asp.net web api 2 基础框架(Github地址)里,我原来使用的是NLog,但 ...
- 在asp.net web api 2 (ioc autofac) 使用 Serilog 记录日志
Serilog是.net里面非常不错的记录日志的库,另外一个我认为比较好的Log库是NLog. 在我个人的asp.net web api 2 基础框架(Github地址)里,我原来使用的是NLog,但 ...
- ASP.NET Core 3.1使用log4net/nlog/Serilog记录日志
Serilog中的结构化日志支持非常好,而且配置简便.我能够比其他任何人更轻松地启动和运行Seirlog.Serilog中的日志可以发送到很多目的地.Serilog称这些东西为"接收器&qu ...
- [AspNetCore3.1] 使用Serilog记录日志
用到的单词 Sink 接收器模块.输出方式.接收模块库.输出模块库 Diagnostic 诊断 Enricher 扩展器 embedded 嵌入式的 compact 紧凑的.简洁的 concept 概 ...
- 在Winform项目和Web API的.NetCore项目中使用Serilog 来记录日志信息
在我们常规的调试或者测试的时候,喜欢把一些测试信息打印在控制台或者记录在文件中,对于.netframework项目来说,我们输出控制台的日志信息习惯的用Console.WriteLine来输出查看,不 ...
- .NET跨平台之旅:在Linux上将ASP.NET 5运行日志写入文件
在前一篇博文(增加文件日志功能遇到的挫折)中,我们遇到了这样一个问题:虽然有一些.NET日志组件(比如Serilog, NLog)已经开始支持.NET Core,但目前只支持控制台输出日志,不支持将日 ...
- .Net Core个人笔记
目录 前言 IOC注册 三种生命周期 如何注册一个IOC服务 .Net Core部署IIS之后500错误 管道和中间件 示意图 管道方法 中间件 加日志观看 使用MVC MVC服务注入 MVC管道调用 ...
- ABP 使用ElasticSearch、Kibana、Docker 进行日志收集
ABP 使用ElasticSearch.Kibana.Docker 进行日志收集 后续会根据公司使用的技术,进行技术整理分享,都是干货哦别忘了关注我!!! 最近领导想要我把项目日志进行一个统一收集,因 ...
- .NET Core的日志[1]:采用统一的模式记录日志
记录各种级别的日志是所有应用不可或缺的功能.关于日志记录的实现,我们有太多第三方框架可供选择,比如Log4Net.NLog.Loggr和Serilog 等,当然我们还可以选择微软原生的诊断框架(相关A ...
随机推荐
- 【uoj34】 多项式乘法
http://uoj.ac/problem/34 (题目链接) 题意 求两个多项式的乘积 Solution 挂个FFT板子. 细节 FFT因为要满足$n$是$2$的幂,所以注意数组大小. 代码 // ...
- 【洛谷P1126】机器人搬重物
题目大意:给定一个 N 行,M 列的地图,一个直径为 1.6 的圆形机器人需要从起点走到终点,每秒钟可以实现:向左转,向右转,向前 1-3 步.求从起点到终点最少要多长时间. 题解:相比于普通的走迷宫 ...
- 【codevs2205】等差数列
题目大意:给定一个长度为 N 的序列,求这个序列中等差数列的个数. 题解:根据题意应该是一道序列计数 dp.设 \(dp[i][j]\) 表示以第 i 项结尾,公差为 j 的等差数列的个数,则状态转移 ...
- Strassen矩阵乘法之思考
可不可以有另外的划分小矩阵的方法? A*B=C A/B分成n*m个矩阵 可看成一个多元方程. Ci,k = Ai,j * Bjk 每一个Ci,k看成方程的一个未知数 每一个小式子:对于A或B同一列/行 ...
- HDU 4280 ISAP+BFS 最大流 模板
Island Transport Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- mongoDB的使用(NodeJs)
MongoDB相信大家都不太陌生了,但是究竟它和我们熟悉的MySQL(MariaSQL).SQLServer有什么区别呢? 我们熟悉的MySQL是关系型数据,每个数据表都有严格的数据结构规定,因而我们 ...
- 实现vue2.0响应式的基本思路
最近看了vue2.0源码关于响应式的实现,以下博文将通过简单的代码还原vue2.0关于响应式的实现思路. 注意,这里只是实现思路的还原,对于里面各种细节的实现,比如说数组里面数据的操作的监听,以及对象 ...
- fastJson顺序遍历JSON字段(转)
fastJson在把json格式的字符串转换成JSONObject的时候,使用的是HashMap,所以排序规则是根据HASH值排序的,如果想要按照字符串顺序遍历JSON属性,需要在转换的时候指定使用L ...
- bzoj千题计划201:bzoj1820: [JSOI2010]Express Service 快递服务
http://www.lydsy.com/JudgeOnline/problem.php?id=1820 很容易想到dp[i][a][b][c] 到第i个收件地点,三个司机分别在a,b,c 收件地点的 ...
- HDU 1730 类NIM模型
两者间的间距就是可取石子数,因为对于行内黑白相连的局面该子游戏已经结束了因为此时不管先手再怎么移都是必败,SG=0的终止态 /** @Date : 2017-10-14 21:46:21 * @Fil ...