Skip to content

Instantly share code, notes, and snippets.

@djeikyb
Last active June 6, 2022 22:16
Show Gist options
  • Save djeikyb/569f1815e511763937a020f2a5bc07ed to your computer and use it in GitHub Desktop.
Save djeikyb/569f1815e511763937a020f2a5bc07ed to your computer and use it in GitHub Desktop.
using Ardalis.GuardClauses;
using Microsoft.Extensions.Logging;
public static class LoggerExtensions
{
/// <summary>
/// Begins a logical operation scope.
/// </summary>
/// <example>
/// <para>
/// For single properties, use like:
/// </para>
/// <code>
/// using var _ = logger.BeginScope("DurationMs", timer.Total);
/// logger.LogDebug("Operation completed successfully.");
/// </code>
/// <para>
/// To get nested structures into the logs, start the key name with an @
/// symbol (the serilog destructuring operator):
/// </para>
/// <code>
/// using var _ = logger.BeginScope("@RateLimit", rateLimitResponse);
/// logger.LogDebug("Operation completed successfully.");
/// </code>
/// <para>
/// https://github.com/serilog/serilog/wiki/Structured-Data#preserving-object-structure
/// </para>
/// </example>
/// <param name="key">
/// The <see cref="value"/> will be serialized if the key name starts with
/// an @ symbol (the serilog destructuring operator)
/// </param>
/// <param name="value">
/// Can be a simple value type like string or int, or a data class. If you
/// pass a data class, its structure can be replicated and queryable in the
/// logs, IF the key name starts with an @ symbol.
/// </param>
/// <returns>An <see cref="IDisposable"/> that ends the logical operation scope on dispose.</returns>
public static IDisposable BeginScope<T>(this ILogger<T> logger, string key, object value)
{
Guard.Against.Empty(key);
// The dictionary type is special. Must be string,object or the log
// object won't be populated correctly.
var state = new Dictionary<string, object>();
state.Add(key, value);
return logger.BeginScope(state);
}
/// <summary>
/// Pass this to <see cref="Logger{T}.BeginScope"/>.
/// Important that the k:v types are string:object!
/// Changing the value type to string will not populate the log object correctly.
/// </summary>
public static Dictionary<string, object> CreateScopeState<T>(this ILogger<T> logger)
{
return new Dictionary<string, object>();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment