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 }