< Summary

Information
Class: GridForge.GridForgeLogger
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Utility/GridForgeLogger.cs
Line coverage
100%
Covered lines: 40
Uncovered lines: 0
Coverable lines: 40
Total lines: 156
Line coverage: 100%
Branch coverage
100%
Covered branches: 7
Total branches: 7
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
get_Channel()100%11100%
get_DebugChannel()100%11100%
get_EnableDebugLogging()100%11100%
set_EnableDebugLogging(...)100%11100%
get_LogHandler()100%11100%
set_LogHandler(...)100%11100%
get_CustomFormatter()100%11100%
set_CustomFormatter(...)100%11100%
get_LogFilePath()100%11100%
set_LogFilePath(...)100%11100%
get_MinimumLevel()100%11100%
set_MinimumLevel(...)100%11100%
IsEnabled(...)100%11100%
DefaultLogHandler(...)100%11100%
DefaultLogFormatter(...)100%11100%
.ctor()100%11100%
DefaultLogHandler(...)100%22100%
DefaultLogFormatter(...)100%55100%

File(s)

/home/runner/work/GridForge/GridForge/src/GridForge/Utility/GridForgeLogger.cs

#LineLine coverage
 1//=======================================================================
 2// GridForgeLogger.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8global using SwiftCollections.Diagnostics;
 9
 10using System;
 11using System.IO;
 12
 13namespace GridForge;
 14
 15/// <summary>
 16/// Provides a configurable logging system for GridForge with support for log levels, formatting, and file output.
 17/// </summary>
 18public static class GridForgeLogger
 19{
 120    private static readonly GridForgeDiagnosticLogger _logger = new();
 21
 22    /// <summary>
 23    /// Gets the diagnostic channel used by GridForge logging.
 24    /// </summary>
 54725    public static DiagnosticChannel Channel => _logger.Channel;
 26
 27    /// <summary>
 28    /// Gets the diagnostic channel used for verbose debug diagnostics.
 29    /// </summary>
 330    public static DiagnosticChannel DebugChannel => _logger.DebugChannel;
 31
 32    /// <summary>
 33    /// Gets or sets a value indicating whether verbose debug diagnostics should be emitted.
 34    /// </summary>
 35    public static bool EnableDebugLogging
 36    {
 337        get => _logger.EnableDebugLogging;
 638        set => _logger.EnableDebugLogging = value;
 39    }
 40
 41    /// <summary>
 42    /// Gets or sets the delegate used to write formatted log messages.
 43    /// Assigning <see langword="null"/> restores <see cref="DefaultLogHandler"/>.
 44    /// </summary>
 45    public static Action<DiagnosticLevel, string, string> LogHandler
 46    {
 2147        get => _logger.LogHandler;
 4148        set => _logger.LogHandler = value;
 49    }
 50
 51    /// <summary>
 52    /// Gets or sets the formatter used to transform log arguments into a final log entry.
 53    /// Assigning <see langword="null"/> restores <see cref="DefaultLogFormatter"/>.
 54    /// </summary>
 55    public static Func<DiagnosticLevel, string, string, string> CustomFormatter
 56    {
 957        get => _logger.CustomFormatter;
 1158        set => _logger.CustomFormatter = value;
 59    }
 60
 61    /// <summary>
 62    /// Gets or sets the file path for logging. If null, file logging is disabled.
 63    /// </summary>
 64    public static string? LogFilePath
 65    {
 366        get => _logger.LogFilePath;
 667        set => _logger.LogFilePath = value;
 68    }
 69
 70    /// <summary>
 71    /// Gets or sets the minimum log level required for messages to be logged.
 72    /// </summary>
 73    public static DiagnosticLevel MinimumLevel
 74    {
 2175        get => _logger.MinimumLevel;
 4376        set => _logger.MinimumLevel = value;
 77    }
 78
 79    /// <summary>
 80    /// Determines whether diagnostics at the specified level are currently enabled.
 81    /// </summary>
 82    /// <param name="level">The diagnostic level to evaluate.</param>
 83    /// <returns><see langword="true"/> when messages at <paramref name="level"/> will be emitted; otherwise, <see langw
 84    public static bool IsEnabled(DiagnosticLevel level)
 85    {
 286        return _logger.IsEnabled(level);
 87    }
 88
 89    /// <summary>
 90    /// The default handler for logging messages, writing them to the console and optionally to a file.
 91    /// </summary>
 92    /// <param name="level">The severity level of the log message.</param>
 93    /// <param name="message">The log message.</param>
 94    /// <param name="source">The source of the log message.</param>
 95    public static void DefaultLogHandler(DiagnosticLevel level, string message, string source)
 96    {
 197        _logger.DefaultLogHandler(level, message, source);
 198    }
 99
 100    /// <summary>
 101    /// The default log formatter that formats log messages with timestamp, log level, and source information.
 102    /// </summary>
 103    /// <param name="level">The severity level of the log message.</param>
 104    /// <param name="message">The log message.</param>
 105    /// <param name="source">The source of the log message.</param>
 106    /// <returns>A formatted log entry as a string.</returns>
 107    public static string DefaultLogFormatter(DiagnosticLevel level, string message, string source)
 108    {
 1109        return _logger.DefaultLogFormatter(level, message, source);
 110    }
 111
 112    private sealed class GridForgeDiagnosticLogger : DiagnosticLogger
 113    {
 1114        private readonly object _lock = new();
 115
 2116        public GridForgeDiagnosticLogger() : base("GridForge") { }
 117
 118        public string? LogFilePath { get; set; }
 119
 120        public override void DefaultLogHandler(DiagnosticLevel level, string message, string source)
 121        {
 34122            lock (_lock)
 123            {
 34124                string logEntry = CustomFormatter(level, message, source);
 34125                Console.WriteLine(logEntry);
 126
 34127                if (!string.IsNullOrEmpty(LogFilePath))
 128                {
 129                    try
 130                    {
 2131                        File.AppendAllText(LogFilePath, logEntry + Environment.NewLine);
 1132                    }
 1133                    catch (Exception ex)
 134                    {
 1135                        Console.WriteLine($"[ERROR] Failed to write to log file: {ex.Message}");
 1136                    }
 137                }
 32138            }
 34139        }
 140
 141        public override string DefaultLogFormatter(DiagnosticLevel level, string message, string source)
 142        {
 38143            var timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
 38144            var levelTag = level switch
 38145            {
 1146                DiagnosticLevel.None => "[NONE]",
 2147                DiagnosticLevel.Info => "[INFO]",
 2148                DiagnosticLevel.Warning => "[WARN]",
 32149                DiagnosticLevel.Error => "[ERROR]",
 1150                _ => "[LOG]"
 38151            };
 152
 38153            return $"{timestamp} {levelTag} [{source}] {message}";
 154        }
 155    }
 156}