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