日志收集框架 Exceptionless
前言
从去年就答应过Eric(Exceptionless的作者之一),在中国会帮助给 Exceptionless 做推广,但是由于各种原因一直没有做这件事情,在此对Eric表示歉意。:)
Exceptionless 简介
Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,ASP.NET Core,Web Api,Web Forms,WPF,Console,MVC 等技术栈的应用程序中,并且提供了Rest接口可以应用在 Javascript,Node.js 中。它将日志收集变得简单易用并且不需要了解太多的相关技术细节及配置。
在以前,我们做日志收集大多使用 Log4net,Nlog 等框架,在应用程序变得复杂并且集群的时候,可能传统的方式已经不是很好的适用了,因为收集各个日志并且分析他们将变得麻烦而且浪费时间。
现在Exceptionless团队给我们提供了一个更好的框架来做这件事情,我认为这是非常伟大并且有意义的,感谢他们。
就让我们一起来看看吧。
GitHub:https://github.com/exceptionless/Exceptionless
Getting Started
一、首先,需要去官网注册一个帐号(打不开的同学你懂的),注册完成之后登录系统。
二、按照提示,添加一个你的项目:
然后可以看到一个下拉菜单,选择项目的类型,可以看到 Exceptionless支持很多种项目。我们来选择一个 ASP.NET Core 的项目:
三、选择完成之后,会有一个详细的步骤,说明了如何做项目中使用。
- 首先,使用 NuGet 添加一个包,名字叫
Exceptionless.AspNetCore
。 - 在 ASP.NET Core 项目中,打开
startup.cs
文件,找到Configure()
方法,添加如下:
using Exceptionless;
......
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// xxxxx 处填写上图画红线部分的key
app.UseExceptionless("xxxxxxxxxxxxxxxxxxxxxxxxxx");
app.UseStaticFiles();
app.UseMvc();
}
至此,Exceptionless 已经可以在你的项目中工作了,它会自动记录项目中的异常情况。
在 Exceptionless 查看日志
在 Getting Started 步骤,我们创建了一个 ASP.NET Core 项目,下面我们来运行一下,看看它是怎么工作的吧。
打开 HomeController.cs
文件,修改About
的action方法,人为的制造一个异常信息:
public IActionResult About() {
throw new Exception("test exception");
return View();
}
接下来,刷新 Exceptionless的页面,在 Dashboard 主面板中,可以看到关于整个项目的一个异常情况,并且分别以几种方式列了出来,其中包括分布图,最频繁的异常,最近的异常等等。
这个我们刚才在Abount Action中制造的一个异常,Exceptionless已经记录了下来,点进去之后可以看一下详情:
在上图中,可以很直观的看出异常的一些具体信息,除了一些基本的异常类型、时间和堆栈外,还包括访问者的坐标、IP地址、发生异常的URL地址、浏览器信息,操作系统、甚至发生异常时请求的Cookie值。
向 Exceptionless 发送事件
除了我们所熟悉的异常信息外,Exceptionless 还可以记录很多种类的其他信息,这些信息统称做事件(Event)。
在Exceptionless 中,有这几类事件: Log (日志)、Feature Usages(功能用途)、404、Custom Event(自定义事件)。
Exceptionless 中发送不同类型事件很简单,代码如下:
using Exceptionless;
// 发送日志
ExceptionlessClient.Default.SubmitLog("Logging made easy");
// 你可以指定日志来源,和日志级别。
// 日志级别有这几种: Trace, Debug, Info, Warn, Error
ExceptionlessClient.Default.SubmitLog(typeof(Program).FullName, "This is so easy", "Info");
ExceptionlessClient.Default.CreateLog(typeof(Program).FullName, "This is so easy", "Info").AddTags("Exceptionless").Submit();
// 发送 Feature Usages
ExceptionlessClient.Default.SubmitFeatureUsage("MyFeature");
ExceptionlessClient.Default.CreateFeatureUsage("MyFeature").AddTags("Exceptionless").Submit();
// 发送一个 404
ExceptionlessClient.Default.SubmitNotFound("/somepage");
ExceptionlessClient.Default.CreateNotFound("/somepage").AddTags("Exceptionless").Submit();
// 发生一个自定义事件
ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Low Fuel", Type = "racecar", Source = "Fuel System" });
手动发送一个已处理的异常
有时候,我们在程序代码中显式的处理一些异常,这个时候可以手动的来将一些异常信息发送到Exceptionless。
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()
// 为事件设定一个编号,以便于你搜索
.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)
// 设置触发异常的用户信息
.SetUserIdentity(user.Id, user.FullName)
// 设置触发用户的一些描述
.SetUserDescription(user.EmailAddress, "I tried creating an order from my saved quote.")
// 发送事件
.Submit();
}
统一处理发送的事件
你可以默认的为ExceptionlessClient.Default.SubmittingEvent
绑定额外的事件,来统一自定义一些处理。
ExceptionlessClient.Default.SubmittingEvent += OnSubmittingEvent;
private void OnSubmittingEvent(object sender, EventSubmittingEventArgs e) {
// 仅处理未被处理过的异常
if (!e.IsUnhandledError)
return;
// 忽略404事件
if (e.Event.IsNotFound()) {
e.Cancel = true;
return;
}
// 获取error对象
var error = e.Event.GetError();
if (error == null)
return;
// 忽略 401 或 `HttpRequestValidationException`异常
if (error.Code == "401" || error.Type == "System.Web.HttpRequestValidationException") {
e.Cancel = true;
return;
}
// 忽略不是指定命名空间代码抛出的异常
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("Order");
e.Event.MarkAsCritical();
e.Event.SetUserIdentity(user.EmailAddress);
}
配合使用 NLog 或 Log4Net
有时候,程序中需要对日志信息做非常详细的记录,比如在开发阶段。这个时候可以配合 log4net 或者 nlog 来联合使用 exceptionless,详细可以查看这个 示例。
如果你的程序中有在短时间内生成大量日志的情况,比如一分钟产生上千的日志。这个时候你需要使用内存存储(in-memory store)事件,这样客户端就不会将事件系列化的磁盘,所以会快很多。这样就可以使用Log4net 或者 Nlog来将一些事件存储到磁盘,另外 Exceptionless 事件存储到内存当中。
using Exceptionless;
ExceptionlessClient.Default.Configuration.UseInMemoryStorage();
总结
本篇主要是对 Exceptionless 做了一个介绍,然后介绍了 Exceptionless 是怎么发送日志的。
因为目前 Exceptionless 的站点在国外,并且站点里面调用了一些 google 的 api,所以可能在中国访问起来有点麻烦,大家可以先科学上网体验一下功能。毕竟 Exceptionless 是开源免费的并且服务端也是可以本地部署的。
如果您觉得本文对您有帮助,想让更多人了解Exceptionless,感谢您帮忙点的【推荐】。
如果您对 Exceptionless 感兴趣或者是想学习 Exceptionless 的代码,可以加入群。
Exceptionless QQ群:330316486。