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

    可实时查看日志信息

  • 相关阅读:
    poj1014 hdu1059 Dividing 多重背包
    浏览器开发工具
    Linux dirname、basename 指令
    linux ar命令
    gcc创建和使用静态库、动态库
    -DDEBUG编译标记
    sigaction函数解析
    Signal ()函数详细介绍 Linux函数
    Linux makefile 教程 非常详细,且易懂
    初始用户组,有效用户组,初始用户,有效用户
  • 原文地址:https://www.cnblogs.com/mojinxun/p/12432823.html
Copyright © 2020-2023  润新知