1 /** 2 * Core module containing types pertaining to the base Logger 3 * class and base MessageTransform class (along with a default 4 * transform, DefaultTransform) 5 */ 6 module dlog.core; 7 8 import std.conv : to; 9 import dlog.defaults; 10 11 /** 12 * DefaultTransform 13 * 14 * Provides a transformation of the kind 15 * 16 * [date+time] (srcFile:lineNumber): message `\n` 17 */ 18 public final class DefaultTransform : MessageTransform 19 { 20 21 /** 22 * Our transformation 23 */ 24 public override string transform(string text, string[] context) 25 { 26 string message; 27 28 /* Date and time */ 29 import std.datetime.systime : Clock, SysTime; 30 SysTime currTime = Clock.currTime(); 31 import std.conv : to; 32 string timestamp = to!(string)(currTime); 33 message = "["~timestamp~"]"; 34 35 /* Module information */ 36 message = message ~ "\t("; 37 message = message ~ context[1]~":"~context[2]; 38 message = message ~ "): "~text; 39 40 /* Add trailing newline */ 41 message = message ~ '\n'; 42 43 return message; 44 } 45 } 46 47 /** 48 * Logger 49 * 50 * Represents a logger instance 51 */ 52 public class Logger 53 { 54 /* Starting transformation */ 55 private MessageTransform messageTransform; 56 57 /** 58 * Constructs a new Logger with the default 59 * MessageTransform, see TODO (ref module) 60 */ 61 this() 62 { 63 this(new DefaultTransform()); 64 } 65 66 /** 67 * Constructs a new Logger with the given 68 * MessageTransform 69 */ 70 this(MessageTransform messageTransform) 71 { 72 this.messageTransform = messageTransform; 73 } 74 75 /** 76 * Log a message 77 */ 78 public final void log(TextType)(TextType message, string c1 = __FILE_FULL_PATH__, 79 string c2 = __FILE__, ulong c3 = __LINE__, 80 string c4 = __MODULE__, string c5 = __FUNCTION__, 81 string c6 = __PRETTY_FUNCTION__, string[] contextExtras = null) 82 { 83 /* Construct context array */ 84 string[] context = [c1, c2, to!(string)(c3), c4, c5, c6]~contextExtras; 85 86 /* Apply the transformation on the message */ 87 string transformedMesage = messageTransform.execute(to!(string)(message), context); 88 89 /* Call the underlying logger implementation */ 90 logImpl(transformedMesage); 91 } 92 93 /** 94 * Logging implementation, this is where the fina 95 * transformed text will be transferred to and finally 96 * logged 97 */ 98 protected abstract void logImpl(string message); 99 } 100 101 /** 102 * MessageTransform 103 * 104 * A message transform takes in text, applies 105 * a transformation to it and outputs said text 106 * 107 * Transforms may be chained 108 */ 109 public abstract class MessageTransform 110 { 111 /* Next transformation (if any) */ 112 private MessageTransform chainedTransform; 113 114 /** 115 * The actual textual transformation. 116 * 117 * This is to be implemented by sub-classes 118 */ 119 public abstract string transform(string text, string[] context); 120 121 /** 122 * Chain a transform 123 */ 124 public final void chain(MessageTransform transform) 125 { 126 chainedTransform = transform; 127 } 128 129 /** 130 * Perform the transformation 131 */ 132 public final string execute(string text, string[] context) 133 { 134 /* Perform the transformation */ 135 string transformedText = transform(text, context); 136 137 /* If there is a chained transformation */ 138 if(chainedTransform) 139 { 140 transformedText = chainedTransform.execute(transformedText, context); 141 } 142 143 return transformedText; 144 } 145 } 146 147 /** 148 * Tests the DefaultLogger 149 */ 150 unittest 151 { 152 Logger logger = new DefaultLogger(); 153 154 logger.log("This is a log message"); 155 logger.log(1); 156 logger.log(1.1); 157 logger.log(true); 158 logger.log([1,2,3]); 159 logger.log('f'); 160 logger.log(logger); 161 }