using Sonex.Data.Database; using Sonex.Data.Records; namespace Sonex.Library.WorkersCore; public static partial class Worker { public static void LogInfo(string message, string operation = "Info") { ExecuteLogWrite(CreateLogRecord( level: "Info", operation: operation, message: message)); } public static void LogError(string message, string operation = "Error") { ExecuteLogWrite(CreateLogRecord( level: "Error", operation: operation, message: message)); } public static void LogError( string message, Exception exception, string operation = "Error") { ArgumentNullException.ThrowIfNull(exception); ExecuteLogWrite(CreateLogRecord( level: "Error", operation: operation, message: message, exceptionType: exception.GetType().FullName, exceptionText: exception.ToString())); } public static void LogException( Exception exception, string operation = "Exception", bool isUnhandled = false) { ArgumentNullException.ThrowIfNull(exception); ExecuteLogWrite(CreateLogRecord( level: "Error", operation: operation, message: exception.Message, isUnhandled: isUnhandled, exceptionType: exception.GetType().FullName, exceptionText: exception.ToString())); } private static AppLoggerRecord CreateLogRecord( string level, string operation, string message, bool isUnhandled = false, string? exceptionType = null, string? exceptionText = null) { return new AppLoggerRecord { ErrorId = CreateErrorId(), OccurredAt = DateTime.UtcNow, Level = level, ApplicationName = Name, AppVersion = ResolveAppVersion(), InstanceId = Environment.ProcessId.ToString(), UserName = GetDatabaseUserName(), MachineName = Environment.MachineName, OsVersion = Environment.OSVersion.VersionString, Source = Name, Operation = operation, IsUnhandled = isUnhandled, Message = message, ExceptionType = exceptionType, Exception = exceptionText, Context = ProgressInfo }; } private static string CreateErrorId() { return Guid.NewGuid().ToString("N")[..12].ToUpperInvariant(); } private static void ExecuteLogWrite(AppLoggerRecord logRecord) { string operation = string.IsNullOrWhiteSpace(logRecord.Operation) ? "Unknown" : logRecord.Operation.Trim(); try { PrintLogConsoleRecord(logRecord); var result = ExecuteDatabaseSingleWithRetry( _ => AppLoggerRecord.Create(logRecord), operation); if (!result.Success || result.Item != true) { PrintLogConsoleError( $"Log write failed. Operation={operation}. Error={result.ErrorMessage}"); PrintLogConsoleError(FormatLogDbErrorDetails(result)); } } catch (Exception ex) { PrintLogConsoleError( $"Log write exception. Operation={operation}. Error={ex.Message}"); PrintLogConsoleError(ex.ToString()); } } private static void PrintLogConsoleRecord(AppLoggerRecord logRecord) { string level = string.IsNullOrWhiteSpace(logRecord.Level) ? "Info" : logRecord.Level.Trim(); string operation = string.IsNullOrWhiteSpace(logRecord.Operation) ? "Unknown" : logRecord.Operation.Trim(); string message = string.IsNullOrWhiteSpace(logRecord.Message) ? string.Empty : logRecord.Message.Trim(); bool isError = string.Equals(level, "Error", StringComparison.OrdinalIgnoreCase); WriteLogConsoleLine( $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [WorkerCore] [DB-LOG] [{level}] [{operation}] {message}", isError); if (!string.IsNullOrWhiteSpace(logRecord.ExceptionType)) { WriteLogConsoleLine( $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [WorkerCore] [DB-LOG] ExceptionType={logRecord.ExceptionType}", true); } if (!string.IsNullOrWhiteSpace(logRecord.Exception)) { WriteLogConsoleLine(logRecord.Exception, true); } } private static void PrintLogConsoleError(string message) { WriteLogConsoleLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [WorkerCore] {message}", true); } private static void WriteLogConsoleLine(string line, bool isError) { if (isError) { Console.Error.WriteLine(line); return; } Console.WriteLine(line); } private static string FormatLogDbErrorDetails(DB.SingleResult result) { return $"DbErrorType={result.ErrorType ?? "(null)"} | " + $"DbErrorStackTrace={result.ErrorStackTrace ?? "(null)"} | " + $"DbErrorData={result.ErrorData ?? "(null)"}"; } }