1 module vibe_json_logger.logger; 2 3 private import vibe.core.log : Logger, LogLine, LogLevel; 4 5 /** 6 JSON based logger for logging to regular files or stdout/stderr 7 */ 8 final class JSONLogger : Logger 9 { 10 import std.stdio : File; 11 import std.format : formattedWrite; 12 13 private 14 { 15 File m_infoFile; 16 File m_diagFile; 17 File m_curFile; 18 } 19 20 this(File info_file, File diag_file) 21 { 22 m_infoFile = info_file; 23 m_diagFile = diag_file; 24 25 multilineLogger = true; 26 } 27 28 this(string filename) 29 { 30 auto f = File(filename, "ab"); 31 this(f, f); 32 } 33 34 this() 35 { 36 import std.stdio : stderr, stdout; 37 38 this(stdout, stderr); 39 } 40 41 override void beginLine(ref LogLine msg) @safe 42 { 43 string pref; 44 final switch (msg.level) 45 { 46 case LogLevel.trace: 47 pref = "TRACE"; 48 m_curFile = m_diagFile; 49 break; 50 case LogLevel.debugV: 51 pref = "DEBUG_VERBOSE"; 52 m_curFile = m_diagFile; 53 break; 54 case LogLevel.debug_: 55 pref = "DEBUG"; 56 m_curFile = m_diagFile; 57 break; 58 case LogLevel.diagnostic: 59 pref = "DIAGNOSTIC"; 60 m_curFile = m_diagFile; 61 break; 62 case LogLevel.info: 63 pref = "INFO"; 64 m_curFile = m_infoFile; 65 break; 66 case LogLevel.warn: 67 pref = "WARN"; 68 m_curFile = m_diagFile; 69 break; 70 case LogLevel.error: 71 pref = "ERROR"; 72 m_curFile = m_diagFile; 73 break; 74 case LogLevel.critical: 75 pref = "CRITICAL"; 76 m_curFile = m_diagFile; 77 break; 78 case LogLevel.fatal: 79 pref = "FATAL"; 80 m_curFile = m_diagFile; 81 break; 82 case LogLevel.none: 83 assert(false); 84 } 85 86 auto dst = m_curFile.lockingTextWriter; 87 88 dst.put('{'); 89 dst.formattedWrite!(`"timestamp":"%s",`)(msg.time.toISOExtString); 90 91 if (msg.threadName.length) 92 dst.formattedWrite!(`"threadName":"%s",`)(msg.threadName); 93 94 dst.formattedWrite!(`"threadID":"%08X",`)(msg.threadID); 95 import vibe.core.task : Task; 96 97 dst.put(`"taskID":"`); 98 Task.getThis().getDebugID(dst); 99 dst.put(`",`); 100 dst.formattedWrite!(`"level":"%s",`)(pref); 101 dst.formattedWrite!(`"file":"%s",`)(msg.file); 102 dst.formattedWrite!(`"line":%d,`)(msg.line); 103 104 dst.put(`"message":"`); 105 } 106 107 override void put(scope const(char)[] text) @safe 108 { 109 import std.array : replace; 110 111 m_curFile.write(text.replace(`"`, `\"`)); 112 } 113 114 override void endLine() @safe 115 { 116 m_curFile.writeln(`"}`); 117 m_curFile.flush(); 118 } 119 }