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. java添加菜单项目

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

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

  3. JavaSE编程题

    Test1–取出一个字符串中字母出现的次数.如:字符串:”abcdekka27qoq”,输出格式为:a(2)b(1)k(2)… Test2–假如我们在开发一个系统时需要对员工进行建模,[员工]包含3个 ...

  4. iOS 关于重定向的那些事(NSURLProcotol-WKWebView)

    重定向定义:重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向.域名的重定向.路由选择的变化也是对数据报文经由路径的一种重定向).   NSURLProt ...

  5. dubbo入门学习 四 注册中心 zookeeper入门

    一.Dubbo支持的注册中心 1. Zookeeper 1.1 优点:支持网络集群 1.2 缺点:稳定性受限于Zookeeper 2. Redis 2.1 优点:性能高. 2.2 缺点:对服务器环境要 ...

  6. 关于python的展望

    在未接触这门课程以前,我完全对编程一类的操作毫无兴趣.但在短短的两星期时间里,我改变了想法,原因有二.其一是老师幽默,其二是课程实用性高.我希望课程以后可以继续沿用现在由浅入深,给予足够提示的方式,引 ...

  7. JS中的同步和异步

    javascript语言是一门“单线程”的语言,不像java语言,类继承Thread再来个thread.start就可以开辟一个线程,所以,javascript就像一条流水线,仅仅是一条流水线而已,要 ...

  8. C#遍历SharePoint文档库下所有文档包括文档库中子文件夹下所有文档

    /// <summary> /// 获取取子文件下所有文件 /// </summary> /// <param name="web"></ ...

  9. VUE项目 npm run build卡住不动,也不报错

    npm config set registry http://registry.cnpmjs.org try again npm run build 居然能动了....

  10. .NET工行E生活接入AES加密算法的吐槽-2018

    工行E生活V2版本AES加密算法 吐槽一下工行的java算法,真的是非标准的,参考了java代码,还参考了php代码终于搞定了. 真的是很坑,很坑.中间还涉及到多重加密之类的,一行行把代码翻译成C#代 ...