asp.net core系列 73 Exceptionless+Nlog以及Apollo介绍
一. 介绍
在一上篇中介绍了exceptionless的基本使用,这篇主要讲exceptionless结合nlog的实现双重日志记录,包括exceptionles的ui可视化日志以及nlog的txt文件日志。再是从apollo配置中心读取配置文件,当系统越庞大越多时,需要配置的参数也越来越多,可以通过使用apollo配置中心来统一管理,例如:配置数据库连接地址、exceptionless的对应项目的apikey值,redis连接地址等等所有可配置的参数。
1.1 asp.net core中apollo配置
打开asp.net core 项目,删除appsettings.json文件默认内容,在添加配置如下所示:
{ "apollo": { "appid": "100001", "metaserver": "http://192.168.0.100:8080/", "env": "dev", "meta": { "dev": "http://192.168.0.100:8080/", "fat": "http://192.168.0.100:8080/", "uat": "http://192.168.0.100:8080/", "pro": "http://192.168.0.100:8080/" } } }
appsettings.json配置对应的apollo客户端配置中心如下,这里端口8070是apollo客户端配置界面。端口8080是.net core程序读取apollo配置地址。apollo配置中参数都是以key-value的形式存储。
下面是读取apollo配置文件的关键代码:
安装包如下:
install-package microsoft.extensions.configuration -version 2.2.0 install-package com.ctrip.framework.apollo.configuration -version 2.0.3
private static iconfigurationroot _root = null; /// <summary> /// 获取apollo的config /// </summary> /// <returns></returns> public static iconfigurationroot getroot() { if (_root != null) { return _root; } //先获取appsettings.json的配置 var config = new configurationbuilder() .setbasepath(directory.getcurrentdirectory()) .addjsonfile("appsettings.json") .build(); //连接apollo string appid = config.getsection("apollo").getsection("appid").value; string metaserver = config.getsection("apollo").getsection("metaserver").value; var configuration = new configurationbuilder() .addapollo(appid, metaserver) // .adddefault(configfileformat.xml) // .adddefault(configfileformat.json) // .adddefault(configfileformat.yml) // .adddefault(configfileformat.yaml) .adddefault().addnamespace("application") .build(); _root = configuration; return _root; }
注意:如果变量configuration 中没有读取到apollo参数值,可以从configuration 对象的参数中查找返回的异常信息。如果读取成功会缓存一份文件到本地,如下所示:
//下面是从apollo(appid:100001)的配置中心获取key为“apikey”的value值: string apikey = getroot().getsection("apikey").value;
关于apollo更多资料,包括apollo服务端部署,参考官方文档:
1.2 nlog结合exceptionles
安装包如下:
install-package exceptionless.nlog install-package nlog.web.aspnetcore
在nlog的基础上,结合exceptionles,关键代码如下
(也可尝试通过配置文件实现 https://github.com/exceptionless/exceptionless.net/tree/master/src/platforms/exceptionless.nlog):
/// <summary> /// 返回nlog.logger /// </summary> /// <returns></returns> public logger getexceptionlesslogger() { var config = new loggingconfiguration(); var exceptionlesstarget = new exceptionlesstarget(); //读取apploo的exceptionless配置参数 string apikey = confighelper.getroot().getsection("apikey").value; string serverurl = confighelper.getroot().getsection("serverurl")?.value; exceptionlesstarget.apikey = apikey; exceptionlesstarget.serverurl = serverurl; exceptionlesstarget.layout = "${longdate} | ${callsite} | ${level} | ${message}"; exceptionlesstarget.name = "exceptionless"; //添加exceptionless的target对象 config.addtarget("exceptionless", exceptionlesstarget); config.loggingrules.add(new loggingrule("*", global::nlog.loglevel.error, exceptionlesstarget)); logmanager.configuration = config; return logmanager.getcurrentclasslogger(); } /// <summary> /// nlog.logger对象 /// </summary> private logger _logger { get { return n.nlogbuilder.configurenlog("config\\nlog.config").getcurrentclasslogger(); } } /// <summary> /// 带有exceptionless的nlog.logger对象 /// </summary> private logger _exceptionlesslogger { get { exceptionlesshelper helper = new exceptionlesshelper(); return helper.getexceptionlesslogger(); } }
//记录错误日志 public void error<t>(iformatprovider formatprovider, t value) { _logger.error(formatprovider, value); _exceptionlesslogger.error(formatprovider, value); }
二. nlog结合exceptionles代码优化
在1.2中介绍了二种日志的结合,下面把1.2的代码进行优化改造,主要包括:
(1) 去掉nlog的配置文件,使用编码来处理
(2) 记录日志时,只需要一个_logger.error,就能同时记录到txt文件和exceptionless中。
/// <summary> /// nlog.logger对象 /// </summary> private logger _logger { get { var config = new loggingconfiguration();// n.nlogbuilder.configurenlog("config\\nlog.config"); //添加exceptionless日志文件 var exceptionlesstarget = getexceptionlesstarget(); config.addtarget("exceptionless", exceptionlesstarget); config.addrule(loglevel.debug, loglevel.fatal, exceptionlesstarget); //添加txt日志文件 var logfile = new filetarget("logfile") { filename =string.format(@"c:\temp\{0}.log",datetime.now.tostring("yyyy-mm-dd")) }; logfile.layout = "${longdate}|${event-properties:item=eventid_id:whenempty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}"; config.addrule(loglevel.debug, loglevel.fatal, logfile); logmanager.configuration = config; return logmanager.getcurrentclasslogger(); } } /// <summary> /// 返回nlog target /// </summary> /// <returns></returns> public static exceptionlesstarget getexceptionlesstarget() { var exceptionlesstarget = new exceptionlesstarget(); //读取apploo配置的exceptionless地址 string apikey = confighelper.getroot().getsection("apikey").value; string serverurl = confighelper.getroot().getsection("serverurl")?.value; exceptionlesstarget.apikey = apikey; exceptionlesstarget.serverurl = serverurl; exceptionlesstarget.layout = "${longdate} | ${callsite} | ${level} | ${message}"; exceptionlesstarget.name = "exceptionless"; return exceptionlesstarget; } //记录日志 public void error(string message, exception exception) { _logger.error(exception, message); }
效果如下所示: