.NET 中 Logger 常被忽视的方法 BeginScope

打印 上一主题 下一主题

主题 857|帖子 857|积分 2571

BeginScope 方法是 .NET 中 ILogger 接口的一部分,用于创建日志记录的作用域(Scope)。这种作用域可以将特定的上下文信息包含在日志中,从而进步日志的可读性和调试效率。
配置日志包含作用域信息

首先,需要在日志配置中启用包含作用域信息。以 appsettings.json 为例,以下是配置示例:
  1. {
  2.   "Logging": {
  3.     "Console": {
  4.       "IncludeScopes": true,
  5.       "LogLevel": {
  6.         "Default": "Information",
  7.         "Microsoft.AspNetCore": "Warning"
  8.       }
  9.     }
  10.   }
  11. }
复制代码
在该配置中,IncludeScopes 被设置为 true,这意味着在控制台日志中将包含作用域信息。
在代码中利用 BeginScope

利用 BeginScope 方法在日志中添加上下文信息,如下代码手动显示:
  1. [HttpGet(Name = "Get")]
  2. public string Get()
  3. {
  4.     using (_logger.BeginScope("TenantName {TenantName}", "test"))
  5.     {
  6.         _logger.LogInformation("这是一条测试日志信息");
  7.     }
  8.     return "ok";
  9. }
复制代码
在这段代码中,我们利用 BeginScope 创建了一个作用域,并设置了一个上下文变量。在这个作用域之内,日志信息将包含这个上下文变量。

 
将作用域信息 JSON化

通过实现自己的 ILogger 接口,我们可以将作用域信息以 JSON 格式输出:
  1. public class ScopeLogger : ILogger
  2. {
  3.     private readonly string _categoryName;
  4.     private static readonly AsyncLocal<Stack<object>> _scopeStack = new AsyncLocal<Stack<object>>();
  5.     public ScopeLogger(string categoryName)
  6.     {
  7.         _categoryName = categoryName;
  8.     }
  9.     public IDisposable BeginScope<TState>(TState state) where TState : notnull
  10.     {
  11.         if (_scopeStack.Value == null)
  12.         {
  13.             _scopeStack.Value = new Stack<object>();
  14.         }
  15.         _scopeStack.Value.Push(state);
  16.         return new Scope(() => _scopeStack.Value.Pop());
  17.     }
  18.     public bool IsEnabled(LogLevel logLevel) => true;
  19.     public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
  20.     {
  21.         var logEntry = new Dictionary<string, object>
  22.         {
  23.             ["Timestamp"] = DateTime.UtcNow,
  24.             ["LogLevel"] = logLevel.ToString(),
  25.             ["Category"] = _categoryName,
  26.             ["Message"] = formatter(state, exception),
  27.             ["Exception"] = exception?.ToString()
  28.         };
  29.         if (_scopeStack.Value != null && _scopeStack.Value.Count > 0)
  30.         {
  31.             var scopes = new List<object>();
  32.             foreach (var scope in _scopeStack.Value)
  33.             {
  34.                 scopes.Add(scope);
  35.             }
  36.             logEntry["Scopes"] = scopes;
  37.         }
  38.         var json = JsonSerializer.Serialize(logEntry, new JsonSerializerOptions { WriteIndented = true });
  39.         Console.WriteLine(json);
  40.     }
  41.     private class Scope : IDisposable
  42.     {
  43.         private readonly Action _onDispose;
  44.         public Scope(Action onDispose)
  45.         {
  46.             _onDispose = onDispose;
  47.         }
  48.         public void Dispose()
  49.         {
  50.             _onDispose?.Invoke();
  51.         }
  52.     }
  53. }
  54. public class ScopeLoggerProvider : ILoggerProvider
  55. {
  56.     public ILogger CreateLogger(string categoryName)
  57.     {
  58.         return new ScopeLogger(categoryName);
  59.     }
  60.     public void Dispose() { }
  61. }
  62. builder.Logging.ClearProviders();
  63. builder.Logging.AddProvider(new ScopeLoggerProvider());
复制代码
上面的代码创建了自己的 ILogger 实现,并将作用域信息以 JSON 格式输出。

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表