using System.Diagnostics.Metrics; using System.Runtime.CompilerServices; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; namespace Terminal.Gui; /// /// Singleton logging instance class. Do not use console loggers /// with this class as it will interfere with Terminal.Gui /// screen output (i.e. use a file logger). /// /// /// Also contains the /// instance that should be used for internal metrics /// (iteration timing etc.). /// public static class Logging { /// /// Logger, defaults to NullLogger (i.e. no logging). Set this to a /// file logger to enable logging of Terminal.Gui internals. /// public static ILogger Logger { get; set; } = NullLogger.Instance; /// /// Metrics reporting meter for internal Terminal.Gui processes. To use /// create your own static instrument e.g. CreateCounter, CreateHistogram etc /// internal static readonly Meter Meter = new ("Terminal.Gui"); /// /// Metric for how long it takes each full iteration of the main loop to occur /// public static readonly Histogram TotalIterationMetric = Meter.CreateHistogram ("Iteration (ms)"); /// /// Metric for how long it took to do the 'timeouts and invokes' section of main loop. /// public static readonly Histogram IterationInvokesAndTimeouts = Meter.CreateHistogram ("Invokes & Timers (ms)"); /// /// Counter for when we redraw, helps detect situations e.g. where we are repainting entire UI every loop /// public static readonly Counter Redraws = Meter.CreateCounter ("Redraws"); /// /// Metric for how long it takes to read all available input from the input stream - at which /// point input loop will sleep. /// public static readonly Histogram DrainInputStream = Meter.CreateHistogram ("Drain Input (ms)"); /// /// Logs an error message including the class and method name. /// /// /// /// public static void Error ( string message, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "" ) { string className = Path.GetFileNameWithoutExtension (filePath); Logger.LogError ($"[{className}] [{caller}] {message}"); } /// /// Logs a fatal/critical message including the class and method name. /// /// /// /// public static void Critical ( string message, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "" ) { string className = Path.GetFileNameWithoutExtension (filePath); Logger.LogCritical ($"[{className}] [{caller}] {message}"); } /// /// Logs a debug message including the class and method name. /// /// /// /// public static void Debug ( string message, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "" ) { string className = Path.GetFileNameWithoutExtension (filePath); Logger.LogDebug ($"[{className}] [{caller}] {message}"); } /// /// Logs an informational message including the class and method name. /// /// /// /// public static void Information ( string message, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "" ) { string className = Path.GetFileNameWithoutExtension (filePath); Logger.LogInformation ($"[{className}] [{caller}] {message}"); } /// /// Logs a trace/verbose message including the class and method name. /// /// /// /// public static void Trace ( string message, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "" ) { string className = Path.GetFileNameWithoutExtension (filePath); Logger.LogTrace ($"[{className}] [{caller}] {message}"); } /// /// Logs a warning message including the class and method name. /// /// /// /// public static void Warning ( string message, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "" ) { string className = Path.GetFileNameWithoutExtension (filePath); Logger.LogWarning ($"[{className}] [{caller}] {message}"); } }