Route legacy logging through file logger provider
Connects existing exception logging to the new file logger and adds an ILoggerProvider bridge for Microsoft logging.feature/centralized-offline-canteen
parent
2ce78b6c65
commit
42cd473e73
|
|
@ -1,53 +1,52 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using UtopiaCanteenSystem.Services.Logging;
|
||||||
|
|
||||||
namespace UtopiaCanteenSystem.Services;
|
namespace UtopiaCanteenSystem.Services;
|
||||||
|
|
||||||
public static class Logger
|
public static class Logger
|
||||||
{
|
{
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
public static void Log(Exception ex, string context = "")
|
public static void Log(Exception ex, string context = "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (ex == null) return;
|
if (ex == null)
|
||||||
|
return;
|
||||||
|
|
||||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
if (FileLogger.IsConfigured)
|
||||||
var appRoot = Path.Combine(localAppData, "UtopiaCanteenSystem");
|
|
||||||
var logsDir = Path.Combine(appRoot, "Logs");
|
|
||||||
var logFile = Path.Combine(logsDir, "error.log");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(logsDir))
|
|
||||||
Directory.CreateDirectory(logsDir);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
|
FileLogger.Error(context, ex.Message, ex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
WriteLegacyErrorLog(ex, context);
|
||||||
sb.AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]");
|
|
||||||
if (!string.IsNullOrWhiteSpace(context))
|
|
||||||
sb.AppendLine($"Context: {context}");
|
|
||||||
sb.AppendLine($"Message: {ex.Message}");
|
|
||||||
sb.AppendLine($"StackTrace: {ex.StackTrace}");
|
|
||||||
if (ex.InnerException != null)
|
|
||||||
sb.AppendLine($"InnerException: {ex.InnerException.Message}");
|
|
||||||
sb.AppendLine("----------------------------------------------------");
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
File.AppendAllText(logFile, sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// never throw from logger
|
// never throw from logger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void WriteLegacyErrorLog(Exception ex, string context)
|
||||||
|
{
|
||||||
|
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
|
var logsDir = Path.Combine(localAppData, "UtopiaCanteenSystem", "Logs");
|
||||||
|
var logFile = Path.Combine(logsDir, "error.log");
|
||||||
|
|
||||||
|
if (!Directory.Exists(logsDir))
|
||||||
|
Directory.CreateDirectory(logsDir);
|
||||||
|
|
||||||
|
var lines = new List<string>
|
||||||
|
{
|
||||||
|
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]",
|
||||||
|
string.IsNullOrWhiteSpace(context) ? string.Empty : $"Context: {context}",
|
||||||
|
$"Message: {ex.Message}",
|
||||||
|
$"StackTrace: {ex.StackTrace}"
|
||||||
|
};
|
||||||
|
if (ex.InnerException != null)
|
||||||
|
lines.Add($"InnerException: {ex.InnerException.Message}");
|
||||||
|
lines.Add("----------------------------------------------------");
|
||||||
|
|
||||||
|
File.AppendAllText(logFile, string.Join(Environment.NewLine, lines.Where(l => !string.IsNullOrEmpty(l))) + Environment.NewLine);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace UtopiaCanteenSystem.Services.Logging;
|
||||||
|
|
||||||
|
public sealed class FileLoggerProvider : ILoggerProvider
|
||||||
|
{
|
||||||
|
public ILogger CreateLogger(string categoryName) => new FileLoggerAdapter(categoryName);
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class FileLoggerAdapter : ILogger
|
||||||
|
{
|
||||||
|
private readonly string _category;
|
||||||
|
|
||||||
|
public FileLoggerAdapter(string category) => _category = category;
|
||||||
|
|
||||||
|
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
|
||||||
|
|
||||||
|
public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Information;
|
||||||
|
|
||||||
|
public void Log<TState>(
|
||||||
|
LogLevel logLevel,
|
||||||
|
EventId eventId,
|
||||||
|
TState state,
|
||||||
|
Exception? exception,
|
||||||
|
Func<TState, Exception?, string> formatter)
|
||||||
|
{
|
||||||
|
if (!IsEnabled(logLevel))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var message = formatter(state, exception);
|
||||||
|
var component = ShortCategory(_category);
|
||||||
|
switch (logLevel)
|
||||||
|
{
|
||||||
|
case LogLevel.Critical:
|
||||||
|
case LogLevel.Error:
|
||||||
|
FileLogger.Error(component, message, exception);
|
||||||
|
break;
|
||||||
|
case LogLevel.Warning:
|
||||||
|
FileLogger.Warn(component, message, exception);
|
||||||
|
break;
|
||||||
|
case LogLevel.Debug:
|
||||||
|
case LogLevel.Trace:
|
||||||
|
FileLogger.Debug(component, message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FileLogger.Info(component, message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ShortCategory(string category)
|
||||||
|
{
|
||||||
|
var idx = category.LastIndexOf('.');
|
||||||
|
return idx >= 0 ? category[(idx + 1)..] : category;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue