Logging.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System.Diagnostics.Metrics;
  2. using System.Runtime.CompilerServices;
  3. using Microsoft.Extensions.Logging;
  4. using Microsoft.Extensions.Logging.Abstractions;
  5. namespace Terminal.Gui;
  6. /// <summary>
  7. /// Singleton logging instance class. Do not use console loggers
  8. /// with this class as it will interfere with Terminal.Gui
  9. /// screen output (i.e. use a file logger).
  10. /// </summary>
  11. /// <remarks>
  12. /// Also contains the
  13. /// <see cref="Meter"/> instance that should be used for internal metrics
  14. /// (iteration timing etc.).
  15. /// </remarks>
  16. public static class Logging
  17. {
  18. /// <summary>
  19. /// Logger, defaults to NullLogger (i.e. no logging). Set this to a
  20. /// file logger to enable logging of Terminal.Gui internals.
  21. /// </summary>
  22. public static ILogger Logger { get; set; } = NullLogger.Instance;
  23. /// <summary>
  24. /// Metrics reporting meter for internal Terminal.Gui processes. To use
  25. /// create your own static instrument e.g. CreateCounter, CreateHistogram etc
  26. /// </summary>
  27. internal static readonly Meter Meter = new ("Terminal.Gui");
  28. /// <summary>
  29. /// Metric for how long it takes each full iteration of the main loop to occur
  30. /// </summary>
  31. public static readonly Histogram<int> TotalIterationMetric = Meter.CreateHistogram<int> ("Iteration (ms)");
  32. /// <summary>
  33. /// Metric for how long it took to do the 'timeouts and invokes' section of main loop.
  34. /// </summary>
  35. public static readonly Histogram<int> IterationInvokesAndTimeouts = Meter.CreateHistogram<int> ("Invokes & Timers (ms)");
  36. /// <summary>
  37. /// Counter for when we redraw, helps detect situations e.g. where we are repainting entire UI every loop
  38. /// </summary>
  39. public static readonly Counter<int> Redraws = Meter.CreateCounter<int> ("Redraws");
  40. /// <summary>
  41. /// Metric for how long it takes to read all available input from the input stream - at which
  42. /// point input loop will sleep.
  43. /// </summary>
  44. public static readonly Histogram<int> DrainInputStream = Meter.CreateHistogram<int> ("Drain Input (ms)");
  45. /// <summary>
  46. /// Logs an error message including the class and method name.
  47. /// </summary>
  48. /// <param name="message"></param>
  49. /// <param name="caller"></param>
  50. /// <param name="filePath"></param>
  51. public static void Error (
  52. string message,
  53. [CallerMemberName] string caller = "",
  54. [CallerFilePath] string filePath = ""
  55. )
  56. {
  57. string className = Path.GetFileNameWithoutExtension (filePath);
  58. Logger.LogError ($"[{className}] [{caller}] {message}");
  59. }
  60. /// <summary>
  61. /// Logs a fatal/critical message including the class and method name.
  62. /// </summary>
  63. /// <param name="message"></param>
  64. /// <param name="caller"></param>
  65. /// <param name="filePath"></param>
  66. public static void Critical (
  67. string message,
  68. [CallerMemberName] string caller = "",
  69. [CallerFilePath] string filePath = ""
  70. )
  71. {
  72. string className = Path.GetFileNameWithoutExtension (filePath);
  73. Logger.LogCritical ($"[{className}] [{caller}] {message}");
  74. }
  75. /// <summary>
  76. /// Logs a debug message including the class and method name.
  77. /// </summary>
  78. /// <param name="message"></param>
  79. /// <param name="caller"></param>
  80. /// <param name="filePath"></param>
  81. public static void Debug (
  82. string message,
  83. [CallerMemberName] string caller = "",
  84. [CallerFilePath] string filePath = ""
  85. )
  86. {
  87. string className = Path.GetFileNameWithoutExtension (filePath);
  88. Logger.LogDebug ($"[{className}] [{caller}] {message}");
  89. }
  90. /// <summary>
  91. /// Logs an informational message including the class and method name.
  92. /// </summary>
  93. /// <param name="message"></param>
  94. /// <param name="caller"></param>
  95. /// <param name="filePath"></param>
  96. public static void Information (
  97. string message,
  98. [CallerMemberName] string caller = "",
  99. [CallerFilePath] string filePath = ""
  100. )
  101. {
  102. string className = Path.GetFileNameWithoutExtension (filePath);
  103. Logger.LogInformation ($"[{className}] [{caller}] {message}");
  104. }
  105. /// <summary>
  106. /// Logs a trace/verbose message including the class and method name.
  107. /// </summary>
  108. /// <param name="message"></param>
  109. /// <param name="caller"></param>
  110. /// <param name="filePath"></param>
  111. public static void Trace (
  112. string message,
  113. [CallerMemberName] string caller = "",
  114. [CallerFilePath] string filePath = ""
  115. )
  116. {
  117. string className = Path.GetFileNameWithoutExtension (filePath);
  118. Logger.LogTrace ($"[{className}] [{caller}] {message}");
  119. }
  120. /// <summary>
  121. /// Logs a warning message including the class and method name.
  122. /// </summary>
  123. /// <param name="message"></param>
  124. /// <param name="caller"></param>
  125. /// <param name="filePath"></param>
  126. public static void Warning (
  127. string message,
  128. [CallerMemberName] string caller = "",
  129. [CallerFilePath] string filePath = ""
  130. )
  131. {
  132. string className = Path.GetFileNameWithoutExtension (filePath);
  133. Logger.LogWarning ($"[{className}] [{caller}] {message}");
  134. }
  135. }