溯源设备 发表于 2025-2-6 12:46:21

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

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

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

使用 BeginScope 方法在日志中添加上下文信息,如下代码手动显示:
public string Get(){    using (_logger.BeginScope("TenantName {TenantName}", "test"))    {      _logger.LogInformation("这是一条测试日志信息");    }    return "ok";}在这段代码中,我们使用 BeginScope 创建了一个作用域,并设置了一个上下文变量。在这个作用域之内,日志信息将包含这个上下文变量。

 
将作用域信息 JSON化

通过实现自己的 ILogger 接口,我们可以将作用域信息以 JSON 格式输出:
public class ScopeLogger : ILogger{    private readonly string _categoryName;    private static readonly AsyncLocal<Stack<object>> _scopeStack = new AsyncLocal<Stack<object>>();    public ScopeLogger(string categoryName)    {      _categoryName = categoryName;    }    public IDisposable BeginScope<TState>(TState state) where TState : notnull    {      if (_scopeStack.Value == null)      {            _scopeStack.Value = new Stack<object>();      }      _scopeStack.Value.Push(state);      return new Scope(() => _scopeStack.Value.Pop());    }    public bool IsEnabled(LogLevel logLevel) => true;    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)    {      var logEntry = new Dictionary<string, object>      {            ["Timestamp"] = DateTime.UtcNow,            ["LogLevel"] = logLevel.ToString(),            ["Category"] = _categoryName,            ["Message"] = formatter(state, exception),            ["Exception"] = exception?.ToString()      };      if (_scopeStack.Value != null && _scopeStack.Value.Count > 0)      {            var scopes = new List<object>();            foreach (var scope in _scopeStack.Value)            {                scopes.Add(scope);            }            logEntry["Scopes"] = scopes;      }      var json = JsonSerializer.Serialize(logEntry, new JsonSerializerOptions { WriteIndented = true });      Console.WriteLine(json);    }    private class Scope : IDisposable    {      private readonly Action _onDispose;      public Scope(Action onDispose)      {            _onDispose = onDispose;      }      public void Dispose()      {            _onDispose?.Invoke();      }    }}public class ScopeLoggerProvider : ILoggerProvider{    public ILogger CreateLogger(string categoryName)    {      return new ScopeLogger(categoryName);    }    public void Dispose() { }}builder.Logging.ClearProviders();builder.Logging.AddProvider(new ScopeLoggerProvider());上面的代码创建了自己的 ILogger 实现,并将作用域信息以 JSON 格式输出。

 
页: [1]
查看完整版本: .NET 中 Logger 常被忽视的方法 BeginScope