1 module minlog.logger; 2 3 import std.stdio; 4 import std.format; 5 import std.conv; 6 import std.datetime; 7 import colorize; 8 9 /// how verbose the messages are 10 enum Verbosity { 11 trace = 4, 12 info = 3, 13 warn = 2, 14 error = 1, 15 crit = 0 16 } 17 18 /// a utility class for displaying diagnostic messages 19 class Logger { 20 /// maximum message verbosity 21 public Verbosity verbosity; 22 /// message output targets 23 public ILogSink[] sinks; 24 25 /** 26 initialize a logger with a given verbosity 27 */ 28 this(Verbosity verbosity) { 29 this.verbosity = verbosity; 30 } 31 32 /// writes a message 33 public void write_line(string log, Verbosity level) { 34 if (level <= verbosity) { 35 foreach (sink; sinks) { 36 sink.write_line(log, level); 37 } 38 } 39 } 40 41 /// writes a message at trace verbosity 42 public void trace(string log) { 43 write_line(log, Verbosity.trace); 44 } 45 46 /// writes a message at INFO verbosity 47 public void info(string log) { 48 write_line(log, Verbosity.info); 49 } 50 51 /// writes a message at warn verbosity 52 public void warn(string log) { 53 write_line(log, Verbosity.warn); 54 } 55 56 /// writes a message at error verbosity 57 public void err(string log) { 58 write_line(log, Verbosity.error); 59 } 60 61 /// writes a message at crit verbosity 62 public void crit(string log) { 63 write_line(log, Verbosity.crit); 64 } 65 66 private static string shortVerbosity(Verbosity level) { 67 switch (level) { 68 case Verbosity.trace: 69 return "trce"; 70 case Verbosity.info: 71 return "info"; 72 case Verbosity.warn: 73 return "warn"; 74 case Verbosity.error: 75 return "err!"; 76 case Verbosity.crit: 77 return "crit"; 78 default: 79 return to!string(level); 80 } 81 } 82 83 private static string formatMeta(Verbosity level) { 84 auto time = cast(TimeOfDay) Clock.currTime(); 85 return format("[%s/%s]", shortVerbosity(level), time.toISOExtString()); 86 } 87 88 /// a sink that accepts log messages 89 public interface ILogSink { 90 /// writes a message to the sink 91 void write_line(string log, Verbosity level); 92 } 93 94 /// a sink that outputs to the console 95 public static class ConsoleSink : ILogSink { 96 public void write_line(string log, Verbosity level) { 97 auto col = colorFor(level); 98 colorize.cwritef(formatMeta(level).color(col, colorize.bg.black)); 99 colorize.cwritefln(" %s", log); 100 } 101 102 private colorize.fg colorFor(Verbosity level) { 103 switch (level) { 104 case Verbosity.trace: 105 return colorize.fg.light_black; 106 case Verbosity.info: 107 return colorize.fg.green; 108 case Verbosity.warn: 109 return colorize.fg.yellow; 110 case Verbosity.error: 111 return colorize.fg.light_red; 112 case Verbosity.crit: 113 return colorize.fg.red; 114 default: 115 return colorize.fg.white; 116 } 117 } 118 } 119 120 /// a sink that outputs to a file 121 public static class FileSink : ILogSink { 122 public string path; 123 private File of; 124 125 this(string path) { 126 this.path = path; 127 this.of = File(path, "a"); 128 } 129 130 public void write_line(string log, Verbosity level) { 131 of.write(formatMeta(level)); 132 of.writeln(" {log}"); 133 of.flush(); 134 } 135 } 136 } 137 138 unittest { 139 auto log = new Logger(Verbosity.info); 140 log.sinks ~= new Logger.ConsoleSink(); 141 log.verbosity = Verbosity.trace; 142 143 log.info("hello world"); 144 }