Net Core集成Exceptionless分布式日志功能以及全局异常过滤

相信很多朋友都看过我的上篇关于Exceptionless的简单入门教程[asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程][https://www.cnblogs.com/yilezhu/p/9193723.html] 上篇文章只是简单的介绍了Exceptionless是什么?能做什么呢?以及怎么进行本地部署和异常提交的简单用法,而这篇文章将带你探讨一下Exceptionless的异常收集高级用法以及你熟悉的类似NLog的日志用法。

这篇文章有一部分内容翻译自官方文档,[点我阅读][https://github.com/exceptionless/Exceptionless.Net/wiki/Sending-Events] 英语好的可以自行阅读 。当然中间很多代码我都进行了重构,还有参考周旭龙的代码,进行了简单地封装,同时加入了为webapi加入异常全局过滤器进行异常日志的记录。希望对大家有所帮助。

本文地址:https://www.cnblogs.com/yilezhu/p/9339017.html

作者:依乐祝

手动发送错误

上篇文章介绍了,导入命名空间后,并使用如下代码就可以简单地提交异常日志:

try {
throw new ApplicationException(Guid.NewGuid().ToString());
} catch (Exception ex) {
ex.ToExceptionless().Submit();
}

发送附加信息

当然你还可以为发送的事件添加额外的标记信息,比如坐标,标签,以及其他的用户相关的信息等等

try {
throw new ApplicationException("Unable to create order from quote.");
} catch (Exception ex) {
ex.ToExceptionless()
// 设置一个ReferenceId方便查找
.SetReferenceId(Guid.NewGuid().ToString("N"))
// 添加一个不包含CreditCardNumber属性的对象信息
.AddObject(order, "Order", excludedPropertyNames: new [] { "CreditCardNumber" }, maxDepth: 2)
// 设置一个名为"Quote"的编号
.SetProperty("Quote", 123)
// 添加一个名为“Order”的标签
.AddTags("Order")
// 标记为关键异常
.MarkAsCritical()
// 设置一个位置坐标
.SetGeo(43.595089, -88.444602)
// 在你的系统中设置userid并提供一个有好的名字,俗称昵称
.SetUserIdentity(user.Id, user.FullName)
// 为异常信息添加一些用户描述信息.
.SetUserDescription(user.EmailAddress, "I tried creating an order from my saved quote.")
// 提交.
.Submit();
}

统一修改未处理的异常报告

你可以在通过SubmittingEvent 事件设置全局的忽略异常信息添加一些自定义信息等等


#region Exceptionless配置
ExceptionlessClient.Default.Configuration.ApiKey = exceptionlessOptions.Value.ApiKey;
ExceptionlessClient.Default.Configuration.ServerUrl = exceptionlessOptions.Value.ServerUrl;
ExceptionlessClient.Default.SubmittingEvent += OnSubmittingEvent;
app.UseExceptionless();
#endregion /// <summary>
/// 全局配置Exceptionless
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSubmittingEvent(object sender, EventSubmittingEventArgs e)
{
// 只处理未处理的异常
if (!e.IsUnhandledError)
return; // 忽略404错误
if (e.Event.IsNotFound())
{
e.Cancel = true;
return;
} // 忽略没有错误体的错误
var error = e.Event.GetError();
if (error == null)
return;
// 忽略 401 (Unauthorized) 和 请求验证的错误.
if (error.Code == "401" || error.Type == "System.Web.HttpRequestValidationException")
{
e.Cancel = true;
return;
}
// Ignore any exceptions that were not thrown by our code.
var handledNamespaces = new List<string> { "Exceptionless" };
if (!error.StackTrace.Select(s => s.DeclaringNamespace).Distinct().Any(ns => handledNamespaces.Any(ns.Contains)))
{
e.Cancel = true;
return;
}
// 添加附加信息.
//e.Event.AddObject(order, "Order", excludedPropertyNames: new[] { "CreditCardNumber" }, maxDepth: 2);
e.Event.Tags.Add("MunicipalPublicCenter.BusinessApi");
e.Event.MarkAsCritical();
//e.Event.SetUserIdentity();
}

配合使用 NLog 或 Log4Net

有时候,程序中需要对日志信息做非常详细的记录,比如在开发阶段。这个时候可以配合 log4net 或者 nlog 来联合使用 exceptionless,详细可以查看这个官方的 [示例][https://github.com/exceptionless/Exceptionless.Net/tree/master/samples/Exceptionless.SampleConsole]。

如果你的程序中有在短时间内生成大量日志的情况,比如一分钟产生上千的日志。这个时候你需要使用内存存储(in-memory store)事件,这样客户端就不会将事件系列化的磁盘,所以会快很多。这样就可以使用Log4net 或者 Nlog来将一些事件存储到磁盘,另外 Exceptionless 事件存储到内存当中。

Exceptionless 日志记录的封装

  1. 首先简单地封装一个ILoggerHelper接口

    /// <summary>
    /// lzhu
    /// 2018.7.19
    /// 日志接口
    /// </summary>
    public interface ILoggerHelper
    {
    /// <summary>
    /// 记录trace日志
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    void Trace(string source, string message, params string[] args);
    /// <summary>
    /// 记录debug信息
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    void Debug(string source, string message, params string[] args);
    /// <summary>
    /// 记录信息
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    void Info(string source, string message, params string[] args);
    /// <summary>
    /// 记录警告日志
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    void Warn(string source, string message, params string[] args);
    /// <summary>
    /// 记录错误日志
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    void Error(string source, string message, params string[] args);
    }
  2. 既然有了接口,那么当然得实现它了

    /// <summary>
    /// lzhu
    /// 2018.7.19
    /// Exceptionless日志实现
    /// </summary>
    public class ExceptionlessLogger : ILoggerHelper
    {
    /// <summary>
    /// 记录trace日志
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">添加标记</param>
    public void Trace(string source,string message, params string[] args)
    {
    if (args != null && args.Length > 0)
    {
    ExceptionlessClient.Default.CreateLog(source, message, LogLevel.Trace).AddTags(args).Submit(); }
    else
    {
    ExceptionlessClient.Default.SubmitLog(source, message, LogLevel.Trace);
    }
    }
    /// <summary>
    /// 记录debug信息
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    public void Debug(string source, string message, params string[] args)
    {
    if (args != null && args.Length > 0)
    {
    ExceptionlessClient.Default.CreateLog(source, message, LogLevel.Debug).AddTags(args).Submit();
    }
    else
    {
    ExceptionlessClient.Default.SubmitLog(source, message, LogLevel.Debug);
    }
    }
    /// <summary>
    /// 记录信息
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    public void Info(string source, string message, params string[] args)
    {
    if (args != null && args.Length > 0)
    {
    ExceptionlessClient.Default.CreateLog(source, message, LogLevel.Info).AddTags(args).Submit();
    }
    else
    {
    ExceptionlessClient.Default.SubmitLog(source, message, LogLevel.Info);
    }
    }
    /// <summary>
    /// 记录警告日志
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    public void Warn(string source, string message, params string[] args)
    {
    if (args != null && args.Length > 0)
    {
    ExceptionlessClient.Default.CreateLog(source, message, LogLevel.Warn).AddTags(args).Submit();
    }
    else
    {
    ExceptionlessClient.Default.SubmitLog(source, message, LogLevel.Warn);
    }
    }
    /// <summary>
    /// 记录错误日志
    /// </summary>
    /// <param name="source">信息来源</param>
    /// <param name="message">日志内容</param>
    /// <param name="args">标记</param>
    public void Error(string source, string message, params string[] args)
    {
    if (args != null && args.Length > 0)
    {
    ExceptionlessClient.Default.CreateLog(source, message, LogLevel.Error).AddTags(args).Submit();
    }
    else
    {
    ExceptionlessClient.Default.SubmitLog(source, message, LogLevel.Error);
    }
    }
    }
  3. 当然实现好了,可别忘了依赖注入哦

 //注入ExceptionlessLogger服务
services.AddSingleton<ILoggerHelper, ExceptionlessLogger>();
  1. 这时候该写一个全局异常过滤器了

    /// <summary>
    /// lzhu
    /// 2018.7.19
    /// 定义全局过滤器
    /// </summary>
    public class GlobalExceptionFilter : IExceptionFilter
    { private readonly ILoggerHelper _loggerHelper;
    //构造函数注入ILoggerHelper
    public GlobalExceptionFilter(ILoggerHelper loggerHelper)
    {
    _loggerHelper = loggerHelper;
    } public void OnException(ExceptionContext filterContext)
    {
    _loggerHelper.Error(filterContext.Exception.TargetSite.GetType().FullName, filterContext.Exception.ToString(), MpcKeys.GlobalExceptionCommonTags, filterContext.Exception.GetType().FullName);
    var result = new BaseResult()
    {
    errcode = ResultCodeAddMsgKeys.CommonExceptionCode,//系统异常代码
    errmsg= ResultCodeAddMsgKeys.CommonExceptionMsg,//系统异常信息
    };
    filterContext.Result = new ObjectResult(result);
    filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
    filterContext.ExceptionHandled = true;
    }
    }
  2. 全局过滤器写好了,怎么让它生效呢,客观别急啊,上正菜

      //添加验证
    services.AddMvc(options=> {
    options.Filters.Add<GlobalExceptionFilter>();
    }).AddFluentValidation();
  3. 哈哈,没什么说的了,代码都已经写好了,剩下的就是上代码测试结果了。我这里只是简单地api测试下,万能的ValuesController登场:

     // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
    //try
    //{
    throw new Exception($"测试抛出的异常{id}");
    //}
    //catch (Exception ex)
    //{
    // ex.ToExceptionless().Submit();
    //}
    //return "Unknown Error!"; }

    这里是直接抛出异常,不进行trycatch,这时候异常会被全局过滤器捕获,然后放到Exceptionless的Log里面,别问我为什么会在log里面,因为我全局过滤器代码里面已经写明了,不明白的回去看代码,然后看接口调用的实现方法。下面上结果:

点进去,看看详细信息:

  1. 再测试下使用try catch捕获的异常处理,这时候异常信息会被提交到Exception这个里面。直接上代码吧

    // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
    try
    {
    throw new Exception($"测试抛出的异常{id}");
    }
    catch (Exception ex)
    {
    ex.ToExceptionless().Submit();
    }
    return "Unknown Error!"; }

    到exceptionless里面看看不活的异常吧。打字很累直接上图吧

    点进去看看详细信息,有三个tab,下面之粘贴一个图片了:

    最后,源码就不上了,因为上面代码很清楚了

    总结

    本文没有对Exceptionless进行过多地介绍,因为博主的[上篇文章][https://www.cnblogs.com/yilezhu/p/9193723.html] 已经进行了详细的介绍。直接切入正题,先对官方高级用法进行了简单地翻译。然后对Exceptionless Log这个eventtype进行了简单地封装,让你可以像使用NLog一样很爽的使用Exceptionless。最后通过一个asp.net core web api的项目进行了演示,在全局过滤器中利用封装的Log方法进行全局异常的捕获。希望对大家使用Exceptionless有所帮助。

Net Core集成Exceptionless分布式日志功能以及全局异常过滤的更多相关文章

  1. .Net Core 集成ExceptionLess分布式日志框架之本地化部署

    前言 公司目前使用的项目中关于日志记录这块,之前一直都是使用的Log4net 存放于后台文件中的,对于异常错误啊,或者需要查看一些详情错误的时候感觉很不方便,要到服务器上去打开日志文件检索错误,降低了 ...

  2. asp.net core集成CAP(分布式事务总线)

    一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET Core 事件总线,分布式事务解决方案:CAP 以及 如何在你的项目中集成 CAP[手把手视频教程],之前也在工作中遇到分布式 ...

  3. asp.net core全局异常过滤并监控系统BUG将异常信息记录到日志

    添加: using Dw.Util.Helper; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Collect ...

  4. 在.NET Core中使用Exceptionless分布式日志收集框架

    一.Exceptionless简介 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,ASP.NET Core,Web Api,Web Forms,WPF, ...

  5. .NetCore下 Exceptionless 分布式日志的个性化处理

    Event Type 在Exceptionless中有 Exception .LogMessage.Broken Links .Feature Usages 接下来就这几种类型分别添加日志记录 Exc ...

  6. Cap+Exceptionless实现日志消息发布订阅异常情况日志处理及Cap DashBoard授权处理

    Dashboard介绍 capOptions.UseDashboard(dashoptions => { dashoptions.AppPath = "applicationpath& ...

  7. .NET Core微服务之基于Exceptionless实现分布式日志记录

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.Exceptionless极简介绍 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,AS ...

  8. 分布式日志框架Exceptionless之生产环境部署步骤

    Exceptionless 是一个开源的实时的日志收集框架,它将日志收集变得简单易用并且不需要了解太多的相关技术细节及配置.本篇基于我的上一篇<基于Exceptionless实现分布式日志> ...

  9. CoreWebApi集成Exceptionless

    参考博客 https://www.cnblogs.com/akaxb/p/7207827.html 一. Exceptionlessr的安装部署 依乐祝,<ASP.NET Core免费开源分布式 ...

随机推荐

  1. 实现一个简易版RPC

    上篇博客主要介绍了dubbo的使用,这篇文章主要深入rpc的核心原理 准备知识: 1 java 网络编程(这里使用的bio) 2 java动态代理 3 反射 ===================== ...

  2. Open quote is expected for attribute "{1}" associated with an element type "column".

    这个的错误的意思很简单:就是自己的配置文件是否缺少""号

  3. MySQL中的latch(闩锁)详解——易产生的问题以及原因分析

    Latch 什么是latch: 锁是数据库系统区别与文件系统的一个关键特性.锁机制用于管理对共享资源的并发访问.Innodb存储引擎在行级别上对表数据上锁,这固然不错.但是Innodb也会在多个地方使 ...

  4. php日志报错child exited with code 0 after seconds from start

    因为日志文件老是有这种提示: [27-May-2015 15:13:48] NOTICE: [pool www] child 3998 started [27-May-2015 15:13:59] N ...

  5. css3用到知识点小结

    属性 默认值 属性值及其描述 animation-name 默认值:none 规定需要绑定到选择器的 keyframe 名称. keyframename 规定需要绑定到选择器的 keyframe 的名 ...

  6. [swarthmore cs75] Lab 0 Warmup & Basic OCaml

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第1次大作业. 什么是编译 编译就是执行Program->Program'转换的过程,如下 ...

  7. ROS学习笔记(一) : 入门之基本概念

    目录 基本概念 1. Package 2. Repositories 3. Computation Graph 4. Node 5. Master 6. Message 7. Topic 8. Ser ...

  8. 零基础Windows + JAVA(jdk)环境搭建以及eclipse安装和使用

    关于java的环境搭建其实网上有很多种,下面小编就自己来操作一下吧~ java的环境搭建最主要的就是jdk的安装及环境变量设置,好了,来看看安装步骤: 一.JDK的下载与安装(java安装包)  JD ...

  9. ie9 css文件大小限制

    使用webpack生成CSS对于一些有趣的定义很有趣.不幸的是,当你拥有一个大型应用程序并且需要IE9支持时,乐趣就会停止,因为IE9会忽略你生成的CSS包中的大于4000个选择器的部分.解决方案是将 ...

  10. Base64格式上传文件至阿里云(java)

    Controller @PostMapping("/save") public R save(@RequestBody ShareEntity share){ OSSClient ...