Net Core集成Exceptionless分布式日志功能以及全局异常过滤
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 日志记录的封装
首先简单地封装一个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);
}
既然有了接口,那么当然得实现它了
/// <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);
}
}
}
当然实现好了,可别忘了依赖注入哦
//注入ExceptionlessLogger服务
services.AddSingleton<ILoggerHelper, ExceptionlessLogger>();
这时候该写一个全局异常过滤器了
/// <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;
}
}
全局过滤器写好了,怎么让它生效呢,客观别急啊,上正菜
//添加验证
services.AddMvc(options=> {
options.Filters.Add<GlobalExceptionFilter>();
}).AddFluentValidation();
哈哈,没什么说的了,代码都已经写好了,剩下的就是上代码测试结果了。我这里只是简单地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里面,因为我全局过滤器代码里面已经写明了,不明白的回去看代码,然后看接口调用的实现方法。下面上结果:

点进去,看看详细信息:

再测试下使用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分布式日志功能以及全局异常过滤的更多相关文章
- .Net Core 集成ExceptionLess分布式日志框架之本地化部署
前言 公司目前使用的项目中关于日志记录这块,之前一直都是使用的Log4net 存放于后台文件中的,对于异常错误啊,或者需要查看一些详情错误的时候感觉很不方便,要到服务器上去打开日志文件检索错误,降低了 ...
- asp.net core集成CAP(分布式事务总线)
一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET Core 事件总线,分布式事务解决方案:CAP 以及 如何在你的项目中集成 CAP[手把手视频教程],之前也在工作中遇到分布式 ...
- asp.net core全局异常过滤并监控系统BUG将异常信息记录到日志
添加: using Dw.Util.Helper; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Collect ...
- 在.NET Core中使用Exceptionless分布式日志收集框架
一.Exceptionless简介 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,ASP.NET Core,Web Api,Web Forms,WPF, ...
- .NetCore下 Exceptionless 分布式日志的个性化处理
Event Type 在Exceptionless中有 Exception .LogMessage.Broken Links .Feature Usages 接下来就这几种类型分别添加日志记录 Exc ...
- Cap+Exceptionless实现日志消息发布订阅异常情况日志处理及Cap DashBoard授权处理
Dashboard介绍 capOptions.UseDashboard(dashoptions => { dashoptions.AppPath = "applicationpath& ...
- .NET Core微服务之基于Exceptionless实现分布式日志记录
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.Exceptionless极简介绍 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,AS ...
- 分布式日志框架Exceptionless之生产环境部署步骤
Exceptionless 是一个开源的实时的日志收集框架,它将日志收集变得简单易用并且不需要了解太多的相关技术细节及配置.本篇基于我的上一篇<基于Exceptionless实现分布式日志> ...
- CoreWebApi集成Exceptionless
参考博客 https://www.cnblogs.com/akaxb/p/7207827.html 一. Exceptionlessr的安装部署 依乐祝,<ASP.NET Core免费开源分布式 ...
随机推荐
- Windows和Frames之间的切换
一些web应用程序有许多Frames或多个Windows. WebDriver支持使用“switchTo”的方法实现的窗口之间切换. driver.switchTo().window("wi ...
- .gitignore语法
没嘛用 “#”表示注释 “!”表示取消忽略 空行不作匹配 若匹配语句中无“/ ” ,便将其视为一个 glob匹配,如'abc'可以匹配 ' abc' , 'cd/abc' , 'ef/abcde.tx ...
- new Image().src资源重复请求问题
const img = new Image(); img.setAttribute("crossOrigin", 'Anonymous'); img.src = url + '?t ...
- 82、iOS 基本算法
“冒泡排序.选择排序.快速排序.归并排序.逆序.二分查找.求两个整数的最大公约数和最小公倍数.” 一.冒泡排序 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2.对每一对相邻元素作同样的 ...
- linux crontab 命令,最小的执行时间是一分钟,如需要在小于一分钟内重复执行
编写shell脚本实现 crontab.sh #!/bin/bash step=2 #间隔的秒数,不能大于60 for (( i = 0; i < 60; i=(i+step) )); do $ ...
- 28. 实现strStr()
实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在,则返 ...
- MIUI 10以上版本通用线刷ROOT方法
1.高版本系统解锁 (解锁工具下载) http://www.miui.com/unlock/index.html 注意事项:登陆解锁工具的账号必须是登陆小米手机的账号 解锁步骤在解锁工具上有说明,就两 ...
- Runtime "Apache Tomcat v6.0 (3)" is invalid. The JRE could not be found. Edit the server and change the JRE location解决方案
使用eclipse,启动Tomcat时出现The JRE could not be found ,Edit server and change teh JRE location的错误提示! 原因:重装 ...
- linux-ssh登陆导语
用户登录前显示的导语信息(在你选择的文件中配置,例如 /etc/login.warn) 用户成功登录后显示的导语信息(在 /etc/motd 中配置) 如何在用户登录前连接系统时显示消息 当用户连接到 ...
- Jeecg框架简介
官方地址:http://www.jeecg.org/