<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Util應用框架基礎(六) - 日志記錄(一) - 正文

      本文介紹Util應用框架如何記錄日志.

      日志記錄共分4篇,本文是正文,后續還有3篇分別介紹寫入不同日志接收器的安裝和配置方法.

      概述

      日志記錄對于了解系統執行情況非常重要.

      Asp.Net Core 抽象了日志基礎架構,支持使用日志提供程序進行擴展,提供控制臺日志等簡單實現.

      Serilog 是 .Net 流行的第三方日志框架,支持結構化日志,并能與 Asp.Net Core 日志集成.

      Serilog 支持多種日志接收器,可以將日志發送到不同的地方.

      我們可以將日志寫入文本文件,但查看文本文件比較困難,文件如果很大,查找問題非常費力.

      對于生產環境,我們需要包含管理界面的日志系統.

      Seq 是一個日志系統,可以很好的展示結構化日志數據,并提供模糊搜索功能.

      Exceptionless 是基于 Asp.Net Core 開發的日志系統.

      與 Seq 相比,Exceptionless 搜索能力較弱.

      Seq 和 Exceptionless 都提供了 Serilog 日志接收器,可以使用 Serilog 接入它們.

      Util應用框架使用 Serilog 日志框架,同時集成了 SeqExceptionless 日志系統.

      Util簡化了日志配置,并對常用功能進行擴展.

      日志配置

      選擇日志接收器

      Util應用框架默認支持三種 Serilog 日志接收器:

      • 日志文件
      • Seq
      • Exceptionless

      你可以從中選擇一種或多種,如果都不能滿足要求,你也可以引用 Serilog 支持的其它日志接收器,或自行實現.

      配置日志接收器

      請轉到特定日志接收器章節查看配置方法.

      配置日志級別

      Asp.Net Core 使用日志級別表示日志的嚴重程度,定義如下:

      • Trace = 0
      • Debug = 1
      • Information = 2
      • Warning = 3
      • Error = 4
      • Critical = 5
      • None = 6

      None不開啟日志,Trace的嚴重程度最低,Critical的嚴重程度最高,需要高度關注.

      可以在 appsettings.json 配置文件設置日志級別.

      {
        "Logging": {
          "LogLevel": {
            "Default": "Information"
          }
        }
      }
      

      Logging 配置節用于配置日志.

      LogLevel 為所有日志提供程序配置日志級別.

      Default 為所有日志類別設置默認的日志級別.

      上面的配置將默認日志級別設置為 Information.

      意味著只輸出日志級別等于或大于 Information 的日志.

      現在 Trace 和 Debug 兩個級別的日志被禁用了.

      可以為特定日志類別設置日志級別.

      {
        "Logging": {
          "LogLevel": {
            "Default": "Information",
            "Microsoft": "Debug",
          }
        }
      }
      

      配置增加了 Microsoft 日志類別,并設置為 Debug 日志級別.

      日志類別用來給日志分類,一般使用帶命名空間的類名作為日志類別.

      日志類別支持模糊匹配, Microsoft 日志類別不僅匹配 Microsoft ,而且還能匹配以 Microsoft 開頭的所有日志類別,比如 Microsoft.AspNetCore .

      Serilog 的日志級別

      Serilog 定義了自己的日志級別,不支持上面介紹的標準配置方式.

      Exceptionless 也是如此.

      使用第三方框架的日志級別會導致復雜性.

      Util應用框架擴展了 Serilog 和 Exceptionless 的日志級別配置,允許以統一的標準方式進行配置.

      記錄日志

      .Net 提供了標準的日志記錄接口 Microsoft.Extensions.Logging.ILogger.

      你可以使用 ILogger 記錄日志.

      Util應用框架還提供了一個 Util.Logging.ILog 接口.

      當你需要寫入很長的日志時,可能需要使用 StringBuilder 拼接日志內容.

      ILog 提供了一種更簡單的方式寫入長內容日志.

      使用 ILogger 記錄日志

      ILogger 支持泛型參數, 用來指定日志類別,使用帶命名空間的類名作為日志類別.

      namespace Demo;
      
      public class DemoController : WebApiControllerBase {
          public DemoController( ILogger<DemoController> logger ) {
              logger.LogDebug( "Util" );
          }
      }
      

      示例在控制器構造方法注入 ILogger<DemoController> ,日志類別為 Demo.DemoController .

      ILogger 擴展了一些以 Log 開頭的方法,比如 LogDebug,表示寫入日志級別為 Debug 的消息.

      logger.LogDebug( "Util" ) 以 Debug 日志級別寫入消息'Util'.

      使用 ILog 記錄日志

      Util應用框架定義了 ILog 接口.

      ILog 是對 ILogger 接口的簡單包裝, 對日志內容的設置進行了擴展.

      ILog 也使用泛型參數來指定日志類別.

      使用 ILog 完成上面相同的示例.

      public class DemoController : WebApiControllerBase {
          public DemoController( ILog<DemoController> log ) {
              log.Message( "Util" ).LogDebug();
          }
      }
      

      Message 是 ILog 定義的方法, 用來設置日志消息,可以多次調用它拼接內容.

      當你需要寫比較長的日志內容, ILog 可以幫你拼接內容,這樣省去了定義 StringBuilder 的麻煩.

      可以在 ILog 添加自定義擴展方法來設置內容, Util應用框架內置了一些設置日志消息的擴展方法, 比如 AppendLine.

      public class DemoController : WebApiControllerBase {
          public DemoController( ILog<DemoController> log ) {
              log.AppendLine( "內容1" )
                  .AppendLine( "內容2" )
                  .LogDebug();
          }
      }
      

      你可以定義自己的擴展方法,以更加語義化的方式記錄日志.

      范例:

      public class DemoController : WebApiControllerBase {
          public DemoController( ILog<DemoController> log ) {
              log.Caption( "標題" )
                  .Content( "內容" )
                  .Sql( "Sql" )
                  .LogDebug();
          }
      }
      

      ILog 與 ILogger 比較:

      ILog 更擅長記錄內容很長的日志.

      ILog 是有狀態服務,不能在多個線程共享使用.

      可以使用 ILog 記錄業務日志,其它場景應使用 ILogger.

      結構化日志支持

      Serilog 日志框架對結構化日志提供了支持.

      結構化日志使用特定語法的消息模板日志格式,可以從日志文本中提取搜索元素.

      結構化日志的優勢主要體現在日志系統對日志消息的展示和搜索方式上.

      不同的日志系統對結構化日志的展示方式和搜索能力不同.

      請參考 Seq 和 Exceptionless 的 結構化日志支持 小節.

      日志操作上下文

      記錄日志時,我們除了需要記錄業務內容,還需要知道一些額外的信息,比如操作用戶是誰.

      我們希望記錄日志時僅設置業務內容,這些額外的信息最好能自動記錄.

      Util應用框架通過日志上下文自動設置這些額外信息.

      • UserId 設置當前操作用戶標識

      • Application 設置當前應用程序名稱.

      • Environment 設置當前環境名稱.

      • TraceId 設置跟蹤號.

      • Stopwatch 設置計時器,用于記錄請求執行花了多長時間.

      在 Asp.Net Core 環境, 日志上下文由日志上下文中間件 Util.Applications.Logging.LogContextMiddleware 創建.

      無需手工添加日志上下文中間件,只要引用 Util.Application.WebApi 類庫, 就會自動添加到中間件管道.

      對于 Web 請求, 跟蹤號是一個重要的信息,可以通過查詢跟蹤號,將相關的請求日志全部查出來.

      另外, Exceptionless 會自動收集很多系統信息.

      源碼解析

      ILog 日志操作

      ILog 日志操作接口提供鏈式調用方式設置日志內容.

      • Message 方法設置日志消息.

      • Property 方法設置擴展屬性.

      • State 設置日志參數對象.

      Log 開頭的日志記錄方法,將日志操作委托給 ILogger 相關方法.

      /// <summary>
      /// 日志操作
      /// </summary>
      /// <typeparam name="TCategoryName">日志類別</typeparam>
      public interface ILog<out TCategoryName> : ILog {
      }
      
      /// <summary>
      /// 日志操作
      /// </summary>
      public interface ILog {
          /// <summary>
          /// 設置日志事件標識
          /// </summary>
          /// <param name="eventId">日志事件標識</param>
          ILog EventId( EventId eventId );
          /// <summary>
          /// 設置異常
          /// </summary>
          /// <param name="exception">異常</param>
          ILog Exception( Exception exception );
          /// <summary>
          /// 設置自定義擴展屬性
          /// </summary>
          /// <param name="propertyName">屬性名</param>
          /// <param name="propertyValue">屬性值</param>
          ILog Property( string propertyName, string propertyValue );
          /// <summary>
          /// 設置日志狀態對象
          /// </summary>
          /// <param name="state">狀態對象</param>
          ILog State( object state );
          /// <summary>
          /// 設置日志消息
          /// </summary>
          /// <param name="message">日志消息</param>
          /// <param name="args">日志消息參數</param>
          ILog Message( string message, params object[] args );
          /// <summary>
          /// 是否啟用
          /// </summary>
          /// <param name="logLevel">日志級別</param>
          bool IsEnabled( LogLevel logLevel );
          /// <summary>
          /// 開啟日志范圍
          /// </summary>
          /// <typeparam name="TState">日志狀態類型</typeparam>
          /// <param name="state">日志狀態</param>
          IDisposable BeginScope<TState>( TState state );
          /// <summary>
          /// 寫跟蹤日志
          /// </summary>
          ILog LogTrace();
          /// <summary>
          /// 寫調試日志
          /// </summary>
          ILog LogDebug();
          /// <summary>
          /// 寫信息日志
          /// </summary>
          ILog LogInformation();
          /// <summary>
          /// 寫警告日志
          /// </summary>
          ILog LogWarning();
          /// <summary>
          /// 寫錯誤日志
          /// </summary>
          ILog LogError();
          /// <summary>
          /// 寫致命日志
          /// </summary>
          ILog LogCritical();
      }
      

      ILogExtensions 日志操作擴展

      Util應用框架內置了幾個日志操作擴展方法,你可以定義自己的擴展方法,以方便內容設置.

      /// <summary>
      /// 日志操作擴展
      /// </summary>
      public static class ILogExtensions {
          /// <summary>
          /// 添加消息
          /// </summary>
          /// <param name="log">配置項</param>
          /// <param name="message">消息</param>
          /// <param name="args">日志消息參數</param>
          public static ILog Append( this ILog log,string message, params object[] args ) {
              log.CheckNull( nameof( log ) );
              log.Message( message, args );
              return log;
          }
      
          /// <summary>
          /// 當條件為true添加消息
          /// </summary>
          /// <param name="log">配置項</param>
          /// <param name="message">消息</param>
          /// <param name="condition">條件,值為true則添加消息</param>
          /// <param name="args">日志消息參數</param>
          public static ILog AppendIf( this ILog log, string message,bool condition, params object[] args ) {
              log.CheckNull( nameof( log ) );
              if ( condition )
                  log.Message( message, args );
              return log;
          }
      
          /// <summary>
          /// 添加消息并換行
          /// </summary>
          /// <param name="log">配置項</param>
          /// <param name="message">消息</param>
          /// <param name="args">日志消息參數</param>
          public static ILog AppendLine( this ILog log, string message, params object[] args ) {
              log.CheckNull( nameof( log ) );
              log.Message( message, args );
              log.Message( Environment.NewLine );
              return log;
          }
      
          /// <summary>
          /// 當條件為true添加消息并換行
          /// </summary>
          /// <param name="log">配置項</param>
          /// <param name="message">消息</param>
          /// <param name="condition">條件,值為true則添加消息</param>
          /// <param name="args">日志消息參數</param>
          public static ILog AppendLineIf( this ILog log, string message, bool condition, params object[] args ) {
              log.CheckNull( nameof( log ) );
              if ( condition ) {
                  log.Message( message, args );
                  log.Message( Environment.NewLine );
              }
              return log;
          }
      
          /// <summary>
          /// 消息換行
          /// </summary>
          /// <param name="log">配置項</param>
          public static ILog Line( this ILog log ) {
              log.CheckNull( nameof(log) );
              log.Message( Environment.NewLine );
              return log;
          }
      }
      

      LogContext 日志上下文

      通過日志上下文自動記錄重要的額外信息.

      /// <summary>
      /// 日志上下文
      /// </summary>
      public class LogContext {
          /// <summary>
          /// 初始化日志上下文
          /// </summary>
          public LogContext() {
              Data = new Dictionary<string, object>();
          }
      
          /// <summary>
          /// 計時器
          /// </summary>
          public Stopwatch Stopwatch { get; set; }
          /// <summary>
          /// 跟蹤標識
          /// </summary>
          public string TraceId { get; set; }
          /// <summary>
          /// 用戶標識
          /// </summary>
          public string UserId { get; set; }
          /// <summary>
          /// 應用程序
          /// </summary>
          public string Application { get; set; }
          /// <summary>
          /// 執行環境
          /// </summary>
          public string Environment { get; set; }
          /// <summary>
          /// 擴展數據
          /// </summary>
          public IDictionary<string, object> Data { get; }
      }
      

      LogContextMiddleware 日志上下文中間件

      日志上下文中間件創建日志上下文,并添加到 HttpContext 對象的 Items .

      /// <summary>
      /// 日志上下文中間件
      /// </summary>
      public class LogContextMiddleware {
          /// <summary>
          /// 下個中間件
          /// </summary>
          private readonly RequestDelegate _next;
      
          /// <summary>
          /// 初始化日志上下文中間件
          /// </summary>
          /// <param name="next">下個中間件</param>
          public LogContextMiddleware( RequestDelegate next ) {
              _next = next;
          }
      
          /// <summary>
          /// 執行中間件
          /// </summary>
          /// <param name="context">Http上下文</param>
          public async Task Invoke( HttpContext context ) {
              var traceId = context.Request.Headers["x-correlation-id"].SafeString();
              if ( traceId.IsEmpty() )
                  traceId = context.TraceIdentifier;
              var session = context.RequestServices.GetService<Util.Sessions.ISession>();
              var environment = context.RequestServices.GetService<IWebHostEnvironment>();
              var logContext = new LogContext {
                  Stopwatch = Stopwatch.StartNew(), 
                  TraceId = traceId, 
                  UserId = session?.UserId,
                  Application = environment?.ApplicationName,
                  Environment = environment?.EnvironmentName
              };
              context.Items[LogContextAccessor.LogContextKey] = logContext;
              await _next( context );
          }
      }
      

      ILogContextAccessor 日志上下文訪問器

      日志上下文訪問器從 HttpContext.Items 獲取日志上下文.

      /// <summary>
      /// 日志上下文訪問器
      /// </summary>
      public interface ILogContextAccessor {
          /// <summary>
          /// 日志上下文
          /// </summary>
          LogContext Context { get; set; }
      }
      
      /// <summary>
      /// 日志上下文訪問器
      /// </summary>
      public class LogContextAccessor : ILogContextAccessor {
          /// <summary>
          /// 日志上下文鍵名
          /// </summary>
          public const string LogContextKey = "Util.Logging.LogContext";
      
          /// <summary>
          /// 日志上下文
          /// </summary>
          public LogContext Context {
              get => Util.Helpers.Convert.To<LogContext>( Web.HttpContext.Items[LogContextKey] );
              set => Web.HttpContext.Items[LogContextKey] = value;
          }
      }
      

      LogContextEnricher 日志上下文擴展

      Serilog 提供 ILogEventEnricher 接口用于設置擴展屬性.

      LogContextEnricher 使用 Ioc.Create 方法獲取依賴服務 ILogContextAccessor.

      這是因為不能使用依賴注入,它要求實現類必須是無參構造函數.

      Ioc.Create 在 Asp.Net Core 環境獲取依賴服務是安全的,但在其它環境則可能獲取失敗.

      如果獲取日志上下文失敗,也不會對功能造成影響,只是丟失了一些上下文信息.

      /// <summary>
      /// 日志上下文擴展屬性
      /// </summary>
      public class LogContextEnricher : ILogEventEnricher {
          /// <summary>
          /// 擴展屬性
          /// </summary>
          /// <param name="logEvent">日志事件</param>
          /// <param name="propertyFactory">日志事件屬性工廠</param>
          public void Enrich( LogEvent logEvent, ILogEventPropertyFactory propertyFactory ) {
              var accessor = Ioc.Create<ILogContextAccessor>();
              if ( accessor == null )
                  return;
              var context = accessor.Context;
              if ( context == null )
                  return;
              if ( logEvent == null )
                  return;
              if ( propertyFactory == null )
                  return;
              RemoveProperties( logEvent );
              AddDuration( context,logEvent, propertyFactory );
              AddTraceId( context, logEvent, propertyFactory );
              AddUserId( context, logEvent, propertyFactory );
              AddApplication( context, logEvent, propertyFactory );
              AddEnvironment( context, logEvent, propertyFactory );
              AddData( context, logEvent, propertyFactory );
          }
      
          /// <summary>
          /// 移除默認設置的部分屬性
          /// </summary>
          private void RemoveProperties( LogEvent logEvent ) {
              logEvent.RemovePropertyIfPresent( "ActionId" );
              logEvent.RemovePropertyIfPresent( "ActionName" );
              logEvent.RemovePropertyIfPresent( "RequestId" );
              logEvent.RemovePropertyIfPresent( "RequestPath" );
              logEvent.RemovePropertyIfPresent( "ConnectionId" );
          }
      
          /// <summary>
          /// 添加執行持續時間
          /// </summary>
          private void AddDuration( LogContext context, LogEvent logEvent, ILogEventPropertyFactory propertyFactory ) {
              if ( context?.Stopwatch == null )
                  return;
              var property = propertyFactory.CreateProperty( "Duration", context.Stopwatch.Elapsed.Description() );
              logEvent.AddOrUpdateProperty( property );
          }
      
          /// <summary>
          /// 添加跟蹤號
          /// </summary>
          private void AddTraceId( LogContext context, LogEvent logEvent, ILogEventPropertyFactory propertyFactory ) {
              if ( context == null || context.TraceId.IsEmpty() )
                  return;
              var property = propertyFactory.CreateProperty( "TraceId", context.TraceId );
              logEvent.AddOrUpdateProperty( property );
          }
      
          /// <summary>
          /// 添加用戶標識
          /// </summary>
          private void AddUserId( LogContext context, LogEvent logEvent, ILogEventPropertyFactory propertyFactory ) {
              if ( context == null || context.UserId.IsEmpty() )
                  return;
              var property = propertyFactory.CreateProperty( "UserId", context.UserId );
              logEvent.AddOrUpdateProperty( property );
          }
      
          /// <summary>
          /// 添加應用程序
          /// </summary>
          private void AddApplication( LogContext context, LogEvent logEvent, ILogEventPropertyFactory propertyFactory ) {
              if ( context == null || context.Application.IsEmpty() )
                  return;
              var property = propertyFactory.CreateProperty( "Application", context.Application );
              logEvent.AddOrUpdateProperty( property );
          }
      
          /// <summary>
          /// 添加執行環境
          /// </summary>
          private void AddEnvironment( LogContext context, LogEvent logEvent, ILogEventPropertyFactory propertyFactory ) {
              if ( context == null || context.Environment.IsEmpty() )
                  return;
              var property = propertyFactory.CreateProperty( "Environment", context.Environment );
              logEvent.AddOrUpdateProperty( property );
          }
      
          /// <summary>
          /// 添加擴展數據
          /// </summary>
          private void AddData( LogContext context, LogEvent logEvent, ILogEventPropertyFactory propertyFactory ) {
              if ( context?.Data == null || context.Data.Count == 0 )
                  return;
              foreach ( var item in context.Data ) {
                  var property = propertyFactory.CreateProperty( item.Key, item.Value );
                  logEvent.AddOrUpdateProperty( property );
              }
          }
      }
      

      LoggerEnrichmentConfigurationExtensions

      將 LogContextEnricher 擴展到 LoggerEnrichmentConfiguration 上.

      /// <summary>
      /// Serilog擴展屬性配置擴展
      /// </summary>
      public static class LoggerEnrichmentConfigurationExtensions {
          /// <summary>
          /// 添加日志上下文擴展屬性
          /// </summary>
          /// <param name="source">日志擴展配置</param>
          public static LoggerConfiguration WithLogContext( this LoggerEnrichmentConfiguration source ) {
              source.CheckNull( nameof( source ) );
              return source.With<LogContextEnricher>();
          }
      
          /// <summary>
          /// 添加日志級別擴展屬性
          /// </summary>
          /// <param name="source">日志擴展配置</param>
          public static LoggerConfiguration WithLogLevel( this LoggerEnrichmentConfiguration source ) {
              source.CheckNull( nameof( source ) );
              return source.With<LogLevelEnricher>();
          }
      }
      

      AddSerilog 配置方法

      AddSerilog 配置方法封裝了 Serilog 的配置.

      • 配置 ILog 接口服務依賴.

      • 將 Asp.Net Core 日志級別轉換為 Serilog 日志級別.

      • 設置日志上下文擴展.

      /// <summary>
      /// Serilog日志操作擴展
      /// </summary>
      public static class AppBuilderExtensions {
          /// <summary>
          /// 配置Serilog日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          public static IAppBuilder AddSerilog( this IAppBuilder builder ) {
              return builder.AddSerilog( false );
          }
      
          /// <summary>
          /// 配置Serilog日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="isClearProviders">是否清除默認設置的日志提供程序</param>
          public static IAppBuilder AddSerilog( this IAppBuilder builder, bool isClearProviders ) {
              return builder.AddSerilog( options => {
                  options.IsClearProviders = isClearProviders;
              } );
          }
      
          /// <summary>
          /// 配置Serilog日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="appName">應用程序名稱</param>
          public static IAppBuilder AddSerilog( this IAppBuilder builder, string appName ) {
              return builder.AddSerilog( options => {
                  options.Application = appName;
              } );
          }
      
          /// <summary>
          /// 配置Serilog日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="setupAction">日志配置操作</param>
          public static IAppBuilder AddSerilog( this IAppBuilder builder, Action<LogOptions> setupAction ) {
              builder.CheckNull( nameof( builder ) );
              var options = new LogOptions();
              setupAction?.Invoke( options );
              builder.Host.ConfigureServices( ( context, services ) => {
                  services.AddSingleton<ILogFactory, LogFactory>();
                  services.AddTransient( typeof( ILog<> ), typeof( Log<> ) );
                  services.AddTransient( typeof( ILog ), t => t.GetService<ILogFactory>()?.CreateLog( "default" ) ?? NullLog.Instance );
                  var configuration = context.Configuration;
                  services.AddLogging( loggingBuilder => {
                      if ( options.IsClearProviders )
                          loggingBuilder.ClearProviders();
                      SerilogLog.Logger = new LoggerConfiguration()
                          .Enrich.WithProperty( "Application", options.Application )
                          .Enrich.FromLogContext()
                          .Enrich.WithLogLevel()
                          .Enrich.WithLogContext()
                          .ReadFrom.Configuration( configuration )
                          .ConfigLogLevel( configuration )
                          .CreateLogger();
                      loggingBuilder.AddSerilog();
                  } );
              } );
              return builder;
          }
      }
      

      AddExceptionless 配置方法

      AddExceptionless 配置方法封裝了 Serilog 和 Exceptionless 的配置.

      • 配置 ILog 接口服務依賴.

      • 將 Asp.Net Core 日志級別轉換為 Exceptionless 日志級別.

      • 設置日志上下文擴展.

      /// <summary>
      /// Exceptionless日志操作擴展
      /// </summary>
      public static class AppBuilderExtensions {
          /// <summary>
          /// 配置Exceptionless日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="isClearProviders">是否清除默認設置的日志提供程序</param>
          public static IAppBuilder AddExceptionless( this IAppBuilder builder, bool isClearProviders = false ) {
              return builder.AddExceptionless( null, isClearProviders );
          }
      
          /// <summary>
          /// 配置Exceptionless日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="appName">應用程序名稱</param>
          public static IAppBuilder AddExceptionless( this IAppBuilder builder, string appName ) {
              return builder.AddExceptionless( null, appName );
          }
      
          /// <summary>
          /// 配置Exceptionless日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="configAction">Exceptionless日志配置操作</param>
          /// <param name="isClearProviders">是否清除默認設置的日志提供程序</param>
          public static IAppBuilder AddExceptionless( this IAppBuilder builder, Action<ExceptionlessConfiguration> configAction, bool isClearProviders = false ) {
              return builder.AddExceptionless( configAction, t => t.IsClearProviders = isClearProviders );
          }
      
          /// <summary>
          /// 配置Exceptionless日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="configAction">Exceptionless日志配置操作</param>
          /// <param name="appName">應用程序名稱</param>
          public static IAppBuilder AddExceptionless( this IAppBuilder builder, Action<ExceptionlessConfiguration> configAction, string appName ) {
              return builder.AddExceptionless( configAction, t => t.Application = appName );
          }
      
          /// <summary>
          /// 配置Exceptionless日志操作
          /// </summary>
          /// <param name="builder">應用生成器</param>
          /// <param name="configAction">Exceptionless日志配置操作</param>
          /// <param name="setupAction">日志配置</param>
          public static IAppBuilder AddExceptionless( this IAppBuilder builder, Action<ExceptionlessConfiguration> configAction, Action<LogOptions> setupAction ) {
              builder.CheckNull( nameof( builder ) );
              var options = new LogOptions();
              setupAction?.Invoke( options );
              builder.Host.ConfigureServices( ( context, services ) => {
                  services.AddSingleton<ILogFactory, LogFactory>();
                  services.AddTransient( typeof( ILog<> ), typeof( Log<> ) );
                  services.AddTransient( typeof( ILog ), t => t.GetService<ILogFactory>()?.CreateLog( "default" ) ?? NullLog.Instance );
                  var configuration = context.Configuration;
                  services.AddLogging( loggingBuilder => {
                      if ( options.IsClearProviders )
                          loggingBuilder.ClearProviders();
                      ConfigExceptionless( configAction, configuration );
                      SerilogLog.Logger = new LoggerConfiguration()
                          .Enrich.WithProperty( "Application", options.Application )
                          .Enrich.FromLogContext()
                          .Enrich.WithLogLevel()
                          .Enrich.WithLogContext()
                          .WriteTo.Exceptionless()
                          .ReadFrom.Configuration( configuration )
                          .ConfigLogLevel( configuration )
                          .CreateLogger();
                      loggingBuilder.AddSerilog();
                  } );
              } );
              return builder;
          }
      
          /// <summary>
          /// 配置Exceptionless
          /// </summary>
          private static void ConfigExceptionless( Action<ExceptionlessConfiguration> configAction, IConfiguration configuration ) {
              ExceptionlessClient.Default.Startup();
              if ( configAction != null ) {
                  configAction( ExceptionlessClient.Default.Configuration );
                  ConfigLogLevel( configuration, ExceptionlessClient.Default.Configuration );
                  return;
              }
              ExceptionlessClient.Default.Configuration.ReadFromConfiguration( configuration );
              ConfigLogLevel( configuration, ExceptionlessClient.Default.Configuration );
          }
      
          /// <summary>
          /// 配置日志級別
          /// </summary>
          private static void ConfigLogLevel( IConfiguration configuration, ExceptionlessConfiguration options ) {
              var section = configuration.GetSection( "Logging:LogLevel" );
              foreach ( var item in section.GetChildren() ) {
                  if ( item.Key == "Default" ) {
                      options.Settings.Add( "@@log:*", GetLogLevel( item.Value ) );
                      continue;
                  }
                  options.Settings.Add( $"@@log:{item.Key}*", GetLogLevel( item.Value ) );
              }
          }
      
          /// <summary>
          /// 獲取日志級別
          /// </summary>
          private static string GetLogLevel( string logLevel ) {
              switch ( logLevel.ToUpperInvariant() ) {
                  case "TRACE":
                      return "Trace";
                  case "DEBUG":
                      return "Debug";
                  case "INFORMATION":
                      return "Info";
                  case "ERROR":
                      return "Error";
                  case "CRITICAL":
                      return "Fatal";
                  case "NONE":
                      return "Off";
                  default:
                      return "Warn";
              }
          }
      }
      
      posted @ 2023-11-11 13:36  何鎮汐  閱讀(568)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 97精品国产91久久久久久久| 精品福利一区二区三区免费视频| 欧美日韩精品一区二区三区在线 | 亚洲天堂男人的天堂在线| 国产美女久久久亚洲综合| 久久人人妻人人爽人人爽| 在线精品国产中文字幕| 欧美18videosex性欧美tube1080| 中文字幕人妻色偷偷久久| 加勒比无码人妻东京热| 精品人妻人人做人人爽| 激情综合色综合久久综合| 南开区| 国产成人不卡一区二区| 久久精品国产福利一区二区| 中文字幕亚洲日韩无线码| 18禁一区二区每日更新| 三上悠亚精品一区二区久久| 人妻夜夜爽天天爽三区麻豆av| 中文字幕久久熟女蜜桃| 麻豆亚州无矿码专区视频| 亚洲老熟女一区二区三区| 麻豆成人av不卡一二三区| 国产精品伦人一久二久三久| 夜夜躁狠狠躁日日躁视频| 黄色亚洲一区二区在线观看| 成人免费乱码大片a毛片| 老司机午夜精品视频资源| 亚洲熟妇丰满多毛xxxx| 国产AV影片麻豆精品传媒| 天干天干夜啦天干天干国产| 辰溪县| 亚洲精品无码久久一线| 久久亚洲人成网站| 人妻少妇精品中文字幕| 精品人妻免费看一区二区三区| 一本无码av中文出轨人妻| 欧洲免费一区二区三区视频| 国产三级精品片| 天堂mv在线mv免费mv香蕉| 亚洲熟妇自偷自拍另欧美|