本文介紹Util應用框架如何記錄日志.
日志記錄共分4篇,本文是正文,后續(xù)還有3篇分別介紹寫入不同日志接收器的安裝和配置方法.
概述
日志記錄對于了解系統(tǒng)執(zhí)行情況非常重要.
Asp.Net Core 抽象了日志基礎(chǔ)架構(gòu),支持使用日志提供程序進行擴展,提供控制臺日志等簡單實現(xiàn).
Serilog 是 .Net 流行的第三方日志框架,支持結(jié)構(gòu)化日志,并能與 Asp.Net Core 日志集成.
Serilog 支持多種日志接收器,可以將日志發(fā)送到不同的地方.
我們可以將日志寫入文本文件,但查看文本文件比較困難,文件如果很大,查找問題非常費力.
對于生產(chǎn)環(huán)境,我們需要包含管理界面的日志系統(tǒng).
Seq 是一個日志系統(tǒng),可以很好的展示結(jié)構(gòu)化日志數(shù)據(jù),并提供模糊搜索功能.
Exceptionless 是基于 Asp.Net Core 開發(fā)的日志系統(tǒng).
與 Seq 相比,Exceptionless 搜索能力較弱.
Seq 和 Exceptionless 都提供了 Serilog 日志接收器,可以使用 Serilog 接入它們.
Util應用框架使用 Serilog 日志框架,同時集成了 Seq 和 Exceptionless 日志系統(tǒng).
Util簡化了日志配置,并對常用功能進行擴展.
日志配置
選擇日志接收器
Util應用框架默認支持三種 Serilog 日志接收器:
- 日志文件
- Seq
- Exceptionless
你可以從中選擇一種或多種,如果都不能滿足要求,你也可以引用 Serilog 支持的其它日志接收器,或自行實現(xiàn).
配置日志接收器
請轉(zhuǎn)到特定日志接收器章節(jié)查看配置方法.
配置日志級別
Asp.Net Core 使用日志級別表示日志的嚴重程度,定義如下:
- Trace = 0
- Debug = 1
- Information = 2
- Warning = 3
- Error = 4
- Critical = 5
- None = 6
None不開啟日志,Trace的嚴重程度最低,Critical的嚴重程度最高,需要高度關(guān)注.
可以在 appsettings.json 配置文件設(shè)置日志級別.
{
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
Logging 配置節(jié)用于配置日志.
LogLevel 為所有日志提供程序配置日志級別.
Default 為所有日志類別設(shè)置默認的日志級別.
上面的配置將默認日志級別設(shè)置為 Information.
意味著只輸出日志級別等于或大于 Information 的日志.
現(xiàn)在 Trace 和 Debug 兩個級別的日志被禁用了.
可以為特定日志類別設(shè)置日志級別.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Debug",
}
}
}
配置增加了 Microsoft 日志類別,并設(shè)置為 Debug 日志級別.
日志類別用來給日志分類,一般使用帶命名空間的類名作為日志類別.
日志類別支持模糊匹配, Microsoft 日志類別不僅匹配 Microsoft ,而且還能匹配以 Microsoft 開頭的所有日志類別,比如 Microsoft.AspNetCore .
Serilog 的日志級別
Serilog 定義了自己的日志級別,不支持上面介紹的標準配置方式.
Exceptionless 也是如此.
使用第三方框架的日志級別會導致復雜性.
Util應用框架擴展了 Serilog 和 Exceptionless 的日志級別配置,允許以統(tǒng)一的標準方式進行配置.
記錄日志
.Net 提供了標準的日志記錄接口 Microsoft.Extensions.Logging.ILogger.
你可以使用 ILogger 記錄日志.
Util應用框架還提供了一個 Util.Logging.ILog 接口.
當你需要寫入很長的日志時,可能需要使用 StringBuilder 拼接日志內(nèi)容.
ILog 提供了一種更簡單的方式寫入長內(nèi)容日志.
使用 ILogger 記錄日志
ILogger 支持泛型參數(shù), 用來指定日志類別,使用帶命名空間的類名作為日志類別.
namespace Demo;
public class DemoController : WebApiControllerBase {
public DemoController( ILogger<DemoController> logger ) {
logger.LogDebug( "Util" );
}
}
示例在控制器構(gòu)造方法注入 ILogger<DemoController> ,日志類別為 Demo.DemoController .
ILogger 擴展了一些以 Log 開頭的方法,比如 LogDebug,表示寫入日志級別為 Debug 的消息.
logger.LogDebug( "Util" ) 以 Debug 日志級別寫入消息'Util'.
使用 ILog 記錄日志
Util應用框架定義了 ILog 接口.
ILog 是對 ILogger 接口的簡單包裝, 對日志內(nèi)容的設(shè)置進行了擴展.
ILog 也使用泛型參數(shù)來指定日志類別.
使用 ILog 完成上面相同的示例.
public class DemoController : WebApiControllerBase {
public DemoController( ILog<DemoController> log ) {
log.Message( "Util" ).LogDebug();
}
}
Message 是 ILog 定義的方法, 用來設(shè)置日志消息,可以多次調(diào)用它拼接內(nèi)容.
當你需要寫比較長的日志內(nèi)容, ILog 可以幫你拼接內(nèi)容,這樣省去了定義 StringBuilder 的麻煩.
可以在 ILog 添加自定義擴展方法來設(shè)置內(nèi)容, Util應用框架內(nèi)置了一些設(shè)置日志消息的擴展方法, 比如 AppendLine.
public class DemoController : WebApiControllerBase {
public DemoController( ILog<DemoController> log ) {
log.AppendLine( "內(nèi)容1" )
.AppendLine( "內(nèi)容2" )
.LogDebug();
}
}
你可以定義自己的擴展方法,以更加語義化的方式記錄日志.
范例:
public class DemoController : WebApiControllerBase {
public DemoController( ILog<DemoController> log ) {
log.Caption( "標題" )
.Content( "內(nèi)容" )
.Sql( "Sql" )
.LogDebug();
}
}
ILog 與 ILogger 比較:
ILog 更擅長記錄內(nèi)容很長的日志.
ILog 是有狀態(tài)服務,不能在多個線程共享使用.
可以使用 ILog 記錄業(yè)務日志,其它場景應使用 ILogger.
結(jié)構(gòu)化日志支持
Serilog 日志框架對結(jié)構(gòu)化日志提供了支持.
結(jié)構(gòu)化日志使用特定語法的消息模板日志格式,可以從日志文本中提取搜索元素.
結(jié)構(gòu)化日志的優(yōu)勢主要體現(xiàn)在日志系統(tǒng)對日志消息的展示和搜索方式上.
不同的日志系統(tǒng)對結(jié)構(gòu)化日志的展示方式和搜索能力不同.
請參考 Seq 和 Exceptionless 的 結(jié)構(gòu)化日志支持 小節(jié).
日志操作上下文
記錄日志時,我們除了需要記錄業(yè)務內(nèi)容,還需要知道一些額外的信息,比如操作用戶是誰.
我們希望記錄日志時僅設(shè)置業(yè)務內(nèi)容,這些額外的信息最好能自動記錄.
Util應用框架通過日志上下文自動設(shè)置這些額外信息.
-
UserId 設(shè)置當前操作用戶標識
-
Application 設(shè)置當前應用程序名稱.
-
Environment 設(shè)置當前環(huán)境名稱.
-
TraceId 設(shè)置跟蹤號.
-
Stopwatch 設(shè)置計時器,用于記錄請求執(zhí)行花了多長時間.
在 Asp.Net Core 環(huán)境, 日志上下文由日志上下文中間件 Util.Applications.Logging.LogContextMiddleware 創(chuàng)建.
無需手工添加日志上下文中間件,只要引用 Util.Application.WebApi 類庫, 就會自動添加到中間件管道.
對于 Web 請求, 跟蹤號是一個重要的信息,可以通過查詢跟蹤號,將相關(guān)的請求日志全部查出來.
另外, Exceptionless 會自動收集很多系統(tǒng)信息.
源碼解析
ILog 日志操作
ILog 日志操作接口提供鏈式調(diào)用方式設(shè)置日志內(nèi)容.
-
Message 方法設(shè)置日志消息.
-
Property 方法設(shè)置擴展屬性.
-
State 設(shè)置日志參數(shù)對象.
Log 開頭的日志記錄方法,將日志操作委托給 ILogger 相關(guān)方法.
/// <summary>
/// 日志操作
/// </summary>
/// <typeparam name="TCategoryName">日志類別</typeparam>
public interface ILog<out TCategoryName> : ILog {
}
/// <summary>
/// 日志操作
/// </summary>
public interface ILog {
/// <summary>
/// 設(shè)置日志事件標識
/// </summary>
/// <param name="eventId">日志事件標識</param>
ILog EventId( EventId eventId );
/// <summary>
/// 設(shè)置異常
/// </summary>
/// <param name="exception">異常</param>
ILog Exception( Exception exception );
/// <summary>
/// 設(shè)置自定義擴展屬性
/// </summary>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">屬性值</param>
ILog Property( string propertyName, string propertyValue );
/// <summary>
/// 設(shè)置日志狀態(tài)對象
/// </summary>
/// <param name="state">狀態(tài)對象</param>
ILog State( object state );
/// <summary>
/// 設(shè)置日志消息
/// </summary>
/// <param name="message">日志消息</param>
/// <param name="args">日志消息參數(shù)</param>
ILog Message( string message, params object[] args );
/// <summary>
/// 是否啟用
/// </summary>
/// <param name="logLevel">日志級別</param>
bool IsEnabled( LogLevel logLevel );
/// <summary>
/// 開啟日志范圍
/// </summary>
/// <typeparam name="TState">日志狀態(tài)類型</typeparam>
/// <param name="state">日志狀態(tài)</param>
IDisposable BeginScope<TState>( TState state );
/// <summary>
/// 寫跟蹤日志
/// </summary>
ILog LogTrace();
/// <summary>
/// 寫調(diào)試日志
/// </summary>
ILog LogDebug();
/// <summary>
/// 寫信息日志
/// </summary>
ILog LogInformation();
/// <summary>
/// 寫警告日志
/// </summary>
ILog LogWarning();
/// <summary>
/// 寫錯誤日志
/// </summary>
ILog LogError();
/// <summary>
/// 寫致命日志
/// </summary>
ILog LogCritical();
}
ILogExtensions 日志操作擴展
Util應用框架內(nèi)置了幾個日志操作擴展方法,你可以定義自己的擴展方法,以方便內(nèi)容設(shè)置.
/// <summary>
/// 日志操作擴展
/// </summary>
public static class ILogExtensions {
/// <summary>
/// 添加消息
/// </summary>
/// <param name="log">配置項</param>
/// <param name="message">消息</param>
/// <param name="args">日志消息參數(shù)</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">日志消息參數(shù)</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">日志消息參數(shù)</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">日志消息參數(shù)</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>
/// 執(zhí)行環(huán)境
/// </summary>
public string Environment { get; set; }
/// <summary>
/// 擴展數(shù)據(jù)
/// </summary>
public IDictionary<string, object> Data { get; }
}
LogContextMiddleware 日志上下文中間件
日志上下文中間件創(chuàng)建日志上下文,并添加到 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>
/// 執(zhí)行中間件
/// </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 接口用于設(shè)置擴展屬性.
LogContextEnricher 使用 Ioc.Create 方法獲取依賴服務 ILogContextAccessor.
這是因為不能使用依賴注入,它要求實現(xiàn)類必須是無參構(gòu)造函數(shù).
Ioc.Create 在 Asp.Net Core 環(huán)境獲取依賴服務是安全的,但在其它環(huán)境則可能獲取失敗.
如果獲取日志上下文失敗,也不會對功能造成影響,只是丟失了一些上下文信息.
/// <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>
/// 移除默認設(shè)置的部分屬性
/// </summary>
private void RemoveProperties( LogEvent logEvent ) {
logEvent.RemovePropertyIfPresent( "ActionId" );
logEvent.RemovePropertyIfPresent( "ActionName" );
logEvent.RemovePropertyIfPresent( "RequestId" );
logEvent.RemovePropertyIfPresent( "RequestPath" );
logEvent.RemovePropertyIfPresent( "ConnectionId" );
}
/// <summary>
/// 添加執(zhí)行持續(xù)時間
/// </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>
/// 添加執(zhí)行環(huán)境
/// </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>
/// 添加擴展數(shù)據(jù)
/// </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 日志級別轉(zhuǎn)換為 Serilog 日志級別.
-
設(shè)置日志上下文擴展.文章來源地址http://www.zghlxwxcb.cn/news/detail-746083.html
/// <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">是否清除默認設(shè)置的日志提供程序</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 日志級別轉(zhuǎn)換為 Exceptionless 日志級別.文章來源:http://www.zghlxwxcb.cn/news/detail-746083.html
-
設(shè)置日志上下文擴展.
/// <summary>
/// Exceptionless日志操作擴展
/// </summary>
public static class AppBuilderExtensions {
/// <summary>
/// 配置Exceptionless日志操作
/// </summary>
/// <param name="builder">應用生成器</param>
/// <param name="isClearProviders">是否清除默認設(shè)置的日志提供程序</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">是否清除默認設(shè)置的日志提供程序</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";
}
}
}
到了這里,關(guān)于Util應用框架基礎(chǔ)(六) - 日志記錄(一) - 正文的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!