1 module vibegraylog; 2 3 import std.array : empty; 4 import std.stdio; 5 import vibe.core.log; 6 import vibe.core.net; 7 import vibe.core.core : runTask, sleep; 8 import gelf; 9 10 @safe: 11 12 struct GrayLoggerConfig { 13 string url; 14 ushort port; 15 string thisHost; 16 ulong shortMessageLength; 17 ushort chuckSize = 500; 18 } 19 20 class GrayLogger : Logger { 21 @safe: 22 GrayLoggerConfig config; 23 LogLine ll; 24 string msg; 25 26 this(GrayLoggerConfig config) { 27 this.config = config; 28 } 29 30 override void beginLine(ref LogLine ll) { 31 this.msg = ""; 32 this.ll = ll; 33 } 34 35 override void put(scope const(char)[] text) { 36 this.msg ~= text; 37 } 38 39 override void endLine() { 40 import std.algorithm.comparison : min; 41 42 const sMsgLen = min( this.msg.length , this.config.shortMessageLength); 43 Message theMessage = Message(this.config.thisHost 44 , this.msg.empty 45 ? "no_message" 46 : this.msg[0 .. sMsgLen] 47 , vibeLogLevel(this.ll.level) 48 ); 49 theMessage.originalLogLevel = this.ll.level; 50 theMessage.file = this.ll.file; 51 theMessage.line = this.ll.line; 52 theMessage.func = this.ll.func; 53 theMessage.threadID = this.ll.threadID; 54 theMessage.moduleName = this.ll.mod; 55 theMessage.hostTime = this.ll.time.toISOExtString(); 56 57 theMessage.full_message = this.msg; 58 () @trusted { 59 try { 60 auto udp_sender = listenUDP(0); 61 udp_sender.connect(this.config.url, this.config.port); 62 foreach(c; Chunks(theMessage, this.config.chuckSize)) { 63 udp_sender.send(c); 64 } 65 } catch(Exception e) { 66 try { 67 writeln(e.toString()); 68 } catch(Exception f) { 69 } 70 } 71 }(); 72 } 73 } 74 75 @trusted unittest { 76 auto cfg = GrayLoggerConfig("127.0.0.1", 12201, "localhost"); 77 cfg.shortMessageLength = 30; 78 79 auto jl = cast(shared Logger)new GrayLogger(cfg); 80 registerLogger(jl); 81 logTrace("Trace"); 82 logDebug("Debug"); 83 logInfo("Info"); 84 logError("Error"); 85 logWarn("Warning"); 86 logCritical("Critical"); 87 logFatal("Fatal"); 88 } 89 90 pure Level vibeLogLevel(LogLevel ll) { 91 final switch(ll) { 92 case LogLevel.trace: return Level.DEBUG; 93 case LogLevel.debugV: return Level.DEBUG; 94 case LogLevel.debug_: return Level.DEBUG; 95 case LogLevel.diagnostic: return Level.DEBUG; 96 case LogLevel.info: return Level.INFO; 97 case LogLevel.warn: return Level.WARNING; 98 case LogLevel.error: return Level.ERROR; 99 case LogLevel.critical: return Level.CRITICAL; 100 case LogLevel.fatal: return Level.EMERGENCY; 101 case LogLevel.none: return Level.DEBUG; 102 } 103 }