enum LogLevel { debug, info, warning, error } class LogEntry { final DateTime timestamp; final LogLevel level; final String message; final String module; final String? funcName; final int? lineNo; final String? errorType; final String? errorMessage; final String? stackTrace; final Map? extra; LogEntry({ required this.timestamp, required this.level, required this.message, required this.module, this.funcName, this.lineNo, this.errorType, this.errorMessage, this.stackTrace, this.extra, }); Map toJson() => { 'timestamp': timestamp.toIso8601String(), 'level': level.name, 'message': message, 'module': module, if (funcName != null) 'func_name': funcName, if (lineNo != null) 'line_no': lineNo, if (errorType != null) 'error_type': errorType, if (errorMessage != null) 'error_message': errorMessage, if (stackTrace != null) 'stack_trace': stackTrace, if (extra != null && extra!.isNotEmpty) 'extra': extra, }; String toConsoleString() { final ts = timestamp.toIso8601String(); final location = [ if (funcName != null) funcName, if (lineNo != null) '@$lineNo', ].join(''); final locationStr = location.isNotEmpty ? ' [$location]' : ''; final errorStr = errorType != null ? ' [$errorType]' : ''; final errorMsgStr = errorMessage != null ? ' $errorMessage' : ''; final extraStr = extra != null && extra!.isNotEmpty ? ' $extra' : ''; return '$ts ${level.name.toUpperCase().padRight(7)} [$module$locationStr]$errorStr $message$errorMsgStr$extraStr'; } String toFileString() { final sb = StringBuffer(); sb.writeln('[$timestamp] ${level.name.toUpperCase()} [$module]'); if (funcName != null || lineNo != null) { sb.write(' at ${funcName ?? ''}'); if (lineNo != null) sb.write(':$lineNo'); sb.writeln(); } sb.writeln(' $message'); if (errorType != null) { sb.writeln(' Error: $errorType'); } if (errorMessage != null) { sb.writeln(' ErrorMessage: $errorMessage'); } if (stackTrace != null) { sb.writeln(' StackTrace:'); sb.writeln(stackTrace); } if (extra != null && extra!.isNotEmpty) { sb.writeln(' Extra: $extra'); } return sb.toString(); } }