BryanWilhite / SonghayCore

core reusable, opinionated concerns for *all* 🧐 of my C# projects
http://songhayblog.azurewebsites.net/
MIT License
1 stars 0 forks source link

add `ILoggerExtensions` and a dependency on `Microsoft.Extensions.Logging` #162

Closed BryanWilhite closed 7 months ago

BryanWilhite commented 7 months ago

/// <summary>
/// Extensions of <see cref="ILogger"/>
/// to assist with “structured logging.”
/// </summary>
/// <remarks>
/// For a video overview, see https://www.youtube.com/watch?v=NlBjVJPkT6M 🎥
/// </remarks>
public static class ILoggerExtensions
{
    /// <summary>
    /// Calls <see cref="LoggerExtensions.LogError(ILogger, string?, object?[])" /> for missing data.
    /// </summary>
    /// <param name="logger">The logger.</param>
    /// <param name="caption">The caption.</param>
    public static void LogErrorForMissingData(this ILogger? logger, string caption)
    {
        logger?.LogError("The expected {caption} data is not here.", caption);
    }

    /// <summary>
    /// Calls <see cref="LoggerExtensions.LogError(ILogger, string?, object?[])"/> for missing data.
    /// </summary>
    /// <typeparam name="TData">The type of the data.</typeparam>
    /// <param name="logger">The logger.</param>
    public static void LogErrorForMissingData<TData>(this ILogger? logger)
    {
        var dataType = typeof(TData);
        logger?.LogError("The expected {dataType} data is not here.", dataType);
    }

    /// <summary>
    /// Logs <see cref="Environment.NewLine"/> for human readability.
    /// </summary>
    /// <param name="logger">The logger.</param>
    /// <param name="level">The level.</param>
    public static void LogNewLine(this ILogger? logger, LogLevel level)
    {
        switch (level)
        {
            case LogLevel.Trace:
                logger?.LogTrace("{newLine}", Environment.NewLine);
                break;
            case LogLevel.Debug:
                logger?.LogDebug("{newLine}", Environment.NewLine);
                break;
            case LogLevel.Information:
                logger?.LogInformation("{newLine}", Environment.NewLine);
                break;
            case LogLevel.Warning:
                logger?.LogWarning("{newLine}", Environment.NewLine);
                break;
            case LogLevel.Error:
                logger?.LogError("{newLine}", Environment.NewLine);
                break;
            case LogLevel.Critical:
                logger?.LogCritical("{newLine}", Environment.NewLine);
                break;
        }
    }

    /// <summary>
    /// Calls <see cref="LogNewLine(ILogger?, LogLevel)"/>
    /// for <see cref="LogLevel.Information"/>.
    /// </summary>
    /// <param name="logger">The logger.</param>
    public static void LogInformationNewLine(this ILogger? logger) => logger.LogNewLine(LogLevel.Information);

    /// <summary>
    /// Traces data type and value.
    /// </summary>
    /// <typeparam name="TData">The type of the data.</typeparam>
    /// <param name="logger">The logger.</param>
    /// <param name="data">The data.</param>
    /// <remarks>
    /// For the best results, ensure that the <see cref="object.ToString"/> method is properly overridden.
    /// </remarks>
    public static void LogTraceDataTypeAndValue<TData>(this ILogger? logger, TData? data)
    {
        var type = typeof(TData);
        logger?.LogTrace("{dataType}: {dataValue}", type.Name, data);
    }

    /// <summary>
    /// Calls <see cref="LogNewLine(ILogger?, LogLevel)"/>
    /// for <see cref="LogLevel.Trace"/>.
    /// </summary>
    /// <param name="logger">The logger.</param>
    public static void LogTraceNewLine(this ILogger? logger) => logger.LogNewLine(LogLevel.Trace);

    /// <summary>
    /// Conventional trace of the specified method call.
    /// </summary>
    /// <param name="logger">The logger.</param>
    /// <param name="methodName">Name of the method.</param>
    public static void LogTraceMethodCall(this ILogger? logger, string? methodName)
    {
        logger?.LogTrace("Calling {methodName}...", methodName);
    }
}