1 /**
2  * Модуль консольного логера, основанного на vibe.core.log и termcolor
3  *
4  * Copyright: (c) 2015-2020, Milofon Project.
5  * License: Subject to the terms of the BSD 3-Clause License, as written in the included LICENSE.md file.
6  * Author: <m.galanin@milofon.pro> Maksim Galanin
7  * Date: 2020-04-18
8  */
9 
10 module dango.system.logging.loggers.console;
11 
12 private
13 {
14     import std.typecons: Tuple;
15     import std.stdio: stdout, stderr, File;
16     import std.format : fmt = format;
17 
18     import vibe.core.log : Logger, LogLevel, LogLine;
19     import termcolor : AnsiColor = C, fg, bg, resetColor;
20 
21     import dango.system.logging.core;
22 }
23 
24 
25 /**
26  * Фабрика создающая расширенный консольный логгер
27  */
28 class ConsoleLoggerFactory : LoggerFactory
29 {
30     shared(Logger) createComponent(UniConf config) @trusted
31     {
32         LogLevel level = matchLogLevel(config.getOrElse("level", "info"));
33         bool isSync = config.getOrElse("sync", false);
34         string outStreamName = config.getOrElse("outStream", "stdout");
35         return cast(shared)new ConsoleLogger(level, outStreamName, isSync);
36     }
37 }
38 
39 
40 /**
41  * Расширенный консольный логгер, с возможностью управления цветом
42  */
43 class ConsoleLogger : Logger
44 {
45     private 
46     {
47         immutable bool isSync;
48         File outStream;
49     }
50 
51 
52     this(LogLevel level, string outStreamName, bool isSync) @trusted
53     {
54         this.isSync = isSync;
55         if (outStreamName == "stderr")
56             this.outStream = stderr;
57         else
58             this.outStream = stdout;
59         minLevel = level;
60     }
61 
62     alias ColorTheme = Tuple!(AnsiColor, AnsiColor);
63 
64     enum themes = [
65         LogLevel.trace: ColorTheme(AnsiColor.cyan, AnsiColor.reset),
66         LogLevel.debugV: ColorTheme(AnsiColor.green, AnsiColor.reset),
67         LogLevel.debug_: ColorTheme(AnsiColor.green, AnsiColor.reset),
68         LogLevel.diagnostic: ColorTheme(AnsiColor.green, AnsiColor.reset),
69         LogLevel.info: ColorTheme(AnsiColor.reset, AnsiColor.reset),
70         LogLevel.warn: ColorTheme(AnsiColor.yellow, AnsiColor.reset),
71         LogLevel.error: ColorTheme(AnsiColor.red, AnsiColor.reset),
72         LogLevel.critical: ColorTheme(AnsiColor.white, AnsiColor.red),
73         LogLevel.fatal: ColorTheme(AnsiColor.white, AnsiColor.red),
74         LogLevel.none: ColorTheme(AnsiColor.reset, AnsiColor.reset),
75     ];
76 
77     override void beginLine(ref LogLine msg) @trusted
78     {
79         string pref;
80         final switch (msg.level)
81         {
82             case LogLevel.trace: pref = "trc"; break;
83             case LogLevel.debugV: pref = "dbv"; break;
84             case LogLevel.debug_: pref = "dbg"; break;
85             case LogLevel.diagnostic: pref = "dia"; break;
86             case LogLevel.info: pref = "INF"; break;
87             case LogLevel.warn: pref = "WRN"; break;
88             case LogLevel.error: pref = "ERR"; break;
89             case LogLevel.critical: pref = "CRITICAL"; break;
90             case LogLevel.fatal: pref = "FATAL"; break;
91             case LogLevel.none: assert(false);
92         }
93         ColorTheme theme = themes[msg.level];
94 
95         auto tm = msg.time;
96         static if (is(typeof(tm.fracSecs)))
97             auto msecs = tm.fracSecs.total!"msecs";
98         else auto msecs = tm.fracSec.msecs;
99 
100         outStream.writef("[%08X:%08X %d.%02d.%02d %02d:%02d:%02d.%03d ",
101                 msg.threadID, msg.fiberID,
102                 tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, msecs);
103         outStream.write(theme[0].fg, theme[1].bg, pref, resetColor);
104         outStream.write("] ");
105     }
106 
107     override void put(scope const(char)[] text)
108     {
109         outStream.write(text);
110     }
111 
112     override void endLine() @trusted
113     {
114         outStream.writeln();
115         if (isSync)
116             outStream.flush();
117     }
118 }
119