net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案

本文目录
1. Net下日志记录
2. NLog的使用
    2.1 添加nuget引用NLog.Web.AspNetCore
    2.2 配置文件设置
    2.3 依赖配置及调用
    2.4 日志类型介绍
    2.5 产生的日志文件
3. 基于Microsoft.Extensions.Logging封装
    3.1 添加引用Microsoft.Extensions.Logging
    3.2 实现我们的Logger
    3.3 调用WLogger
2018-03-28 补充

4. 总结

1.  Net下日志记录

  Net Freamwork框架下在日志记录框架有很多,常见的有NLog、Log4Net、Loggr和内置 Microsoft.Diagnostics.Trace/Debug/TraceSource等。Asp.Net Core 2.0下大部分框架已不支持,Microsoft提供Microsoft.Extensions.Logging供大家实现自己的记录日志框架。现在笔者了解到的NLog已支持Net Core,下面我们介绍下nlog在项目中的使用以及基于Microsoft.Extensions.Logging封装自己的日志记录类。

1.  NLog的使用

  2.1添加nuget引用NLog.Web.AspNetCore

  

  2.2配置文件设置

    在Asp.Net Core 2.0项目实战项目中,我们把配置文件统一放在configs文件夹中,方便管理。读取时用Path.Combine("configs", "nlog.config")即可。下面是nlog.config的配置。

复制代码
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"autoReload="true"internalLogLevel="Warn"internalLogFile="internal-nlog.txt"><!--define various log targets--><targets><!--write logs to file--><target xsi:type="File" name="allfile" fileName="nlog-all-${shortdate}.log"layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}" /><target xsi:type="File" name="ownFile-web" fileName="nlog-my-${shortdate}.log"layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}" /><target xsi:type="Null" name="blackhole" /></targets><rules><!--All logs, including from Microsoft--><logger name="*" minlevel="Trace" writeTo="allfile" /><!--Skip Microsoft logs and so log only own logs--><logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" /><logger name="*" minlevel="Trace" writeTo="ownFile-web" /></rules></nlog>
复制代码

  2.3依赖配置及调用

    在startup.cs中配置日志工厂,添加使用的服务配置后在项目中就可以调用。

 

复制代码
     /// <summary>/// 配置/// </summary>/// <param name="app"></param>/// <param name="env"></param>/// <param name="loggerFactory"></param>public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){loggerFactory.AddNLog();//添加NLog  //读取Nlog配置文件,这里如果是小写,文件也一定是小写,否则linux下不识别  env.ConfigureNLog(Path.Combine("configs", "nlog.config"));}
复制代码

 

     nlog调用,如在Controller中调用,如:在HomeController中

  2.4 日志类型介绍

复制代码
public enum LogLevel
{Debug = 1,Verbose = 2,Information = 3,Warning = 4,Error = 5,Critical = 6,None = int.MaxValue
}
复制代码

  2.5产生的日志文件

    日志的位置默认是在bin\Debug\netcoreapp2.0下面

 

    日志文件内容根据文件名可以很方便的区分开,其中nlog-all包含的内比较多,nlog-my中就只包含了我们记录日志的内容,大家动手试一下。

 

3.基于Microsoft.Extensions.Logging封装

  由于受老项目webform影响,记录日志是在第三方类库dll中封装好了帮助类,这样在可以在项目中任何位置方便调用,这里我的nc.common工具库WLogger基于Microsoft NET Core的日志模型主要由三个核心对象构成,它们分别是Logger、LoggerProvider和LoggerFactory。现在只实现了文件记录日志txt,数据库模式有业务需求的朋友可自己扩展。

 

  3.1添加引用Microsoft.Extensions.Logging

    扩展微软日志记录框架,集成一个自己的Logger,现在扩展的是txt形式,后续可参考完善数据库模式。添加引用dll后,增加配置文件并配置,这里我先加在appsettings.json文件中,主要是配置是否开启日志和日志记录。

 

 

  3.2 实现我们的Logger

    首先实现日志工厂的扩展LoggerFactoryExtensions,为net core 依赖注入LoggerFactory扩张一个方法,提供增加日志写文件方式的入口。

复制代码
using Microsoft.Extensions.Logging;namespace NC.Common
{public static class LoggerFactoryExtensions{public static ILoggerFactory AddFileLogger(this ILoggerFactory factory){factory.AddProvider(new FileLoggerProvider());return factory;}}
}
复制代码

    然后实现ILoggerProvider接口,FileLoggerProvider提供程序真正具有日志写入功能的Logger。

复制代码
using Microsoft.Extensions.Logging;namespace NC.Common
{public class FileLoggerProvider : ILoggerProvider{/// <summary>/// 默认构造函数,根据Provider进此构造函数/// </summary>/// <param name="categoryName"></param>/// <returns></returns>public ILogger CreateLogger(string categoryName){return new FileLogger(categoryName);}public void Dispose(){}}
}
复制代码

    最后实现ILogger接口FileLogger继承并进行封装,方便写入文本日志。

复制代码
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;namespace NC.Common
{public class FileLogger : ILogger{private string name;private bool IsOpen;private string WPath;public FileLogger(string _name){name = _name;}public IDisposable BeginScope<TState>(TState state){return null;}/// <summary>/// 是否禁用/// </summary>/// <param name="logLevel"></param>/// <returns></returns>public bool IsEnabled(LogLevel logLevel){return true;}/// <summary>/// 实现接口ILogger/// </summary>/// <typeparam name="TState"></typeparam>/// <param name="logLevel"></param>/// <param name="eventId"></param>/// <param name="state"></param>/// <param name="exception"></param>/// <param name="formatter"></param>public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter){IsOpen = UtilConf.GetSection("WLogger")["IsOpen"] == "true" ? true : false;if (IsOpen){//获取日志信息var message = formatter?.Invoke(state, exception);//日志写入文件LogToFile(logLevel, message);}}/// <summary>/// 记录日志/// </summary>/// <param name="level">等级</param>/// <param name="message">日志内容</param>private void LogToFile(LogLevel level, string message){var filename = GetFilename();var logContent = GetLogContent(level, message);File.AppendAllLines(filename, new List<string> { logContent }, Encoding.UTF8);}/// <summary>/// 获取日志内容/// </summary>/// <param name="level">等级</param>/// <param name="message">日志内容</param>/// <returns></returns>private string GetLogContent(LogLevel level, string message){return $"[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.h3")}]{level}|{name}|{message}";}private string DirectorySeparatorChar = Path.DirectorySeparatorChar.ToString();//目录分隔符/// <summary>/// 获取文件名/// </summary>private string GetFilename(){var dir = "";WPath = UtilConf.GetSection("WLogger")["WPath"];if (WPath.IndexOf(":") > -1){dir = WPath;}else{//此方法不是真正的获取应用程序的当前方法,而是执行dotnet命令所在目录dir = Directory.GetCurrentDirectory() + WPath;}if (!Directory.Exists(dir))Directory.CreateDirectory(dir);var result = $"{dir}/WLog-{DateTime.Now.ToString("yyyy-MM-dd")}.txt".Replace("/",DirectorySeparatorChar);return result;}}
}
复制代码

  3.3 调用WLogger

    在nc.common类库中封装好logger实现后,在调用连接使用数据库在core类库中调用实例如下。

    首先我们先做一下封装调用类

 

复制代码
using Microsoft.Extensions.Logging;namespace NC.Common
{public class UtilLogger<T>{private static ILogger iLog;public static ILogger Log{get{if (iLog != null) return iLog;第一种写法//ILoggerFactory loggerFactory = new LoggerFactory();//loggerFactory.AddFileLogger();//iLog = loggerFactory.CreateLogger<DbCommand>();//第二种写法iLog = new LoggerFactory().AddFileLogger().CreateLogger<T>();return iLog;}set => iLog = value;}}
}
复制代码

    然后在DbCommand中调用就可以直接写成:

      public static ILogger Log = UtilLogger<DbCommand>.Log;//日志记录

      Log. LogInformation(string);

      Log.LogError(string)

    详细方法还可以参考

 

2018-03-28补充:

  日志记录与全局错误处理结合,首先创建全局错误过滤类HttpGlobalExceptionFilter并在startup.cs中ConfigureServices方法下添加

services.AddMvc(options =>{options.Filters.Add(typeof(HttpGlobalExceptionFilter));//全局错误过滤日志}).AddControllersAsServices();

  然后实现OnException方法并记录日志,这样系统只要报异常,日志 就会被记录下来。

复制代码
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using NC.Common;namespace NC.MVC
{/// <summary>/// 错误处理类/// </summary>public class HttpGlobalExceptionFilter : IExceptionFilter{private readonly IHostingEnvironment _env;public static ILogger Log = UtilLogger<HttpGlobalExceptionFilter>.Log;//日志记录public HttpGlobalExceptionFilter(IHostingEnvironment env){this._env = env;}public ContentResult FailedMsg(string msg = null){string retResult = "{\"status\":" + JHEnums.ResultStatus.Failed + ",\"msg\":\"" + msg + "\"}";//, msg);string json = JsonHelper.ObjectToJSON(retResult);return new ContentResult() { Content = json };}public void OnException(ExceptionContext filterContext){if (filterContext.ExceptionHandled)return;//执行过程出现未处理异常Exception ex = filterContext.Exception;
#if DEBUGif (filterContext.HttpContext.Request.IsAjaxRequest()){string msg = null;if (ex is Exception){msg = ex.Message;filterContext.Result = this.FailedMsg(msg);filterContext.ExceptionHandled = true;return;}}this.LogException(filterContext);return;
#endifif (filterContext.HttpContext.Request.IsAjaxRequest()){string msg = null;if (ex is Exception){msg = ex.Message;}else{this.LogException(filterContext);msg = "服务器错误";}filterContext.Result = this.FailedMsg(msg);filterContext.ExceptionHandled = true;return;}else{//对于非 ajax 请求this.LogException(filterContext);return;}}/// <summary>/// 记录日志/// </summary>/// <param name="filterContext"></param>private void LogException(ExceptionContext filterContext){string mid = filterContext.HttpContext.Request.Query["mid"];//codding 后续完善每个action带一个idvar areaName = (filterContext.RouteData.DataTokens["area"] == null ? "" : filterContext.RouteData.DataTokens["area"]).ToString().ToLower();var controllerName = (filterContext.RouteData.Values["controller"]).ToString().ToLower();var actionName = (filterContext.RouteData.Values["action"]).ToString().ToLower();#region --记录日志 codding 后续增加自定义字段的日志。如:记录Controller/action,模块ID等--Log.LogError(filterContext.Exception, "全局错误:areaName:" + areaName + ",controllerName:" + controllerName + ",action:" + actionName);#endregion}}
}
复制代码

 

 

4.总结

  不管是生产环境还是开发环境,总会碰到这样或那样的问题,这时日志记录就为我们提供了记录分析问题的便利性,net core 2.0下记录日志功能是最需要我们及时实现的功能,这样为我们接下来的学习提供技术支撑。另外net core 生态还不完善,很多功能需要我们自己动手去实现,在这里希望大家多动手去实现去分享,文中有不清楚或有问题欢迎留言讨论。

参考:

https://msdn.microsoft.com/magazine/mt694089

https://www.cnblogs.com/artech/p/inside-net-core-logging-2.html

https://www.cnblogs.com/calvinK/p/5673218.html

转载于:https://www.cnblogs.com/hmit/p/10769576.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462767.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

strcasecmp()--忽略大小写比较字符串

strcasecmp()的功能是&#xff1a;忽略大小写比较字符串 头文件 #include <strings.h> 函数原型&#xff1a;int strcasecmp(const char *s1, const char *s2); 函数功能: 用来比较参数s1和s2字符串&#xff0c;比较时会自动忽略大小写的差异。 返回值: 若参数字符串…

NDK 获取android的imei和serial number

1&#xff0c;获取imei int setAndroidDeviceID(JNIEnv *env, jobject obj,jobject mContext) {if(mContext 0){return -1;}jclass cls_context (*env)->FindClass(env, "android/content/Context");if(cls_context 0){return -1;}jmethodID getSystemService …

《JS高级程序设计》PART3.对象基础

3.2对象应用 对象废除&#xff1a;如果一个对象有2个及以上引用&#xff0c;则要正确的废除该对象&#xff0c;必须将其所有引用都设置为null。 js和java一样&#xff0c;有垃圾回收机制&#xff0c;会自动收回已无引用指向的对象。 早绑定和晚绑定 绑定&#xff1a;把对象的…

python迭代-如何对迭代器做切片操作

如何对迭代器做切片操作 问题举例 读取某个文件内容的100~300行内容&#xff0c;我们是否可以使用 类似列表切片的方式得到一个100~300行文件内容的生成器 分析 列表的切片操作其实是在重载方法__getItem__方法 可以通过file.readlines()后再做切片&#xff0c;内存会加载整个文…

如何让linux服务器同步互联网时间

今天在工作中需要搭建一个数据库集群s1&#xff0c;需要将节点A、节点B和节点C都加入集群&#xff0c;先在A节点上创建集群&#xff0c;然后将B和C节点加入到集群&#xff0c;但是在B和C加入到集群之前&#xff0c;会判断B与A、C与A的时间戳是不是在设置的2s~5s内&#xff0c;如…

Conda常见命令

Anaconda,Miniconda,Conda,Pip的区别&#xff1a; Anaconda&#xff1a;用于科学计算的python发行版&#xff0c;里面预装好了conda&#xff0c;某个版本的python&#xff0c;众多packages,科学计算工具等。Anaconda利用工具/命令conda来进行package和environment的管理&#x…

MySQL一张innodb表列个数的限制和engine的选择

在MySQL innodb存储引擎中&#xff0c;一张表中列的个数最大为4096。 其中在MySQL中&#xff0c;创建表时可以任意指定engine的类型&#xff0c;但是&#xff0c;考虑到join、union、union all等复杂的场景时&#xff0c;尽量每张表都用统一的engine。

Hibernate读书笔记

伟大的信息管理与信息系统专业&#xff0c;万恶的信息管理与信息系统专业。说这句话我是有根据的&#xff1a;因为这个专业雄心勃勃的想把自己的子弟培养成全面发展的人才但是结果则不然。两方面的原因&#xff1a;一部分在学生&#xff0c;但是一部分在这个专业。让我极其郁闷…

基于报文地址的策略路由配置示例

【实验拓扑】本文实验采用的交换机是H3C模拟器&#xff0c;下载地址如下&#xff1a; http://forum.h3c.com/forum.php? modviewthread&tid109740&highlightH3C%E6%A8%A1%E6% 8B%9F%E5%99%A8 有兴趣的朋 友可以在论坛上去下载 【组网需求】普通的报文转发是依据报文的…

html字体加大标签与写法介绍

在html中字体加大的标签为<big>&#xff0c;一般用于重要文字&#xff0c;醒目文字&#xff0c;让用户容易看到&#xff01; 字体加大: <big>写上你想写的字</big> 效果&#xff1a;未加大 加大 效果中我们能轻易分辨&#xff0c;加大和未加大的文字区别&am…

CustomValidator

使用服务器验证时 要注意 IsValid 需要再次进行判断转载于:https://www.cnblogs.com/spchenjie/archive/2011/03/02/1968968.html

MySQL单机版Recycle Bin回收站功能

最近调研了阿里的Recycle Bin回收站功能&#xff0c;可以保证数据不丢失。 为了防止开发或运维人员的误操作&#xff0c;比如DROP TABLE/DATABASE、TRUNCATE TABLE&#xff0c;这类DDL语句不具有可操作的回滚特性&#xff0c;而导致数据丢失,AliSQL 8.0(基于MySQL)新特性支持回…

Delphi纯代码连SQLite数据库,同时支持数据库的加密解密

//摘自&#xff1a;http://bbs.witbase.com/thread-1141-1-1.html Delphi纯代码连SQLite数据库&#xff0c;同时支持数据库的加密解密 Delphi纯代码连SQLite数据库&#xff0c;同时支持数据库的加密解密本文的内容包括&#xff1a;&#xff08;1&#xff09;一个实现了加密解密…

用STATSVN统计公司SVN代码修改

直接用LOG&#xff0c;BOSS还是不满意&#xff0c;那只好架上JDK&#xff0c;用STATSVN了。 跑得还顺利&#xff0c;只是具体代码没跑出来。。 但共用一个帐号&#xff0c;害人呀&#xff0c;还好有提交注释里有程序员的名字。。 STATSVN文档很简单&#xff0c;简单报告也就一个…

Informix IDS 11零碎治理(918考试)认证指南,第 7 部分: IDS复制(24)

SDS&#xff1a;看管可以使用 onstat 或零碎看管接口&#xff08;SMI&#xff09;表查察 SDS 效能器统计信息。本节品评争论以下主题&#xff1a;onstat 选项 sysmaster 表 旧事日志输出 onstat 选项可以使用 onstat -g sds 饬令查察 SDS 效能器统计信息。onstat 的输出取决于运…

leafLet入门教程兼leafLet API中文文档参考

英文文档参考&#xff1a;https://leafletjs.com/reference-1.3.4.html#popup 博客参考&#xff1a;https://blog.csdn.net/qq_36595013/article/details/83144874#leafLet_API__243 使用说明参考&#xff1a;https://www.cnblogs.com/cainiaomeng/p/6072139.html转载于:https:…

MySQL源码解读之数据结构-LF_DYNARRAY

MySQL的代码中实现了一个Lock Free的Hash结构&#xff0c;称作LF_Hash。MySQL的不少模块使用了LF_Hash&#xff0c;比如Metadata Lock就依赖于它。但由于使用的方法不正确&#xff0c;导致了bug#98911和bug#98624。理解LF_Hash的实现细节&#xff0c;可以帮助我们用好LF_Hash。…

Flex通过Blazeds利用Remoteservice与后台java消息推送

Flex通过Blazeds利用Remoteservice与后台java消息推送 准备工作&#xff1a;Myeclipse中先建立一个Web project工程&#xff0c;然后导入Blazeds的文件&#xff0c;再转换为Flex项目类型。前言&#xff1a;Flex 通过开源的BlazeDS消息服务来支持订阅及发布消息。这个消息服务管…

如何运行一个Vue项目

一开始很多刚入手vue.js的人&#xff0c;会扒GitHub上的开源项目&#xff0c;但是发现不知如何运行GitHub上的开源项目&#xff0c;很尴尬。通过查阅网上教程&#xff0c;成功搭建好项目环境&#xff0c;同时对前段工程化有了朦朦胧胧的认知&#xff0c;因此将环境搭建过程分享…

用上Linux后收集变得山穷水尽

作者: ginceo 出自: http://www.linuxdiyf.com   没用Linux时上彀总得先开防火墙&#xff0c;然后再开杀毒软件把守&#xff0c;假如少了这些步骤我的机子将遭到史无前例的毁伤&#xff0c;有的时分换来的是硬盘继续事项一小时。遇到网友发来的音讯还是毛骨悚然&#xff0c;…