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