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. 修改pudb颜色

    2019-02-19,18点20vim调整颜色vim ~/.vimrc 这个pudb的配色用上的方法改不了.调试状态时候按o和回车能切换console和调试界面. 成功了.通过修改pudb源代码来实现 ...

  2. iOS12 XCode10更新

    原因:libc++.tbd库取代了libstdc++.6.0.9.tbd库 解决方法:我在项目里去掉了libstdc++.6.0.9.tbd库 这个时候去编译还是会报错, 解决方法:Xcode-fil ...

  3. python3 第三十一章 - 模块

    1.什么是模块 如果从Python解释器退出并再次输入,您所做的定义(函数和变量)将丢失.因此,如果要编写一个稍长的程序,最好使用文本编辑器为解释器准备输入,并以该文件作为输入运行它.这称为创建脚本. ...

  4. python爬虫-百度百科百名红通人员名单

    爬虫代码: import urllib.request import os, re from bs4 import BeautifulSoup import xlwt URL = "http ...

  5. 关于微信小程序切换获取不到元素的问题

    1.由于公司要实现微信小程序的自动化,所以开始学习python + appium 实现微信小程序自动化.在学习过程中遇到在切换webview后获取不到页面元素的问题,导致无法继续.今天在网上看到一篇关 ...

  6. 《Java核心技术卷1》拾遗

    之前对Java的基础知识有过学习,现在开始学习<Java核心技术卷1>,将一些新学的知识点,做简要记录,以备后续回顾: 1.double (1)所有的“非数值”都认为是不相同的 if(x= ...

  7. 20175316盛茂淞 2018-2019-2 《Java程序设计》第8周学习总结

    20175316盛茂淞 2018-2019-2 <Java程序设计>第8周学习总结 教材学习内容总结 第十五章 泛型 -- 主要目的是可以建立具有类型安全的集合框架,如链表.散列映射等数据 ...

  8. centos7 防火墙相关命令

    启动:systemctl start firewalld禁用:systemctl stop firewalld重新载入规则:firewall-cmd --reload查看所有打开的端口:firewal ...

  9. DML&&DQL

    数据操纵语言DML(Data Manipulation Language) insert update delete 查询条件用where DQL:select查询语句

  10. uva12307(旋转卡壳)

    省选前练模板系列 #include<iostream> #include<cmath> #include<cstdio> #include<cstring&g ...