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 }