为什么在软件设计中一定要有日志系统?
在软件设计中日志模块是必不可少的一部分,可以帮助开发人员更好的了解程序的运行情况,提高软件的可靠性,安全性和性能,日志通常能帮我们解决如下问题:
- 调试和故障排查:日志可以记录程序运行时的各种信息,包括错误,异常,警告等,方便开发人员在出现问题时进行调试和故障排查。
- 性能优化:日志可以记录程序的运行时间,资源占用等信息,帮助开发人员进行性能优化。
- 安全审计:日志可以记录用户的操作行为,方便进行安全审计和追踪。
- 统计分析:日志可以记录用户的访问情况,使用习惯等信息,方便进行统计分析和用户行为研究。
- 业务监控:日志可以记录业务数据的变化情况,方便进行业务监控和数据分析。
- 数据还原:日志记录每次请求的请求及响应数据,可以在数据丢失的情况下还原数据。
如何在.net6webapi中添加日志?
1.添加日志组件
.net6有自带的logging组件,还有很多优秀的开源log组件,如nlog,serilog,这里我们使用serilog组件来构建日志模块。
新建.net6,asp net web api项目之后,为其添加如下四个包
dotnet add package serilog.aspnetcore//核心包 dotnet add package serilog.formatting.compact dotnet add serilog.sinks.file//提供记录到文件 dotnet add serilog.sinks.mssqlserver//提供记录到sqlserver
2.新建serilogextend扩展类型,配置日志格式并注入
public static class serilogextend { public static void addserillog(this configurehostbuilder configurehostbuilder) { //输出模板 string outputtemplate = "{newline}【{level:u3}】{timestamp:yyyy-mm-dd hh:mm:ss.fff}" + "{newline}#msg#{message:lj}" + "{newline}#pro #{properties:j}" + "{newline}#exc#{exception}" + new string('-', 50); // 配置serilog log.logger = new loggerconfiguration() .minimumlevel.override("microsoft", logeventlevel.warning) // 排除microsoft的日志 .enrich.fromlogcontext() // 注册日志上下文 .writeto.console(outputtemplate: outputtemplate) // 输出到控制台 .writeto.mssqlserver("server=.;database=testdb;user id=sa;password=123;trustservercertificate=true", sinkoptions: getsqlserversinkoptions(), columnoptions: getcolumnoptions()) .writeto.logger(configure => configure // 输出到文件 .minimumlevel.debug() .writeto.file( //单个日志文件,总日志,所有日志存到这里面 $"logs\\log.txt", rollinginterval: rollinginterval.day, outputtemplate: outputtemplate) .writeto.file( //每天生成一个新的日志,按天来存日志 "logs\\{date}-log.txt", //定输出到滚动日志文件中,每天会创建一个新的日志,按天来存日志 retainedfilecountlimit: 7, outputtemplate: outputtemplate )) .createlogger(); configurehostbuilder.useserilog(log.logger); // 注册serilog /// <summary> /// 设置日志sqlserver配置 /// </summary> /// <returns></returns> mssqlserversinkoptions getsqlserversinkoptions() { var sqlsinkotpions = new mssqlserversinkoptions(); sqlsinkotpions.tablename = "sys_serilog";//表名称 sqlsinkotpions.schemaname = "dbo";//数据库模式 sqlsinkotpions.autocreatesqltable = true;//是否自动创建表 return sqlsinkotpions; } /// <summary> /// 设置日志sqlserver 列配置 /// </summary> /// <returns></returns> columnoptions getcolumnoptions() { var customcolumnoptions = new columnoptions(); customcolumnoptions.store.remove(standardcolumn.messagetemplate);//删除多余的这两列 customcolumnoptions.store.remove(standardcolumn.properties); var columlist = new list<sqlcolumn>(); columlist.add(new sqlcolumn("requestjson", sqldbtype.nvarchar, true, 2000));//添加一列,用于记录请求参数string columlist.add(new sqlcolumn("responsejson", sqldbtype.nvarchar, true, 2000));//添加一列,用于记录响应数据 customcolumnoptions.additionalcolumns = columlist; return customcolumnoptions; } } }
然后再program.cs中调用这个扩展方法
var builder = webapplication.createbuilder(args); // add services to the container. builder.services.addcontrollers(options => { options.filters.add(typeof(requestloggingfilter)); }); // learn more about configuring swagger/openapi at https://aka.ms/aspnetcore/swashbuckle builder.services.addendpointsapiexplorer(); builder.services.addswaggergen(); builder.host.addserillog(); var app = builder.build(); // configure the http request pipeline. if (app.environment.isdevelopment()) { app.useswagger(); app.useswaggerui(); } app.usehttpsredirection(); app.useauthorization(); app.mapcontrollers(); app.run();
这里我设计的日志信息只包括了
- message:日志信息
- level:等级
- timestamp:记录日志时间
- exception:异常信息
- requestjson:请求参数json
- responsejson:响应结果json
其中前面四种为日志默认,后两种为我主动添加,在实际的设计中还有可能有不同的信息,如:
- ip:请求日志
- action:请求方法
- token:请求token
- user:请求的用户
日志的设计应该根据实际的情况而来,其应做到足够详尽,能帮助开发者定位,解决问题,而又不能过于重复臃肿,白白占用系统空间,我这边的示例仅供大家参考
3.添加requestloggingfilter过滤器,用以记录每次请求的日志
public class requestloggingfilter : iactionfilter { private readonly serilog.ilogger _logger;//注入serilog private stopwatch _stopwatch;//统计程序耗时 public requestloggingfilter(serilog.ilogger logger) { _logger = logger; _stopwatch = stopwatch.startnew(); } public void onactionexecuted(actionexecutedcontext context) { _stopwatch.stop(); var request = context.httpcontext.request; var response = context.httpcontext.response; _logger .forcontext("requestjson",request.querystring)//请求字符串 .forcontext("responsejson", jsonconvert.serializeobject(context.result))//响应数据json .information("request {method} {path} responded {statuscode} in {elapsed:0.0000} ms",//message request.method, request.path, response.statuscode, _stopwatch.elapsed.totalmilliseconds); } public void onactionexecuting(actionexecutingcontext context) { } }
在program.cs中将该过滤器添加进所有控制器之中
builder.services.addcontrollers(options => { options.filters.add(typeof(requestloggingfilter)); }); // learn more about configuring swagger/openapi at https://aka.ms/aspnetcore/swashbuckle builder.services.addendpointsapiexplorer(); builder.services.addswaggergen(); builder.host.addserillog(); var app = builder.build(); // configure the http request pipeline. if (app.environment.isdevelopment()) { app.useswagger(); app.useswaggerui(); } app.usehttpsredirection(); app.useauthorization(); app.mapcontrollers(); app.run();
测试效果
在控制器添加一个测试方法并将其调用一次
[httpget] public dynamic get123(string model) { return new { name = "123", id = 2 }; }
控制台输出
数据库记录
项目根目录下logs文件夹中日志文件记录
到此这篇关于如何在.net6 web api中记录每次接口请求的日志的文章就介绍到这了,更多相关.net记录每次接口请求的日志内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论