NetCore微服务实战体系:日志管理

一. 起始

进入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. 最终效果

可实时查看日志信息

原文地址:https://www.cnblogs.com/mojinxun/p/12432823.html