1 module coloredlogger; 2 3 import std.experimental.logger; 4 import std.stdio : File; 5 import std.concurrency : Tid; 6 import std.datetime : SysTime; 7 8 9 class ColoredLogger : FileLogger 10 { 11 // See this list: https://wiki.archlinux.org/index.php/Color_Bash_Prompt#List_of_colors_for_prompt_and_Bash 12 enum Color : string 13 { 14 Clear = "\033c", // clear console 15 Normal = "\033[0m", // reset color 16 Black = "\033[1;30m", 17 Red = "\033[1;31m", 18 Green = "\033[1;32m", 19 Yellow = "\033[1;33m", 20 Blue = "\033[1;34m", 21 Purple = "\033[1;35m", 22 Cyan = "\033[1;36m", 23 White = "\033[1;37m" 24 } 25 26 27 private: 28 immutable string[LogLevel] _colorMap; 29 30 31 public: 32 this(File file, const LogLevel lv = LogLevel.info) @safe 33 { 34 this(file, null, lv); 35 } 36 37 this(File file, in string[LogLevel] colorMap, const LogLevel lv = LogLevel.info) @safe 38 { 39 super(file, lv); 40 _colorMap = buildColorMap(colorMap); 41 } 42 43 override protected void beginLogMsg(string file, int line, string funcName, 44 string prettyFuncName, string moduleName, LogLevel logLevel, 45 Tid threadId, SysTime timestamp, Logger logger) @safe 46 { 47 48 this.file.lockingTextWriter().put(_colorMap[logLevel]); 49 super.beginLogMsg(file, line, funcName, prettyFuncName, moduleName, logLevel, threadId, timestamp, logger); 50 } 51 52 override protected void finishLogMsg() 53 { 54 auto lt = this.file.lockingTextWriter(); 55 lt.put(cast(string)Color.Normal); 56 lt.put('\n'); 57 this.file.flush(); 58 } 59 60 61 private: 62 immutable(string[LogLevel]) buildColorMap(in string[LogLevel] colorMap) @trusted pure 63 { 64 import std.exception : assumeUnique; 65 import std.traits : EnumMembers; 66 67 string[LogLevel] result; 68 69 foreach (ll; EnumMembers!LogLevel) { 70 if (ll in colorMap) { 71 result[ll] = colorMap[ll]; 72 continue; 73 } 74 75 // Default color mapping 76 final switch (ll) { 77 case LogLevel.all, LogLevel.off: 78 break; 79 case LogLevel.trace: 80 result[ll] = Color.Blue; 81 break; 82 case LogLevel.info: 83 result[ll] = Color.Green; 84 break; 85 case LogLevel.warning: 86 result[ll] = Color.Yellow; 87 break; 88 case LogLevel.error: 89 result[ll] = Color.Purple; 90 break; 91 case LogLevel.critical: 92 result[ll] = Color.Red; 93 break; 94 case LogLevel.fatal: 95 result[ll] = Color.Cyan; 96 break; 97 } 98 } 99 100 return result.assumeUnique; 101 } 102 }