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: writeln, write, writef, stdout; 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 return cast(shared)new ConsoleLogger(level, isSync); 35 } 36 } 37 38 39 /** 40 * Расширенный консольный логгер, с возможностью управления цветом 41 */ 42 class ConsoleLogger : Logger 43 { 44 private immutable bool isSync; 45 46 47 this(LogLevel level, bool isSync) 48 { 49 this.isSync = isSync; 50 minLevel = level; 51 } 52 53 alias ColorTheme = Tuple!(AnsiColor, AnsiColor); 54 55 enum themes = [ 56 LogLevel.trace: ColorTheme(AnsiColor.cyan, AnsiColor.reset), 57 LogLevel.debugV: ColorTheme(AnsiColor.green, AnsiColor.reset), 58 LogLevel.debug_: ColorTheme(AnsiColor.green, AnsiColor.reset), 59 LogLevel.diagnostic: ColorTheme(AnsiColor.green, AnsiColor.reset), 60 LogLevel.info: ColorTheme(AnsiColor.reset, AnsiColor.reset), 61 LogLevel.warn: ColorTheme(AnsiColor.yellow, AnsiColor.reset), 62 LogLevel.error: ColorTheme(AnsiColor.red, AnsiColor.reset), 63 LogLevel.critical: ColorTheme(AnsiColor.white, AnsiColor.red), 64 LogLevel.fatal: ColorTheme(AnsiColor.white, AnsiColor.red), 65 LogLevel.none: ColorTheme(AnsiColor.reset, AnsiColor.reset), 66 ]; 67 68 override void beginLine(ref LogLine msg) @trusted 69 { 70 string pref; 71 final switch (msg.level) 72 { 73 case LogLevel.trace: pref = "trc"; break; 74 case LogLevel.debugV: pref = "dbv"; break; 75 case LogLevel.debug_: pref = "dbg"; break; 76 case LogLevel.diagnostic: pref = "dia"; break; 77 case LogLevel.info: pref = "INF"; break; 78 case LogLevel.warn: pref = "WRN"; break; 79 case LogLevel.error: pref = "ERR"; break; 80 case LogLevel.critical: pref = "CRITICAL"; break; 81 case LogLevel.fatal: pref = "FATAL"; break; 82 case LogLevel.none: assert(false); 83 } 84 ColorTheme theme = themes[msg.level]; 85 86 auto tm = msg.time; 87 static if (is(typeof(tm.fracSecs))) 88 auto msecs = tm.fracSecs.total!"msecs"; 89 else auto msecs = tm.fracSec.msecs; 90 91 writef("[%08X:%08X %d.%02d.%02d %02d:%02d:%02d.%03d ", 92 msg.threadID, msg.fiberID, 93 tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, msecs); 94 write(theme[0].fg, theme[1].bg, pref, resetColor); 95 write("] "); 96 } 97 98 override void put(scope const(char)[] text) 99 { 100 write(text); 101 } 102 103 override void endLine() @trusted 104 { 105 writeln(); 106 if (isSync) 107 stdout.flush(); 108 } 109 } 110