emby-toolbox/EmbyToolbox/Services/LoggingService.cs
Emby Toolbox 6264b487fe Initial commit: Emby Toolbox (conversion scroll fix, bulk Del for tracks).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 21:33:47 +05:00

142 lines
4.4 KiB
C#

using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Threading;
using EmbyToolbox.ViewModels;
namespace EmbyToolbox.Services;
public sealed class LoggingService
{
private const int UiLogLimit = 1000;
private readonly string _logsDirectory;
public LoggingService()
{
_logsDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"EmbyToolbox",
"Logs");
Directory.CreateDirectory(_logsDirectory);
}
public ObservableCollection<LogEntryViewModel> UiEntries { get; } = new();
public LogLevel MinimumFileLogLevel { get; set; } = LogLevel.Info;
public string LogsDirectory => _logsDirectory;
public void Debug(string message, string module = "app", Exception? exception = null, string? command = null, string? stdout = null, string? stderr = null)
{
Write(LogLevel.Debug, message, module, exception, command, stdout, stderr);
}
public void Info(string message, string module = "app", Exception? exception = null, string? command = null, string? stdout = null, string? stderr = null)
{
Write(LogLevel.Info, message, module, exception, command, stdout, stderr);
}
public void Warning(string message, string module = "app", Exception? exception = null, string? command = null, string? stdout = null, string? stderr = null)
{
Write(LogLevel.Warning, message, module, exception, command, stdout, stderr);
}
public void Error(string message, string module = "app", Exception? exception = null, string? command = null, string? stdout = null, string? stderr = null)
{
Write(LogLevel.Error, message, module, exception, command, stdout, stderr);
}
public void ClearUi()
{
UiEntries.Clear();
}
private void Write(LogLevel level, string message, string module, Exception? exception, string? command, string? stdout, string? stderr)
{
var now = DateTime.Now;
var entry = new LogEntryViewModel
{
Timestamp = now,
Level = level,
LevelText = level.ToString(),
Module = module,
Message = message
};
AddUiEntryThreadSafe(entry);
if (level < MinimumFileLogLevel)
{
return;
}
WriteToFile(now, level, module, message, exception, command, stdout, stderr);
}
private void AddUiEntryThreadSafe(LogEntryViewModel entry)
{
var dispatcher = Application.Current?.Dispatcher;
if (dispatcher is null || dispatcher.CheckAccess())
{
UiEntries.Add(entry);
while (UiEntries.Count > UiLogLimit)
{
UiEntries.RemoveAt(0);
}
return;
}
dispatcher.BeginInvoke(
DispatcherPriority.DataBind,
new Action(
() =>
{
UiEntries.Add(entry);
while (UiEntries.Count > UiLogLimit)
{
UiEntries.RemoveAt(0);
}
}));
}
private void WriteToFile(DateTime timestamp, LogLevel level, string module, string message, Exception? exception, string? command, string? stdout, string? stderr)
{
var path = Path.Combine(_logsDirectory, $"app-{timestamp:yyyy-MM-dd}.log");
var sb = new StringBuilder();
sb.Append('[').Append(timestamp.ToString("yyyy-MM-dd HH:mm:ss")).Append("] ");
sb.Append(level.ToString().ToUpperInvariant()).Append(" ");
sb.Append("module=").Append(module).Append(" ");
sb.Append("message=").Append(message);
sb.AppendLine();
if (exception is not null)
{
sb.AppendLine("exception:");
sb.AppendLine(exception.ToString());
}
if (!string.IsNullOrWhiteSpace(command))
{
sb.Append("command: ").AppendLine(command);
}
if (!string.IsNullOrWhiteSpace(stdout))
{
sb.AppendLine("stdout:");
sb.AppendLine(stdout);
}
if (!string.IsNullOrWhiteSpace(stderr))
{
sb.AppendLine("stderr:");
sb.AppendLine(stderr);
}
sb.AppendLine(new string('-', 80));
File.AppendAllText(path, sb.ToString(), Encoding.UTF8);
}
}