一. 起始
進入NetCore時代,日志的使用有了很大的變化,因為跨平台以及虛擬化技術的使用,日志不能夠再像Framework的方式直接記錄在文本,文本其實也可以,但是日志的管理以及查看都不太方便。Linux都是指令化,對於開發來說並不友好。
后來Exceptionless進入了視線,選擇這個組件的原因很簡單,可視化、數據統計、實時性以及對於.net開發人員相當友好。在當前網絡上,有很多關於Exceptionless的使用文檔,但是個人覺得並不友好,在使用上並不方便。
在微軟體系中,Microsoft.Extesions.Logging是官方日志框架,它允許我們自己去實現ILoggerProvider / ILogging,那么根據這兩者得特性,由此開發了組件 Overt.Core.Logging
二. 組件Overt.Core.Logging
https://github.com/overtly/logging
三. 簡單介紹使用
1. Nuget包引用
-
Nuget版本:V 1.0.4.1
-
框架支持: NetStandard 2.0
Install-Package Overt.Core.Logging -Version 1.0.4.1
2. 配置信息
-
NetCore配置案例 appsettings.json
{
"Exceptionless": {
"ServerUrl": "http://exless.g.lan", // 私有化域名(Exceptionless私有化的文檔網上很多)
"ApiKey": "ugGFmeeriaj1BG12itWWURfiJjwqiyi2o71ll4mm", // 項目Key 如何創建網上文檔也很多
"Tags": "Local" // 日志所屬項目環境
}
}
3. 具體使用
(1)服務注入
-
Web服務使用
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{// Logging
app.AddExlessLogging();
}
-
IHost 普通服務使用
static void Main(string[] args)
{
var host = new HostBuilder() .UseConsoleLifetime() //使用控制台生命周期 .ConfigureAppConfiguration((context, configuration) => { configuration .AddJsonFile("appsettings.json", optional: true) .AddEnvironmentVariables(); }) .ConfigureLogging(logger => { }) .ConfigureServices(ConfigureServices) .Build(); host.Services.AddExlessLogging(); ThreadPool.SetMinThreads(100, 100); AppDomain.CurrentDomain.UnhandledException += (sender, e) => { var logFactory = host.Services.GetService<ILoggerFactory>(); var logger = logFactory.CreateLogger<Program>(); logger.LogError(e.ExceptionObject as Exception, $"UnhandledException"); }; host.Run(); }
(2)日志使用
using Microsoft.Extensions.Logging;
private readonly ILogger _logger; public Test(ILogger<Test> logger) { _logger = logger; }
_logger.LogInformation("你好");
4. 源碼詳解
(1)實現ILogger
using Exceptionless;
using Microsoft.Extensions.Logging; using System; namespace Overt.Core.Logging { /// <summary> /// Logger實現 /// </summary> public class ExlessLogger : ILogger { private readonly string _categoryName; public ExlessLogger(string categoryName) { _categoryName = categoryName; } /// <summary> /// /// </summary> /// <typeparam name="TState"></typeparam> /// <param name="state"></param> /// <returns></returns> public IDisposable BeginScope<TState>(TState state) { return new NoopDisposable(); } /// <summary> /// 是否可用 /// </summary> /// <param name="logLevel"></param> /// <returns></returns> public bool IsEnabled(LogLevel logLevel) { return true; } /// <summary> /// 記錄日志 /// </summary> /// <typeparam name="TState"></typeparam> /// <param name="logLevel"></param> /// <param name="eventId"></param> /// <param name="state"></param> /// <param name="exception"></param> /// <param name="formatter"></param> public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { try { var message = formatter(state, exception); var source = $"{_categoryName}"; var exlessLogLevel = Exceptionless.Logging.LogLevel.Trace; switch (logLevel) { case LogLevel.Trace: exlessLogLevel = Exceptionless.Logging.LogLevel.Trace; break; case LogLevel.Information: exlessLogLevel = Exceptionless.Logging.LogLevel.Info; break; case LogLevel.Warning: exlessLogLevel = Exceptionless.Logging.LogLevel.Warn; break; case LogLevel.Error: exlessLogLevel = Exceptionless.Logging.LogLevel.Error; break; case LogLevel.Critical: exlessLogLevel = Exceptionless.Logging.LogLevel.Fatal; break; default: exlessLogLevel = Exceptionless.Logging.LogLevel.Debug; break; } var eventBuilder = ExceptionlessClient.Default .CreateLog(message, exlessLogLevel) .SetSource(source) .SetException(exception); if (eventId != null) eventBuilder.SetProperty("Event", $"{eventId.ToString()}"); var serverAndPoint = LoggingUtility.GetAddressIP(); if (!string.IsNullOrEmpty(serverAndPoint)) eventBuilder.SetProperty("ServerEndPoint", serverAndPoint); eventBuilder.Submit(); } catch { } } private class NoopDisposable : IDisposable { public void Dispose() { } } } }
(2)實現ILoggerProvider
using Microsoft.Extensions.Logging;
namespace Overt.Core.Logging { /// <summary> /// LoggerProvider /// </summary> public class ExlessLoggerProvider : ILoggerProvider { /// <summary> /// Contructor /// </summary> /// <param name="categoryName"></param> /// <returns></returns> public ILogger CreateLogger(string categoryName) { return new ExlessLogger(categoryName); } /// <summary> /// /// </summary> public void Dispose() { } } }
(3)依賴注入
using Exceptionless;
using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; using Overt.Core.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace Microsoft.Extensions.DependencyInjection { public static class ServiceCollectionExtensions { #region ExLess /// <summary> /// 注入 /// </summary> /// <param name="loggingBuilder"></param> /// <param name="configFile"></param> public static void AddExlessLogging(this IServiceProvider provider) { var configuration = provider.GetService<IConfiguration>(); var loggerFactory = provider.GetService<ILoggerFactory>(); var client = ExceptionlessClient.Default; client.InitExlessTags(configuration); client.Configuration.ReadFromConfiguration(configuration); client.Configuration.ReadFromEnvironmentalVariables(); client.Configuration.UseInMemoryStorage(); client.Startup(); loggerFactory.AddProvider(new ExlessLoggerProvider()); } /// <summary> /// 注入 /// </summary> /// <param name="loggingBuilder"></param> /// <param name="configFile"></param> public static void AddExlessLogging(this IApplicationBuilder app) { var provider = app.ApplicationServices; var configuration = provider.GetService<IConfiguration>(); var loggerFactory = provider.GetService<ILoggerFactory>(); app.UseExceptionless(configuration); var client = ExceptionlessClient.Default; client.InitExlessTags(configuration); client.Configuration.UseInMemoryStorage(); loggerFactory.AddProvider(new ExlessLoggerProvider()); } /// <summary> /// tags /// </summary> /// <param name="client"></param> /// <param name="configuration"></param> private static void InitExlessTags(this ExceptionlessClient client, IConfiguration configuration) { var tags = configuration?["Exceptionless:Tags"]?.Split(",", StringSplitOptions.RemoveEmptyEntries)?.ToList(); foreach (var tag in tags ?? new List<string>()) { client.Configuration.DefaultTags.Add(tag); } } #endregion } }
5. 最終效果
可實時查看日志信息