Skip to content

Instantly share code, notes, and snippets.

@djeikyb
Last active December 22, 2023 01:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save djeikyb/eeb600e1ce3619059adec6c8ca304923 to your computer and use it in GitHub Desktop.
Save djeikyb/eeb600e1ce3619059adec6c8ca304923 to your computer and use it in GitHub Desktop.
Fluent methods to add scope state key-value pairs to your logs!
using Microsoft.Extensions.Logging;
public static class LogEx
{
public static ScopeStateBuilder<T> With<T>(this ILogger<T> logger, string k, object? v) => new(logger, k, v);
public sealed class ScopeStateBuilder<T> : ILogger<T>
{
private readonly ILogger<T> _logger;
private readonly IDictionary<string, object?> _state = new Dictionary<string, object?>();
public ScopeStateBuilder(ILogger<T> logger, string k, object? v)
{
_logger = logger;
_state[k] = v;
}
public ScopeStateBuilder<T> With(string k, object? v)
{
_state[k] = v;
return this;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
using var _ = _logger.BeginScope(_state);
_logger.Log(logLevel, eventId, state, exception, formatter);
}
public bool IsEnabled(LogLevel logLevel) => _logger.IsEnabled(logLevel);
public IDisposable? BeginScope() => _logger.BeginScope(_state);
/// Why would you use this? Use the fluent <see cref="With"/> and <see cref="BeginScope()"/> instead!
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => _logger.BeginScope(state);
}
}
using Microsoft.Extensions.Logging;
var lf = LoggerFactory.Create(lb => lb.AddJsonConsole(o => o.IncludeScopes = true));
var mel = lf.CreateLogger<Program>();
using var _ = mel.With("app", "example");
mel.With("hey", "ho")
.With("🐛", "🐞")
.LogInformation("pbbbtth");
mel.LogInformation("fwop");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment