ASP .NET Core 集成 Exceptionless 日志
Exceptionless简介
Exceptionless是一款分布式日志管理框架,它可以统一收集管理并展示出来程序的日志,这样的话减少了传统开发过程中还需要去服务器查找日志的痛苦,大大提升对程序的运维效率。 Exceptionless依赖于Redis和Elasticsearch。
官网地址:https://exceptionless.com/
官方文档地址:https://exceptionless.com/docs/
官方Github地址:https://github.com/exceptionless/Exceptionless
Docker镜像地址:https://hub.docker.com/r/exceptionless/exceptionless
日志搜索文档:https://exceptionless.com/docs/filtering-and-searching
目前支持JavaScript, Node, .NET Core, .NET相关应用程序的异常信息采集。为何仅支持.Net .Net Core和JS相关的?原因很简单,Exceptionless是基于.NET Core开发的。如果你有别的语言的开发需求也想使用Exceptionless,这个时候不要气馁,因为Exceptionless本质是基于http接口的形式上报数据的,这个可在官方文档上找到如何使用http上报日志信息相关
官方文档api地址:https://exceptionless.com/docs/api/api-getting-started/
api官方文档地址:https://api.exceptionless.io/
api官方swagger地址:https://api.exceptionless.io/docs/index.html
部署Exceptionless
官网提供了两种使用的方式
- 在官方网站注册账号然后获取apiKey,这样的话不用自己搭建Exceptionless,而是将日志直接收集上报到Exceptionless服务器上。但是,一般基于安全和性能考虑,这种方式并不常用。
- 自建Exceptionless服务,也是本篇我们要使用的方式。之前的低版本支持在window服务器上自建服务,但是高版本已经是基于docker的方式构建了。而使用docker的方式也是我个人日常学习中比较喜欢的方式。
基于docker-compose
部署。官方yml文件地址
https://github.com/exceptionless/Exceptionless/blob/main/docker-compose.yml
https://github.com/exceptionless/Exceptionless/blob/main/samples/docker-compose.yml
简化版docker-compose.yml
version: '3.7'
services:
app:
depends_on:
- elasticsearch
image: exceptionless/app:7.2.1
environment:
EX_AppMode: Production
EX_ConnectionStrings__Cache: provider=redis
EX_ConnectionStrings__Elasticsearch: server=http://elasticsearch:9200
EX_ConnectionStrings__MessageBus: provider=redis
EX_ConnectionStrings__Queue: provider=redis
EX_ConnectionStrings__Redis: server=192.168.1.5:6379,abortConnect=false
EX_RunJobsInProcess: 'false'
ports:
- 5000:80
volumes:
- appdata:/app/storage
jobs:
depends_on:
- app
image: exceptionless/job:7.2.1
environment:
EX_AppMode: Production
EX_BaseURL: http://192.168.1.5:5000
EX_ConnectionStrings__Cache: provider=redis
EX_ConnectionStrings__Elasticsearch: server=http://elasticsearch:9200
EX_ConnectionStrings__MessageBus: provider=redis
EX_ConnectionStrings__Queue: provider=redis
EX_ConnectionStrings__Redis: server=192.168.1.5:6379,abortConnect=false
EX_ConnectionStrings__Storage: provider=folder;path=/app/storage
volumes:
- appdata:/app/storage
elasticsearch:
image: exceptionless/elasticsearch:7.15.2
environment:
discovery.type: single-node
xpack.security.enabled: 'false'
xpack.ml.enabled: 'false'
ES_JAVA_OPTS: -Xms1g -Xmx1g
ports:
- 9200:9200
- 9300:9300
volumes:
- esdata7:/usr/share/elasticsearch/data
volumes:
esdata7:
driver: local
appdata:
driver: local
yml
下载到服务器后直接docker-compose up -d
启动站点
Exceptionless 使用
访问站点http://192.168.1.5:5000/
,首次登陆使用注册邮箱账号
注册成功后登陆就可以看到主界面了
新建一个组织
组织中新建一个项目,项目与组织绑定关系是为了后续组织邀请其他用户方便管理查看日志
输入项目名称
项目类型选择ASP.NET Core,然后选择管理项目
进入项目详情,选择API秘钥,在ASP.NET Core项目中需要此秘钥配置
ASP .NET Core 集成 Exceptionless
appsettings.json
添加Exceptionless
配置
"Exceptionless": {
"ServerUrl": "http://192.168.1.5:5000",
"ApiKey": "2oWkeKEw0gKqb4gu2vsMvr4b3mK1V47fshjaYyJ2"
}
使用官方包集成
Neget安装包
Exceptionless.AspNetCore
Startup.cs
添加配置
services.AddExceptionless(Configuration);
//或者
//ExceptionlessClient.Default.Configuration.ApiKey = Configuration["ExceptionLess:ApiKey"];
//ExceptionlessClient.Default.Configuration.ServerUrl = Configuration["ExceptionLess:ServerUrl"];
services.AddSingleton<ILogger, ExceptionLessLogger>();
app.UseExceptionless();
或者ConfigureExceptionlessExtensions
添加
using Exceptionless;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApp1
{
public static class ConfigureExceptionlessExtensions
{
private static string ServerName = "";
public static void ConfigureExceptionless(this IServiceCollection services, IConfiguration configuration)
{
string apiKey = configuration["exceptionless:ApiKey"];
string serverUrl = configuration["exceptionless:ServerUrl"];
ServerName = configuration["GlobalTags:server"];
if (!string.IsNullOrWhiteSpace(apiKey) && !string.IsNullOrWhiteSpace(serverUrl))
{
ExceptionlessClient.Default.Configuration.ApiKey = apiKey;
ExceptionlessClient.Default.Configuration.ServerUrl = serverUrl;
//事件添加Tag
ExceptionlessClient.Default.SubmittingEvent += Default_SubmittingEvent;
}
}
private static void Default_SubmittingEvent(object sender, EventSubmittingEventArgs e)
{
if (!string.IsNullOrWhiteSpace(ServerName)) e.Event.Tags.Add(ServerName);
}
}
}
添加日志
ExceptionlessClient.Default.CreateLog("GUID", LogLevel.Warn).AddTags("tag").Submit();
扩展日志帮助类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Exceptionless;
using Exceptionless.Logging;
namespace ExceptionlessDemo
{
public static class Extensions
{
/// <summary>
/// 跟踪
/// </summary>
public static void TraceExceptionless(this Microsoft.Extensions.Logging.ILogger log, string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Trace).AddTags(tags).Submit();
}
/// <summary>
/// 信息
/// </summary>
public static void InfoExceptionless(this ILogger log, string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Info).AddTags(tags).Submit();
}
/// <summary>
/// 警告
/// </summary>
public static void WarnExceptionless(this Microsoft.Extensions.Logging.ILogger log, string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Warn).AddTags(tags).Submit();
}
/// <summary>
/// 错误
/// </summary>
public static void ErrorExceptionless(this ILogger log, string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Error).AddTags(tags).Submit();
}
/// <summary>
/// 错误
/// </summary>
public static void ErrorExceptionless(this Microsoft.Extensions.Logging.ILogger log, Exception exception, params string[] tags)
{
ExceptionlessClient.Default.CreateException(exception).AddTags(tags).Submit();
}
}
public interface ILogger
{
void Trace(string message, params string[] args);
void Debug(string message, params string[] args);
void Info(string message, params string[] args);
void Warn(string message, params string[] args);
void Error(string message, params string[] args);
void Error(Exception ex, params string[] args);
}
public class ExceptionLessLogger : ILogger
{
/// <summary>
/// Trace
/// </summary>
public void Trace(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Trace).AddTags(tags).Submit();
}
/// <summary>
/// Debug
/// </summary>
public void Debug(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Debug).AddTags(tags).Submit();
}
/// <summary>
/// Info
/// </summary>
public void Info(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Info).AddTags(tags).Submit();
}
/// <summary>
/// Warn
/// </summary>
public void Warn(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Warn).AddTags(tags).Submit();
}
/// <summary>
/// Error
/// </summary>
public void Error(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Error).AddTags(tags).Submit();
}
/// <summary>
/// 错误
/// </summary>
public void Error(Exception exception, params string[] tags)
{
ExceptionlessClient.Default.CreateException(exception).AddTags(tags).Submit();
}
}
//日志Tags
public static class LogTags
{
public const string LogTag = "TestProjectLogTag";
}
}
Controllers发送日志
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ExceptionlessDemo.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
//建议使用 _logger2
public ILogger<WeatherForecastController> Logger { get; set; }
private readonly ILogger _logger2;
public WeatherForecastController(ILogger<WeatherForecastController> logger, ILogger logger2)
{
_logger2 = logger2;
Logger = logger;
//Logger = NullLogger<WeatherForecastController>.Instance;
}
[HttpGet]
public string Get()
{
Logger.WarnExceptionless("微软日志扩展", "LogInformation");
_logger2.Debug("12321321", "Debug1");
return Guid.NewGuid().ToString();
}
}
}
使用Serilog集成
Neget安装包
Serilog.AspNetCore
Serilog.Sinks.Exceptionless
Program.cs
添加配置
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using System.Text;
namespace ExceptionlessDemo
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseSerilog(ConfigureSerilog);
static void ConfigureSerilog(HostBuilderContext context, LoggerConfiguration logger)
{
var apiKey = context.Configuration["ExceptionLess:ApiKey"];
var serverUrl = context.Configuration["ExceptionLess:ServerUrl"];
logger
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
.Enrich.FromLogContext()
//添加Exceptionless
.WriteTo.Exceptionless(apiKey, serverUrl);
}
}
}
查看日志
参考文档
https://www.cnblogs.com/wucy/p/14401650.html
https://www.dongchuanmin.com/net/3230.html