返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
DevOps

Installation, Configuration, and Usage of ExceptionLess

Preface Exceptionless is an open-source real-time log collection framework. It can be used in applications developed with technologies such as ASP.NET, ASP.NET Core, Web API, Web Forms, WPF, Console, and ASP.NET MVC, and it also provides a REST API that can be used with Javascript and Node.js. (Basically a set of tools for the .NET tech stack) Project address: https://github.com/ex

曦远 (DealiAxy)约 27 分钟
目录9 个章节

Preface

Exceptionless is an open-source real-time log collection framework. It can be used in applications developed with technologies such as ASP.NET, ASP.NET Core, Web API, Web Forms, WPF, Console, and ASP.NET MVC, and it also provides a REST API that can be used with Javascript and Node.js. (Basically a set of tools for the .NET tech stack)

Project address: https://github.com/exceptionless/Exceptionless

It makes log collection simple and easy to use without requiring much knowledge of the related technical details and configuration. For applications with a microservices architecture, establishing a unified log collection system is even more necessary.

To use it, you just need to register an account on its official website and then configure an APIKey in your code. However, the free version has a limited quota, so of course it's better to deploy your own instance. This time I'll still deploy with Docker.

Installation

For Docker deployment, you can download the code from GitHub and build it yourself, or use the official packaged image. For convenience, I'll just use the official packaged image here.

The contents of docker-compose.yml are as follows

As you can see, it contains 5 containers: ExceptionLess App, ExceptionLess Job, elasticsearch, kibana, and Redis

version: '3.7'

services:
  app:
    depends_on:
      - elasticsearch
      - redis
    image: exceptionless/app:latest
    environment:
      EX_AppMode: Production
      EX_ConnectionStrings__Cache: provider=redis
      EX_ConnectionStrings__Elasticsearch: server=http://elasticsearch:9200
      EX_ConnectionStrings__MessageBus: provider=redis
      #EX_ConnectionStrings__Metrics: provider=statsd;server=statsd;
      EX_ConnectionStrings__Queue: provider=redis
      EX_ConnectionStrings__Redis: server=redis,abortConnect=false
      EX_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.pfx
      EX_RunJobsInProcess: 'false'
    ports:
      - 5000:80
      # 关了HTTPS,不需要映射443端口
      #- 5001:443
    volumes:
      - ex_appdata:/app/storage
      - ex_ssldata:/https

  jobs:
    depends_on:
      - app
    image: exceptionless/job:latest
    environment:
      EX_AppMode: Production
      # UI地址,修改这里的IP地址为你的服务器IP地址
      EX_BaseURL: http://你的IP:5000
      EX_ConnectionStrings__Cache: provider=redis
      EX_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=redis
      EX_ConnectionStrings__Redis: server=redis,abortConnect=false
      EX_ConnectionStrings__Storage: provider=folder;path=/app/storage
    volumes:
      - ex_appdata:/app/storage

  elasticsearch:
    image: exceptionless/elasticsearch:7.15.2
    environment:
      discovery.type: single-node
      xpack.security.enabled: 'false'
      ES_JAVA_OPTS: -Xms1g -Xmx1g
    ports:
      - 9200:9200
      - 9300:9300
    volumes:
      - ex_esdata:/usr/share/elasticsearch/data

  kibana:
    depends_on:
      - elasticsearch
    image: docker.elastic.co/kibana/kibana:7.15.2
    ports:
      - 5601:5601

  redis:
    image: redis:6.0-alpine
    ports:
      - 6379:6379

volumes:
  ex_esdata:
    driver: local
  ex_appdata:
    driver: local
  ex_ssldata:
    driver: local

Email Configuration

Email configuration is one of the more troublesome parts; I had to look up some materials before I got it working

Configure them in these two environment variables in the jobs container

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

The gotcha is that the email address in the EX_ConnectionStrings__Email variable needs to have the @ symbol escaped, replacing the @ symbol with %40

Taking my self-hosted email as an example, the email address is: test@dealiaxy.com, so the configuration looks like this

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

Once configured this way, emails can be sent normally~

PS: You can also configure a Webhook to automatically push errors to platforms like WeChat, DingTalk, and the like. I won't go into details.

AspNetCore Integration

The .NET tech stack I mainly use is AspNetCore. For other projects, you can refer to the integration tutorials in the official documentation.

First, create a project in ExceptionLess and copy the APIKey

Edit the AspNetCore project's appsettings.json file and add the following configuration

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

Then edit Program.cs to add the service and middleware

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

That's the integration step done

Recording Events

Events in Exceptionless have the following types:

  • Log messages: recorded logs, which can be any text content
  • Feature usage: records of feature usage, such as API call statistics
  • Exceptions: records of exception information
  • Broken links: recorded when the page being accessed does not exist

In addition, each event can also have tags, object, UserIdentity, Description, and similar information attached. With the help of this information, subsequent troubleshooting becomes more convenient.

The simplest usage

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

The CreateLog method returns an object of type EventBuilder. Most subsequent operations on this object support method chaining.

You can chain it in a single line of code as shown above, or do it like this

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

There is a lot of information that can be attached to an event. Below are some examples provided by the official site

// 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.")

For example, after setting user information with SetUserIdentity, you can see the username in the exception list, as shown below

1658417495126

Use AddTags to add tags, which are displayed as badges on the page

1658417640010

There's also AddObject, which is very convenient—you can pass an object in directly. Since C# has anonymous objects, it's even more convenient. You can see it on the "Extended Data" tab of the page; ExceptionLess will process the object into a table format, which is more intuitive

1658417782570

Submitting Error Information

ExceptionLess provides extension methods for the Exception object

You can catch an error and Submit it directly

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

Of course, you can also attach some extra information

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

Integrating Logging Frameworks

Besides submitting events manually, it also provides ways to integrate with existing logging frameworks

Just install the corresponding NuGet package (I did a quick search; at least the support for Log4net and NLog should be fine)

1658418198887

Taking integration with Log4net as an example, first install the NuGet package: Exceptionless.Log4net

Here's a simple Log4net configuration

<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>

Can it be used with other languages?

Although official support is only for the .NET platform and the frontend (JS calls, Vue 3), ExceptionLess provides a large number of HTTP APIs. If you want to use it in projects in other languages, you only need to call the corresponding APIs, and you can even wrap them yourself.

However, for projects in other languages, I recommend using Sentry (which I'll introduce in the next article). It supports more languages/frameworks. ExceptionLess's advantage is that it integrates better with .NET platforms such as AspNetCore, and the results pages are more intuitive~

That said, ExceptionLess's API documentation (Swagger) is at /docs/index.html. Visit it based on your deployment address and you'll see it; it basically has all the features you need.

References

_EOF_

Installation, Configuration, and Usage of ExceptionLess

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…