You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
6.3 KiB
146 lines
6.3 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace marking_gui.Services
|
|
{
|
|
public static class LoggerService
|
|
{
|
|
private static readonly string LogDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
|
|
private static readonly string DiagnosticDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "debug");
|
|
private static readonly object LockObj = new object();
|
|
private static readonly Queue<string> RecentLogs = new Queue<string>();
|
|
private const int RecentLogLimit = 100;
|
|
|
|
static LoggerService()
|
|
{
|
|
try
|
|
{
|
|
if (!Directory.Exists(LogDirectory))
|
|
{
|
|
Directory.CreateDirectory(LogDirectory);
|
|
}
|
|
|
|
// 오래된 로그 정리 태스크 백그라운드 구동 (애플리케이션 시작 차단 방지)
|
|
System.Threading.Tasks.Task.Run(() => CleanUpOldLogs(30));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("Log directory creation failed: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private static void CleanUpOldLogs(int retentionDays)
|
|
{
|
|
try
|
|
{
|
|
var dirInfo = new DirectoryInfo(LogDirectory);
|
|
if (!dirInfo.Exists) return;
|
|
|
|
DateTime threshold = DateTime.Now.AddDays(-retentionDays);
|
|
foreach (var file in dirInfo.GetFiles("*.log"))
|
|
{
|
|
try
|
|
{
|
|
if (file.LastWriteTime < threshold)
|
|
{
|
|
file.Delete();
|
|
System.Diagnostics.Debug.WriteLine($"[SRE Logger] 만료된 로그 파일 삭제 완료: {file.Name}");
|
|
}
|
|
}
|
|
catch (Exception fileEx)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[SRE Logger] 로그 파일 삭제 중 예외 (파일명: {file.Name}): {fileEx.Message}");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("[SRE Logger] 만료 로그 정리 중 예외 발생: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
public static void Info(string message)
|
|
{
|
|
WriteLog("INFO", message);
|
|
}
|
|
|
|
public static void Warn(string message)
|
|
{
|
|
WriteLog("WARN", message);
|
|
}
|
|
|
|
public static void Error(string message, Exception ex = null, string context = null)
|
|
{
|
|
string detail = message;
|
|
if (ex != null)
|
|
{
|
|
// ToString preserves exception types, inner exceptions and their stack traces.
|
|
detail += Environment.NewLine + ex;
|
|
}
|
|
WriteLog("ERROR", detail, context);
|
|
}
|
|
|
|
private static void WriteLog(string level, string message, string context = null)
|
|
{
|
|
lock (LockObj)
|
|
{
|
|
DateTime now = DateTime.Now;
|
|
string logLine = string.Format("[{0}] [{1}] {2}", now.ToString("yyyy-MM-dd HH:mm:ss.fff zzz"), level, message) + Environment.NewLine;
|
|
RecentLogs.Enqueue(logLine);
|
|
while (RecentLogs.Count > RecentLogLimit) RecentLogs.Dequeue();
|
|
|
|
// Keep diagnostic and daily writes independent so either can survive a failure in the other.
|
|
if (level == "ERROR")
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(DiagnosticDirectory);
|
|
string diagnosticFile = Path.Combine(DiagnosticDirectory,
|
|
$"error_{now:yyyyMMdd_HHmmss_fff}_{Guid.NewGuid():N}.log");
|
|
var report = new StringBuilder();
|
|
report.AppendLine($"발생 시각: {now:yyyy-MM-dd HH:mm:ss.fff zzz}");
|
|
report.AppendLine($"프로그램 버전: {typeof(LoggerService).Assembly.GetName().Version}");
|
|
report.AppendLine($"실행 경로: {AppDomain.CurrentDomain.BaseDirectory}");
|
|
report.AppendLine($"실행 환경: {RuntimeInformation.FrameworkDescription}, {RuntimeInformation.OSDescription}, {RuntimeInformation.ProcessArchitecture}");
|
|
report.AppendLine($"프로세스 ID: {Environment.ProcessId}, 스레드 ID: {Environment.CurrentManagedThreadId}");
|
|
report.AppendLine();
|
|
report.AppendLine("[오류 상세]");
|
|
report.AppendLine(message);
|
|
if (!string.IsNullOrWhiteSpace(context))
|
|
{
|
|
report.AppendLine();
|
|
report.AppendLine("[진단 정보]");
|
|
report.AppendLine(context);
|
|
}
|
|
report.AppendLine();
|
|
report.AppendLine($"[직전 로그 - 최대 {RecentLogLimit}건]");
|
|
foreach (string recent in RecentLogs) report.Append(recent);
|
|
File.WriteAllText(diagnosticFile, report.ToString(), Encoding.UTF8);
|
|
logLine += "[진단 파일] " + diagnosticFile + Environment.NewLine;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logLine += "[진단 파일 저장 실패] " + ex.Message + Environment.NewLine;
|
|
System.Diagnostics.Debug.WriteLine("Writing diagnostic failed: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
Directory.CreateDirectory(LogDirectory);
|
|
string logFile = Path.Combine(LogDirectory, now.ToString("yyyy-MM-dd") + ".log");
|
|
if (!string.IsNullOrWhiteSpace(context))
|
|
logLine += "[진단 정보] " + context + Environment.NewLine;
|
|
File.AppendAllText(logFile, logLine);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("Writing log failed: " + ex.Message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|