< Summary

Information
Class: ArturRios.Logging.StateLogger
Assembly: ArturRios.Logging
File(s): /home/ci/agent/workspace/dotnet-logging-docs_main/app/src/StateLogger.cs
Line coverage
98%
Covered lines: 59
Uncovered lines: 1
Coverable lines: 60
Total lines: 193
Line coverage: 98.3%
Branch coverage
92%
Covered branches: 52
Total branches: 56
Branch coverage: 92.8%
Method coverage
100%
Covered methods: 12
Fully covered methods: 11
Total methods: 12
Method coverage: 100%
Full method coverage: 91.6%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%2283.33%
get_TraceId()100%11100%
Trace(...)100%22100%
Debug(...)100%22100%
Info(...)100%22100%
Warn(...)100%22100%
Error(...)100%22100%
Exception(...)100%22100%
Critical(...)100%22100%
Fatal(...)100%22100%
ResolveCallerInfo(...)91.66%3636100%
FormatMessageWithTraceId(...)100%22100%

File(s)

/home/ci/agent/workspace/dotnet-logging-docs_main/app/src/StateLogger.cs

#LineLine coverage
 1using ArturRios.Logging.Configuration;
 2using ArturRios.Logging.Factories;
 3using ArturRios.Logging.Interfaces;
 4
 5namespace ArturRios.Logging;
 6
 7/// <summary>
 8/// A logger that extracts caller information from state objects passed with log messages.
 9/// Useful for integration with dependency injection frameworks and structured logging.
 10/// </summary>
 11public class StateLogger : IStateLogger
 12{
 2813    private readonly List<IInternalLogger> _loggers = [];
 14
 15    /// <summary>
 16    /// Gets or sets the trace ID for correlating log entries across related operations.
 17    /// </summary>
 4118    public string? TraceId { get; set; }
 19
 20    /// <summary>
 21    /// Initializes a new instance of the <see cref="StateLogger"/> class with the specified configurations.
 22    /// </summary>
 23    /// <param name="configurations">The list of logger configurations to use.</param>
 24    /// <exception cref="ArgumentNullException"><paramref name="configurations"/>, or one of its items, is <c>null</c>.<
 2825    public StateLogger(List<LoggerConfiguration> configurations)
 26    {
 2827        ArgumentNullException.ThrowIfNull(configurations);
 28
 5429        foreach (var config in configurations)
 30        {
 031            _loggers.Add(InternalLoggerFactory.Create(config));
 32        }
 2733    }
 34
 35    /// <summary>
 36    /// Logs a trace-level message with caller information extracted from state.
 37    /// </summary>
 38    /// <param name="message">The message to log.</param>
 39    /// <param name="state">Optional state object containing caller information.</param>
 40    public void Trace(string message, object? state = null)
 41    {
 342        var (fp, mn) = ResolveCallerInfo(state);
 1243        foreach (var logger in _loggers)
 44        {
 345            logger.Trace(FormatMessageWithTraceId(message), fp, mn);
 46        }
 347    }
 48
 49    /// <summary>
 50    /// Logs a debug-level message with caller information extracted from state.
 51    /// </summary>
 52    /// <param name="message">The message to log.</param>
 53    /// <param name="state">Optional state object containing caller information.</param>
 54    public void Debug(string message, object? state = null)
 55    {
 456        var (fp, mn) = ResolveCallerInfo(state);
 1657        foreach (var logger in _loggers)
 58        {
 459            logger.Debug(FormatMessageWithTraceId(message), fp, mn);
 60        }
 461    }
 62
 63    /// <summary>
 64    /// Logs an information-level message with caller information extracted from state.
 65    /// </summary>
 66    /// <param name="message">The message to log.</param>
 67    /// <param name="state">Optional state object containing caller information.</param>
 68    public void Info(string message, object? state = null)
 69    {
 570        var (fp, mn) = ResolveCallerInfo(state);
 2271        foreach (var logger in _loggers)
 72        {
 673            logger.Info(FormatMessageWithTraceId(message), fp, mn);
 74        }
 575    }
 76
 77    /// <summary>
 78    /// Logs a warning-level message with caller information extracted from state.
 79    /// </summary>
 80    /// <param name="message">The message to log.</param>
 81    /// <param name="state">Optional state object containing caller information.</param>
 82    public void Warn(string message, object? state = null)
 83    {
 384        var (fp, mn) = ResolveCallerInfo(state);
 1285        foreach (var logger in _loggers)
 86        {
 387            logger.Warn(FormatMessageWithTraceId(message), fp, mn);
 88        }
 389    }
 90
 91    /// <summary>
 92    /// Logs an error-level message with caller information extracted from state.
 93    /// </summary>
 94    /// <param name="message">The message to log.</param>
 95    /// <param name="state">Optional state object containing caller information.</param>
 96    public void Error(string message, object? state = null)
 97    {
 398        var (fp, mn) = ResolveCallerInfo(state);
 1299        foreach (var logger in _loggers)
 100        {
 3101            logger.Error(FormatMessageWithTraceId(message), fp, mn);
 102        }
 3103    }
 104
 105    /// <summary>
 106    /// Logs an exception with caller information extracted from state.
 107    /// </summary>
 108    /// <param name="exception">The exception to log.</param>
 109    /// <param name="state">Optional state object containing caller information.</param>
 110    public void Exception(Exception exception, object? state = null)
 111    {
 3112        ArgumentNullException.ThrowIfNull(exception);
 113
 3114        var (fp, mn) = ResolveCallerInfo(state);
 3115        var msg = FormatMessageWithTraceId(exception.ToString());
 12116        foreach (var logger in _loggers)
 117        {
 3118            logger.Exception(msg, fp, mn);
 119        }
 3120    }
 121
 122    /// <summary>
 123    /// Logs a critical-level message with caller information extracted from state.
 124    /// </summary>
 125    /// <param name="message">The message to log.</param>
 126    /// <param name="state">Optional state object containing caller information.</param>
 127    public void Critical(string message, object? state = null)
 128    {
 3129        var (fp, mn) = ResolveCallerInfo(state);
 12130        foreach (var logger in _loggers)
 131        {
 3132            logger.Critical(FormatMessageWithTraceId(message), fp, mn);
 133        }
 3134    }
 135
 136    /// <summary>
 137    /// Logs a fatal-level message with caller information extracted from state.
 138    /// </summary>
 139    /// <param name="message">The message to log.</param>
 140    /// <param name="state">Optional state object containing caller information.</param>
 141    public void Fatal(string message, object? state = null)
 142    {
 3143        var (fp, mn) = ResolveCallerInfo(state);
 12144        foreach (var logger in _loggers)
 145        {
 3146            logger.Fatal(FormatMessageWithTraceId(message), fp, mn);
 147        }
 3148    }
 149
 150    private static (string filePath, string methodName) ResolveCallerInfo(object? state)
 151    {
 27152        string? filePath = null;
 27153        string? methodName = null;
 154
 27155        if (state is not IEnumerable<KeyValuePair<string, object>> pairs)
 156        {
 7157            return (filePath ?? "unknown", methodName ?? "unknown");
 158        }
 159
 101160        foreach (var (key, value) in pairs)
 161        {
 40162            if (value is null)
 163            {
 164                continue;
 165            }
 166
 39167            if (filePath == null && (string.Equals(key, "CallerFilePath", StringComparison.OrdinalIgnoreCase) ||
 39168                                     string.Equals(key, "FilePath", StringComparison.OrdinalIgnoreCase) ||
 39169                                     string.Equals(key, "callerFilePath", StringComparison.OrdinalIgnoreCase)))
 170            {
 19171                filePath = value.ToString();
 172            }
 173
 39174            if (methodName == null && (string.Equals(key, "CallerMemberName", StringComparison.OrdinalIgnoreCase) ||
 39175                                       string.Equals(key, "MemberName", StringComparison.OrdinalIgnoreCase) ||
 39176                                       string.Equals(key, "Method", StringComparison.OrdinalIgnoreCase) ||
 39177                                       string.Equals(key, "callerMemberName", StringComparison.OrdinalIgnoreCase)))
 178            {
 20179                methodName = value.ToString();
 180            }
 181
 39182            if (filePath != null && methodName != null)
 19183                break;
 184        }
 185
 20186        return (filePath ?? "unknown", methodName ?? "unknown");
 187    }
 188
 189    private string FormatMessageWithTraceId(string message)
 190    {
 28191        return !string.IsNullOrEmpty(TraceId) ? $"[{nameof(TraceId)}] {TraceId} | {message}" : message;
 192    }
 193}