一. 起始
进入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. 最终效果
可实时查看日志信息