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. SQL 语句中 where 条件后 写上1=1 的意思

    这段代码应该是由程序(例如Java)中生成的,where条件中 1=1 之后的条件是通过 if 块动态变化的.例如:  String sql="select * from table_nam ...

  2. Gitlab使用时的一些注意事项

    1 gitlab-runner 不选中,在commit没有tab的时候,runner不会进行运行 2 在新安装的gitlab的环境上更改@localhost为远程地址 2.1  vim /opt/gi ...

  3. C# 结构体和List<T>类型数据转Json数据保存和读取

    C#  结构体和List<T>类型数据转Json数据保存和读取 一.结构体转Json public struct FaceLibrary { public string face_name ...

  4. 绑定hover事件

    <label> <span id="pattern">实战模式</span> <div class='tab' style="t ...

  5. C语言中结构体(struct)的几种初始化方法

    转自https://www.jb51.net/article/91456.htm     本文给大家总结的struct数据有3种初始化方法 1.顺序 2.C风格的乱序 3.C++风格的乱序 下面通过示 ...

  6. 从今天开始慢慢阅读java9源码决心的声明。

    我从很早的时候就好奇java的源码了,因为有使用者就有制作者. 在校期间使用了java两年多的我却不知道java里面的任何东西. 这个寒假前我无意之间看到了java9出现的新闻,网上查询到原来源码就隐 ...

  7. Activiti工作流数据库表详细介绍

    Activiti的后台是有数据库的支持,所有的表都以ACT_开头. 第二部分是表示表的用途的两个字母标识. 用途也和服务的API对应. ACT_RE_*: 'RE'表示repository. 这个前缀 ...

  8. STM32 HAL库的使用心得

    1.I2C函数中HAL_I2C_Mem_Write和HAL_I2C_Master_Transmit有啥区别?{ 使用HAL_I2C_Mem_Write等于 先使用HAL_I2C_Master_Tran ...

  9. 我的C#跨平台之旅(一):从 Hello World 开始

    创建一个“控制台应用程序”,目标框架为“.NET Framework 4.5”,并移除无关的文件及引用,仅保留对 “system.dll”的引用:其中工程文件中核心内容如下: 使用NuGet添加如下引 ...

  10. gii配置

    下载完成后不要设置urlManager http://zjm.testyii.com/index.php?r=gii 即可进入gii页面 或者是 将'urlManager'=> [ 'enabl ...