手机版

详解 净核心中的日志组件(日志记录)

时间:2021-08-30 来源:互联网 编辑:宝哥软件园 浏览:

1、介绍

记录组件是微软实现的日志记录组件包括控制台(控制台)、调试(调试)、事件日志(事件日志)和TraceSource,但是没有实现最常用用的文件记录日志功能(可以用其他第三方的如NLog、Log4Net。之前写过股市分析使用的文章)。

2、默认配置

新建。网络核心网络应用编程接口项目,添加下面代码。

[路线(' API/[控制器]')]公共类值控制器:控制器{值控制器记录器;//构造函数注入记录器公共值控制器(iloggervalues控制器记录器){这。logger=logger}[HttpGet]public IEnumerablesting Get(){ logger .日志警告("警告");返回新字符串[] { 'value1 ',' value 2 ' };} }运行结果如下:

我刚开始接触的时候,我就有一个疑问我根本没有配置关于记录器的任何代码,仅仅写了注入,为什么会起作用呢?最后我发现其实是在程序类中使用了微软默认的配置。

公共类程序{公共静态void Main(字符串[]参数){ BuildWebHost(参数)} .run();}公共静态IWebHost BuildWebHost(字符串[]个参数)=WebHost .CreateDefaultBuilder(args)//在这里使用了默认配置UseStartupStartup().build();}下面为CreateDefaultBuilder方法的部分源码,整个源码在https://github.com/aspnet/MetaPackages,可以看出在使用模板创建项目的时候,默认添加了控制台和调试日志组件,并从appsettings.json中读取配置。

建筑商. usekesstrel((builder context,options)={ options .配置(builderContext .配置。GetSection('红隼');}) .ConfigureAppConfiguration((宿主上下文,config)={ var env=hostingContext .主机环境;//加载appsettings.json文件使用模板创建的项目,会生成一个配置文件,配置文件中包含记录的配置项配置AddJsonFile('appsettings.json ',optional: true,reloadOnChange: true).AddJsonFile($'appsettings .{env .环境名称}。json ',optional:为真,重新加载更改:为真);}) .配置日志记录((宿主上下文,日志记录)={ //从appsettings.json中获取记录的配置日志记录。添加配置(主机上下文。配置。GetSection('日志');//添加控制台输出日志记录AddConsole();//添加调试输出日志记录AddDebug();})3、建立自己的记录配置

首先修改程序类

公共类程序{公共静态void Main(字符串[]参数){ //指定配置文件路径var配置=新的ConfigurationBuilder().SetBasePath(目录. GetCurrentDirectory())//设置基础路径AddJsonFile($'appsettings.json ',true,true)//加载配置文件AddJsonFile($'appsettings .{环境名称.发展}。'' JSON ',真,真)。build();var host=new WebHostBuilder().UseKestrel().UseStartupStartup().UseContentRoot(目录. GetCurrentDirectory()).使用配置(配置)//使用配置. UseUrls(配置['AppSettings:Url'])//从配置中读取程序监听的端口号。使用环境(环境名称.发展)//如果加载了多个环境配置,可以设置使用哪个配置一般有测试环境、正式环境//.配置日志记录((主机上下文,日志记录)=//第一种配置方法直接在webHostBuilder建立时配置不需要修改下面的启动代码//{ //日志记录。添加配置(主机上下文。配置。GetSection('日志');//日志记录AddConsole();//}) .build();主持人run();} }修改启动类如下面,此类的执行顺序为启动构造函数配置服务配置

公共类启动{公共图标配置配置{获取;私有集;} public ihostingenvironment instance environment { get;私有集;} //在构造函数中注入IHostingEnvironment和图标配置,配置已经在程序中设置了,注入后就可以获取配置文件的数据公共启动(IHostingEnvironment env,图标配置配置){ HostingEnvironment=env配置=配置;} public void ConfigureServices(IServiceCollection services){ services .AddMvc();//第二种配置也可以这样加上日志功能,不用下面的注入//服务AddLogging(builder=//{//builder .添加配置(配置GetSection(' Logging ')//.AddConsole();//});} //注入ILoggerFactory公共无效配置(应用程序生成器应用程序,IHostingEnvironment env,ILoggerFactory logger factory){ if(env .IsDevelopment()) { app .usedeveloper异常页();} //第三种配置注入ILogggerFactory,然后配置参数//添加控制台输出伐木工厂。添加控制台(配置GetSection('日志');//添加调试输出伐木工厂AddDebug();应用程序.UseMvc();} }这种结构就比较清晰明了。

4、测井源码解析

三种配置其实都是为了注入日志相关的服务,但是调用的方法稍有不同。现在我们以第二种配置来详细看看其注入过程。首先调用添加日志记录方法,其实现源码如下:

公共静态IServiceCollection AddLogging(此为IServiceCollection服务,ActionILoggingBuilder配置){服务.AddOptions();//这里会注入最基础的5个服务选择权相关服务只要是跟配置文件相关,通过[计]选项服务获取相关配置文件参数参数服务。尝试添加(服务描述符.单线记录器工厂,loglerfactory());服务。尝试添加(服务描述符Singleton(类型为(ILogger),类型为(Logger));服务TryAddEnumerable(服务描述符.singletoniconfigureoptions sloggerfilteroptions(新的defaultloglerleveconfigureoptions(日志级别。信息)));配置(新的日志生成器(服务));退货服务;}接着会调用添加配置

公共静态ILoggingBuilder添加配置(此ILoggingBuilder生成器,图标配置配置){建设者.AddConfiguration();//下面为添加配置的实现公共静态void AddConfiguration(此ILoggingBuilder生成器){建设者.服务。tryaddsingletionloglerproviderconfigurationfactory,loglerproviderconfigurationfactory();建筑商服务。TryAddSingleton(类型of(ilogepiderconfiguration),类型of(logger provider configuration));}建设者。服务。addsingletoniconfigureoptions sloggerfilteroptions(新的LoggerFilterConfigureOptions(配置));建筑商。服务。addsingletonioptions schengetokensourcelogerfilteroptions(新配置更改tokensourceloggerfilteroptions(配置));建筑商。服务。添加单例(新的日志配置(配置));返回生成器;}下面来看打印日志的具体实现:

公共void logt状态(LogLevel LogLevel,EventId eventId,TState状态,exception异常,FuncTState,Exception,字符串格式化程序){ var logger=logger slisteexception exception=null//记录器为记录器信息数组,如果你在启动中添加了控制台、Deubg日志功能了,那记录器数组值有2个,就是它俩foreach(记录器中的var记录器信息){//循环遍历每一种日志打印,如果满足些日子的条件,才执行打印原木方法。比如某一个日志等级为信息,//但是安慰配置的最低打印等级为警告,调试配置的最低打印等级为调试//则安慰中不会打印,调试中会被打印if(!记录器信息IsEnabled(LogLevel)){ continue;}尝试{//每一种类型的日志,对应的打印方法不同。执行对应的打印方法记录器信息。日志(日志级别、事件标识、状态、异常、格式化程序);} catch(Exception ex){ if(exceptions==null){ exceptions=new ListException();}例外。添加(例如);} }}下面具体看一下安慰的打印实现:

首先控制台实现了ILogger的原木方法,并在方法中调用WriteMessage方法

公共void logt状态(LogLevel,LogLevel,EventId,t state状态,异常异常,函数状态,异常,字符串格式化程序){ //代码太多我就省略一些判空代码var消息=格式化程序(状态,异常);if(!字符串IsNullOrEmpty(消息)||异常!=null) { WriteMessage(日志级别,名称,事件身份证.身份证、消息、异常);} }公共虚拟无效写消息(日志级别日志级别,字符串日志名,int eventId,字符串消息,异常异常){ 0.if(日志生成器.长度0) { var hasLevel=!字符串IsNullOrEmpty(LogLevelString);//这里是主要的代码实现,可以看到,并没有写日志的代码,而是将日志打入到一个BlockingCollectionLogMessageEntry队列中_queueProcessor .入队消息(新的日志消息条目(){消息=日志生成器. ToString(),消息颜色=defaultconsoleclor,LevelString=hasLevel?logLevelString : null,LevelBackground=hasLevel?对数级颜色.背景: null,LevelForeground=hasLevel?对数级颜色.前台: null });} .}下面看日志被放入队列后的具体实现:

公共类控制台记录器处理器: IDisposable { private const int _ maxQueuedMessages=1024;private readonly BlockingCollectionLogMessageEntry _ messageQueue=new BlockingCollectionLogMessageEntry(_ maxQueuedMessages);私有只读线程_输出线程;公共图标控制台;public consolerogprocessor(){//在构造函数中启动一个线程,执行ProcessLogQueue方法//从下面ProcessLogQueue方法可以看出,是循环遍历集合,将集合中的数据打印_输出线程=新线程(进程日志队列){ ISbackground=true,Name='控制台日志记录程序队列处理线程公共虚拟无效入队消息(LogMessageEntry消息){ if(!_消息队列.IsAddingCompleted){ try { _ message queue .添加(消息);返回;} catch(InvalidOperationException){ } }写消息(消息);}内部虚拟无效写入消息(日志消息条目消息){ if(消息LevelString!=null){ 0控制台。写(消息级别字符串,消息。级别背景,消息.水平前景);}控制台。写(消息。留言留言。消息颜色,消息消息颜色);控制台flush();} private void ProcessLogQueue(){ try {//getconsumeingnumerable()方法比较特殊,当集合中没有值时,会阻塞自己,一但有值了,知道集合中又有元素继续遍历foreach(var消息在消息队列中).getconsumeingnumerable()){写消息(message);} } catch { try { _messageQueue .完成添加();} catch { } } }以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

版权声明:详解 净核心中的日志组件(日志记录)是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。