Fix gestione allegati e creato metodo di esportazione log
This commit is contained in:
185
SteUp.Maui/Core/Logger/FileLogger.cs
Normal file
185
SteUp.Maui/Core/Logger/FileLogger.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace SteUp.Maui.Core.Logger;
|
||||
|
||||
public class FileLogger : ILogger
|
||||
{
|
||||
private readonly string _path;
|
||||
private readonly string _fileNamePrefix;
|
||||
private readonly string _categoryName;
|
||||
private readonly Lock _lock = new();
|
||||
private readonly int _retentionDays;
|
||||
private string? _currentFileName;
|
||||
private DateTime _currentFileDate;
|
||||
private DateTime _lastCleanupDate;
|
||||
|
||||
public FileLogger(string path, string fileNamePrefix, string categoryName, int retentionDays = 60)
|
||||
{
|
||||
_path = path;
|
||||
_fileNamePrefix = fileNamePrefix;
|
||||
_retentionDays = retentionDays;
|
||||
_lastCleanupDate = DateTime.MinValue;
|
||||
_categoryName = categoryName;
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
UpdateCurrentFileName();
|
||||
TryCleanOldLogs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elimina i log più vecchi di <see cref="_retentionDays"/> giorni.
|
||||
/// Viene eseguita al massimo una volta al giorno.
|
||||
/// </summary>
|
||||
private void ClearOldLogs()
|
||||
{
|
||||
try
|
||||
{
|
||||
var cutoff = DateTime.Now.Date.AddDays(-_retentionDays);
|
||||
var logFiles = Directory.GetFiles(_path, $"{_fileNamePrefix}-*.log");
|
||||
|
||||
foreach (var file in logFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileNameWithoutExtension(file);
|
||||
|
||||
var datePart = fileName[(_fileNamePrefix.Length + 1)..];
|
||||
|
||||
if (!DateTime.TryParseExact(datePart, "yyyy-MM-dd",
|
||||
CultureInfo.InvariantCulture,
|
||||
DateTimeStyles.None,
|
||||
out var fileDate) || fileDate >= cutoff) continue;
|
||||
File.Delete(file);
|
||||
Debug.WriteLine($"[FileLogger] Log eliminato: {file}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[FileLogger] Errore durante l'eliminazione del file {file}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[FileLogger] Errore durante la pulizia dei log: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue la pulizia dei log solo se non è già stata eseguita oggi.
|
||||
/// </summary>
|
||||
private void TryCleanOldLogs()
|
||||
{
|
||||
var today = DateTime.Now.Date;
|
||||
if (_lastCleanupDate == today) return;
|
||||
_lastCleanupDate = today;
|
||||
ClearOldLogs();
|
||||
}
|
||||
|
||||
private void UpdateCurrentFileName()
|
||||
{
|
||||
var today = DateTime.Now.Date;
|
||||
if (_currentFileName != null && _currentFileDate == today) return;
|
||||
_currentFileDate = today;
|
||||
_currentFileName = $"{_fileNamePrefix}-{today:yyyy-MM-dd}.log";
|
||||
}
|
||||
|
||||
public IDisposable? BeginScope<TState>(TState state) => null;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
|
||||
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
TState state,
|
||||
Exception? exception,
|
||||
Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
if (!IsEnabled(logLevel))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
UpdateCurrentFileName();
|
||||
TryCleanOldLogs();
|
||||
|
||||
if (_currentFileName == null) return;
|
||||
|
||||
var fullPath = Path.Combine(_path, _currentFileName);
|
||||
var logEntry = BuildLogEntry(logLevel, eventId, state, exception, formatter);
|
||||
|
||||
File.AppendAllText(fullPath, logEntry + Environment.NewLine + Environment.NewLine);
|
||||
Debug.WriteLine($"[FileLogger] {logEntry}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[FileLogger] Errore durante la scrittura del log: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private string BuildLogEntry<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
TState state,
|
||||
Exception? exception,
|
||||
Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}]");
|
||||
sb.Append($" [{GetLogLevelShort(logLevel)}]");
|
||||
sb.Append($" [{_categoryName}]");
|
||||
|
||||
if (eventId.Id != 0 || !string.IsNullOrEmpty(eventId.Name))
|
||||
sb.Append($" [{eventId}]");
|
||||
|
||||
sb.Append($" {formatter(state, exception)}");
|
||||
|
||||
if (exception != null)
|
||||
AppendException(sb, exception);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static void AppendException(StringBuilder sb, Exception exception, int depth = 0)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var indent = depth == 0 ? "" : " Inner ";
|
||||
sb.AppendLine();
|
||||
sb.Append($"{indent}Exception: {exception.GetType().FullName}: {exception.Message}");
|
||||
if (!string.IsNullOrWhiteSpace(exception.StackTrace))
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.Append($"{indent}StackTrace: {exception.StackTrace.Trim()}");
|
||||
}
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
exception = exception.InnerException;
|
||||
depth += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetLogLevelShort(LogLevel level) => level switch
|
||||
{
|
||||
LogLevel.Trace => "TRC",
|
||||
LogLevel.Debug => "DBG",
|
||||
LogLevel.Information => "INF",
|
||||
LogLevel.Warning => "WRN",
|
||||
LogLevel.Error => "ERR",
|
||||
LogLevel.Critical => "CRT",
|
||||
_ => "???"
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user