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