分散式日誌-ExceptionLess
阿新 • • 發佈:2020-10-07
Exceptionless 是一個開源的實時的日誌收集框架,它可以應用在基於 ASP.NET,ASP.NET Core,Web Api,Web Forms,WPF,Console,MVC 等技術棧的應用程式中,並且提供了Rest介面可以應用在 Javascript,Node.js 中。它將日誌收集變得簡單易用並且不需要了解太多的相關技術細節及配置。 在以前,我們做日誌收集大多使用 Log4net,Nlog 等框架,在應用程式變得複雜並且叢集的時候,可能傳統的方式已經不是很好的適用了,因為收集各個日誌並且分析他們將變得麻煩而且浪費時間。 現在Exceptionless團隊給我們提供了一個更好的框架來做這件事情。 使用方式1、可以使用官方的服務,但是試用版有限制,每天最多3000條錯誤日誌,如需更多使只能購買付費。 2、所以一般我們都是自己搭建exceptionless服務; 具體搭建方式可以見 https://github.com/exceptionless/Exceptionless 服務搭建完畢就可以在客戶端呼叫,這裡我們結合nlog來實現; 1、新建專案,引用 <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="LogDashboard" Version="1.4.5" /> <PackageReference Include="NLog.Web.AspNetCore" Version="4.9.2" /> <PackageReference Include="NLog" Version="4.7.2" /> <PackageReference Include="Exceptionless.AspNetCore" Version="4.4.0" /> <PackageReference Include="Exceptionless.NLog" Version="4.4.0" /> </ItemGroup> <ItemGroup> <Content Update="nlog.config"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup> </Project> 2、在服務端申請key,在appsettings.json配置 { "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Trace", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Exceptionless": { "ApiKey": "xxxxxxxxxxxxxxxxxxxxxxxx", "ServerUrl": "http://localhost:50000" } } 3、Program.cs配置 using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NLog.Web; using System; namespace WebApplicationnlog { public class Program { public static void Main(string[] args) { //https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-3 //https://blog.csdn.net/sD7O95O/article/details/78097249 var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); try { logger.Debug("init main"); CreateHostBuilder(args).Build().Run(); } catch (Exception exception) { //NLog: catch setup errors logger.Error(exception, "Stopped program because of exception"); throw; } finally { // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) NLog.LogManager.Shutdown(); } } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) .ConfigureLogging(logging => { logging.ClearProviders(); logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); }) .UseNLog(); // NLog: Setup NLog for Dependency injection } } 4、Startup.cs 配置 using Exceptionless; using LogDashboard; using LogDashboard.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace WebApplicationnlog { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); //services.AddLogDashboard(); services.AddLogDashboard(opt => { opt.CustomLogModel<RequestTraceLogModel>(); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseLogDashboard(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); ExceptionlessClient.Default.Configuration.ApiKey = Configuration.GetSection("Exceptionless:ApiKey").Value; // ExceptionlessClient.Default.Configuration.ServerUrl = Configuration.GetSection("Exceptionless:ServerUrl").Value; app.UseExceptionless(); } } } 5、nlog.config配置 <?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" throwConfigExceptions="true" internalLogLevel="Debug" internalLogToTrace="true"> <extensions> <add assembly="Exceptionless.NLog" /> </extensions> <targets> <!--<target xsi:type="file" name="logdashboardTraceLog" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate}||${level}||${logger}||${message}||${exception:format=ToString:innerFormat=ToString:maxInnerExceptionLevel=10:separator=\r\n} || ${aspnet-traceidentifier} ||end" />--> <target xsi:type="file" name="logdashboardFile" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate}||${level}||${logger}||${message}||${exception:format=ToString:innerFormat=ToString:maxInnerExceptionLevel=10:separator=\r\n}||end" /> <target xsi:type="File" name="logfile" fileName="${basedir}/logs/${shortdate}/${level}/${callsite:className=true:methodName=true:skipFrames=1}.log" layout="${longdate} [${level:uppercase=true}] ${callsite:className=true:methodName=true:skipFrames=1} ${message} ${exception} @${callsite:fileName=true:includeSourcePath=true}" maxArchiveFiles="10" archiveAboveSize="10240" archiveEvery="Day" /> <target xsi:type="File" name="sqllogfile" fileName="${basedir}/logs/${shortdate}/${level}.log" layout="${longdate} [${level:uppercase=true}] ${callsite:className=true:methodName=true:skipFrames=1} ${stacktrace} ${message} ${exception} @${callsite:fileName=true:includeSourcePath=true}" maxArchiveFiles="10" archiveAboveSize="10240000" archiveEvery="Day" /> <target xsi:type="ColoredConsole" name="console" layout="${longdate} [${level:uppercase=true}] ${callsite:className=true:methodName=true:skipFrames=1} ${message} ${exception} @${callsite:fileName=true:includeSourcePath=true}" /> <target xsi:type="Null" name="blackhole" /> <target xsi:type="Exceptionless" name="exceptionless"> <field name="host" layout="${machinename}" /> <field name="identity" layout="${identity}" /> <!-- <field name="windows-identity" layout="${windows-identity:userName=True:domain=False}" />--> <field name="process" layout="${processname}" /> </target> </targets> <rules> <!--<logger name="*" minlevel="Debug" writeTo="logdashboardTraceLog" />--> <logger name="*" minlevel="ERROR" writeTo="logdashboardFile" /> <!-- 除非除錯需要,把 .NET Core 程式集的 Debug 輸出都遮蔽 Trace -》Debug-》 Information -》Warning-》 Error-》 Critical--> <logger name="Microsoft.*" minLevel="Trace" writeTo="blackhole" final="true" /> <!-- 除非除錯需要,把系統的 Debug 輸出都遮蔽 --> <logger name="System.*" minLevel="Trace" writeTo="blackhole" final="true" /> <logger name="*" minlevel="Info" writeTo="logfile,console" /> <logger name="*" minlevel="Debug" maxlevel="Debug" writeTo="sqllogfile" /> <logger name="*" minlevel="ERROR" writeTo="exceptionless" /> </rules> </nlog> 6、最後測試產生日誌 using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Diagnostics; using System.Net.Http; using System.Threading.Tasks; using WebApplicationnlog.Models; namespace WebApplicationnlog.Controllers { //https://github.com/liangshiw/LogDashboard public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; _logger.LogDebug(1, "NLog injected into HomeController"); } public async Task<IActionResult> Index() { _logger.LogInformation("Hello, this is the index!"); _logger.LogError(exception: new Exception("test"), message: ""); var client = new HttpClient(); await client.GetStringAsync("https://www.cnblogs.com/"); return View(); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } } } 程式碼地址: https://github.com/conanl5566/mydemo/tree/master/log/Exceptionless.NLog.Demo