前言

Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,ASP.NET Core,Web API,Web Forms,WPF,Console,ASP.NET MVC 等技术开发的应用程序中,并且提供了REST接口可以应用在 Javascript,Node.js 中。(基本就是.Net技术栈的一套东西)

项目地址:https://github.com/exceptionless/Exceptionless

它将日志收集变得简单易用并且不需要了解太多的相关技术细节及配置,对于微服务架构的应用程序来说,统一的日志收集系统的建立更是有必要。

要使用的话只需要在其官网上注册个账号,然后在代码中配置一下APIKey就可以了,不过免费版额度有限,当然还是自己部署一套比较好,这次依然使用docker部署

安装

docker部署可以在GitHub下载代码自己构建,也可以用官方打包好的镜像,为了方便这里我直接使用官方打包的镜像

docker-compose.yml 内容如下

可以看到其中包含5个容器:ExceptionLess App、ExceptionLess Job、elasticsearch、kibana、Redis

version: '3.7'services:app:depends_on:- elasticsearch- redisimage: exceptionless/app:latestenvironment:EX_AppMode: ProductionEX_ConnectionStrings__Cache: provider=redisEX_ConnectionStrings__Elasticsearch: server=http://elasticsearch:9200EX_ConnectionStrings__MessageBus: provider=redis#EX_ConnectionStrings__Metrics: provider=statsd;server=statsd;EX_ConnectionStrings__Queue: provider=redisEX_ConnectionStrings__Redis: server=redis,abortConnect=falseEX_ConnectionStrings__Storage: provider=folder;path=/app/storage# 官方配置默认包含HTTPS,我把它关了#ASPNETCORE_URLS: http://+;https://+ASPNETCORE_URLS: http://+# 关了HTTPS,这个端口也不用配置了#ASPNETCORE_HTTPS_PORT: 5001# 关了HTTPS,证书也不用配置#ASPNETCORE_Kestrel__Certificates__Default__Password: password#ASPNETCORE_Kestrel__Certificates__Default__Path: /https/aspnetapp.pfxEX_RunJobsInProcess: 'false'ports:- 5000:80# 关了HTTPS,不需要映射443端口#- 5001:443volumes:- ex_appdata:/app/storage- ex_ssldata:/httpsjobs:depends_on:- appimage: exceptionless/job:latestenvironment:EX_AppMode: Production# UI地址,修改这里的IP地址为你的服务器IP地址EX_BaseURL: http://你的IP:5000EX_ConnectionStrings__Cache: provider=redisEX_ConnectionStrings__Elasticsearch: server=http://elasticsearch:9200# 邮件配置EX_ConnectionStrings__Email: smtps://邮箱地址:密码@SMTP服务器:端口EX_SmtpFrom: 发件邮箱地址EX_ConnectionStrings__MessageBus: provider=redis#EX_ConnectionStrings__Metrics: provider=statsd;server=statsd;EX_ConnectionStrings__Queue: provider=redisEX_ConnectionStrings__Redis: server=redis,abortConnect=falseEX_ConnectionStrings__Storage: provider=folder;path=/app/storagevolumes:- ex_appdata:/app/storageelasticsearch:image: exceptionless/elasticsearch:7.15.2environment:discovery.type: single-nodexpack.security.enabled: 'false'ES_JAVA_OPTS: -Xms1g -Xmx1gports:- 9200:9200- 9300:9300volumes:- ex_esdata:/usr/share/elasticsearch/datakibana:depends_on:- elasticsearchimage: docker.elastic.co/kibana/kibana:7.15.2ports:- 5601:5601redis:image: redis:6.0-alpineports:- 6379:6379volumes:ex_esdata:driver: localex_appdata:driver: localex_ssldata:driver: local

邮件配置

邮件配置是比较麻烦的地方,我查了一些资料才解决

jobs容器中的这两个环境变量里配置

EX_ConnectionStrings__Email: smtps://邮箱地址:密码@SMTP服务器:端口EX_SmtpFrom: 发件邮箱地址

有坑的地方就是EX_ConnectionStrings__Email变量的邮箱地址需要对@符号进行转义,用%40代替@符号

以我的自建邮箱为例,邮箱地址是:test@dealiaxy.com,那么配置就是这样

EX_ConnectionStrings__Email: smtps://test%40dealiaxy.com:密码@SMTP服务器:端口EX_SmtpFrom: test@dealiaxy.com

这样配置完成就可以正常发邮件了~

PS:还可以配置Webhook实现报错自动推送到微信、钉钉之类的平台,不细说了

AspNetCore集成

我主要使用的.Net技术栈是AspNetCore,其他项目可以参考官方文档的集成教程

首先在ExceptionLess中创建一个项目,把APIKey复制下来

编辑AspNetCore项目的appsettings.json文件,增加配置

"Exceptionless": {"ServerUrl": "http://12.0.0.1:5000","ApiKey": "Rajo99MksQTS6zZK81238jTkNHNOQP33A3iW45JC"}

然后编辑Program.cs,添加服务和中间件

builder.Services.AddExceptionless(builder.Configuration);app.UseExceptionless();

集成这一步就搞定了

记录事件

Exceptionless中的事件有以下几种类型:

  • 日志消息:记录的日志,可以是任何文本内容
  • 特性使用:功能使用量的记录,例如接口调用情况等
  • 异常情况:记录异常的信息
  • 失效链接:当被访问的页面不存在时进行记录

除此之外,每个事件还可以附加tags、object、UserIdentity、Description之类的信息,有这些信息的辅助可以方便后续排查问题。

最简单的使用

ExceptionlessClient.Default.CreateLog("message").Submit();

CreateLog方法会放回一个EventBuilder类型的对象,之后在这个对象上进行大部分操作支持链式调用

可以像上面那样一行代码链式调用,也可以这样

// 先创建var eventBuilder = ExceptionlessClient.Default.CreateLog("message");// 再来慢慢添加eventBuilder.AddObject(...);eventBuilder.AddTags(...);// 最后提交eventBuilder.Submit();

可以附加到事件中的信息有很多,下面是官网提供的一些例子

// Set the reference id of the event so we can search for it later (reference:id).// This will automatically be populated if you call ExceptionlessClient.Default.Configuration.UseReferenceIds();.SetReferenceId(Guid.NewGuid().ToString("N"))// Add the order object but exclude the credit number property..AddObject(order, "Order", excludedPropertyNames: new [] { "CreditCardNumber" }, maxDepth: 2)// Set the quote number..SetProperty("Quote", 123)// Add an order tag..AddTags("Order")// Mark critical..MarkAsCritical()// Set the coordinates of the end user..SetGeo(43.595089, -88.444602)// Set the user id that is in our system and provide a friendly name..SetUserIdentity(user.Id, user.FullName)// Set the users description of the error..SetUserDescription(user.EmailAddress, "I tried creating an order from my saved quote.")

例如,使用SetUserIdentity设置了用户信息,在异常列表就可以看到用户名,如图

AddTags添加标签,在页面中以badge的形式显示

还有AddObject,很方便,可以直接把对象传进去,由于C#语言有匿名对象,那就更方便了,在页面上的“扩展数据”标签页上可以看到,ExceptionLess会把对象处理成表格形式,更加直观

提交错误信息

ExceptionLess提供了Exception对象的扩展方法

可以catch到错误后直接Submit

try {}catch (Exception ex) {ex.ToExceptionless().Submit();}

当然也可以附加一些信息进去

ex.ToExceptionless().AddObject(...).Submit();

集成日志框架

除了手动提交事件,它还提供了与现有日志框架集成的方法

安装对应的nuget包就行(简单搜了一下,至少对Log4net和NLog的支持应该是没啥问题的)

以与Log4net集成为例,首先安装nuget包:Exceptionless.Log4net

附上一个简单的Log4net配置

<log4net><appender name="exceptionless" type="Exceptionless.Log4net.ExceptionlessAppender,Exceptionless.Log4net"><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline"/></layout></appender><root><level value="DEBUG"/><appender-ref ref="exceptionless"/></root></log4net>

其他语言能用吗?

虽然官方只支持.Net平台和前端(js调用、vue3),不过ExceptionLess提供了大量的HTTP接口,想要在其他语言的项目中使用,只需要调用对应的接口就行了,甚至可以自己封装一个

不过在其他语言的项目中,我推荐使用Sentry(下一篇文章要介绍的),支持的语言/框架更多,ExceptionLess的优势在于和AspNetCore这类.Net平台的结合更好,结果页面更直观~

话说回来,ExceptionLess的接口文档(Swagger)在/docs/index.html,根据部署地址访问就能看到,里面你要的功能基本都有。

参考资料