1 /** 2 * Core logging services 3 * 4 * Authors: Tristan Brice Velloza Kildaire (deavmi) 5 */ 6 module dlog.core; 7 8 import std.container.slist : SList; 9 import core.sync.mutex : Mutex; 10 11 /** 12 * The base message type 13 */ 14 public abstract class Message 15 { 16 17 } 18 19 /** 20 * Defines the filtering 21 * interface 22 */ 23 public interface Filter 24 { 25 /** 26 * Filters the given message 27 * returning a verdict 28 * based on it 29 * 30 * Params: 31 * message = the message 32 * Returns: the verdct 33 */ 34 public bool filter(Message message); 35 } 36 37 /** 38 * Defines the message 39 * transformation interface 40 */ 41 public interface Transform 42 { 43 /** 44 * Transforms the given message 45 * 46 * Params: 47 * message = the message input 48 * Returns: the transformed 49 * message 50 */ 51 public Message transform(Message message); 52 } 53 54 /** 55 * Defines the interface 56 * for handling messages 57 */ 58 public interface Handler 59 { 60 /** 61 * Handles the given message 62 * 63 * Params: 64 * message = the message to 65 * handle 66 */ 67 public void handle(Message message); 68 } 69 70 /** 71 * Defines the base logger 72 * and functionality associated 73 * with it 74 */ 75 public abstract class Logger 76 { 77 private SList!(Transform) transforms; 78 private SList!(Filter) filters; 79 private SList!(Handler) handlers; 80 private Mutex lock; // Lock for attached handlers, filters and transforms 81 82 /** 83 * Constructs a new logger 84 */ 85 this() 86 { 87 this.lock = new Mutex(); 88 } 89 90 // TODO: Handle duplicate? 91 /** 92 * Adds the given transform 93 * 94 * Params: 95 * transform = the transform 96 * to add 97 */ 98 public final void addTransform(Transform transform) 99 { 100 scope(exit) 101 { 102 this.lock.unlock(); 103 } 104 105 this.lock.lock(); 106 107 this.transforms.insertAfter(this.transforms[], transform); 108 } 109 110 // TODO: Hanmdle not found explicitly? 111 /** 112 * Removes the given transform 113 * 114 * Params: 115 * transform = the transform 116 * to remove 117 */ 118 public final void removeTransform(Transform transform) 119 { 120 scope(exit) 121 { 122 this.lock.unlock(); 123 } 124 125 this.lock.lock(); 126 127 this.transforms.linearRemoveElement(transform); 128 } 129 130 // TODO: Handle duplicate? 131 132 /** 133 * Adds the given filter 134 * 135 * Params: 136 * filter = the filter 137 * to add 138 */ 139 public final void addFilter(Filter filter) 140 { 141 scope(exit) 142 { 143 this.lock.unlock(); 144 } 145 146 this.lock.lock(); 147 148 this.filters.insertAfter(this.filters[], filter); 149 } 150 151 // TODO: Hanmdle not found explicitly? 152 153 /** 154 * Removes the given filter 155 * 156 * Params: 157 * filter = the filter 158 * to remove 159 */ 160 public final void removeFilter(Filter filter) 161 { 162 scope(exit) 163 { 164 this.lock.unlock(); 165 } 166 167 this.lock.lock(); 168 169 this.filters.linearRemoveElement(filter); 170 } 171 172 // TODO: Handle duplicate? 173 174 /** 175 * Adds the given handler 176 * 177 * Params: 178 * handler = the handler 179 * to add 180 */ 181 public final void addHandler(Handler handler) 182 { 183 scope(exit) 184 { 185 this.lock.unlock(); 186 } 187 188 this.lock.lock(); 189 190 this.handlers.insertAfter(this.handlers[], handler); 191 } 192 193 // TODO: Hanmdle not found explicitly? 194 195 /** 196 * Removes the given handler 197 * 198 * Params: 199 * handler = the handler 200 * to remove 201 */ 202 public final void removeHandler(Handler handler) 203 { 204 scope(exit) 205 { 206 this.lock.unlock(); 207 } 208 209 this.lock.lock(); 210 211 this.handlers.linearRemoveElement(handler); 212 } 213 214 /** 215 * Logs the provided message by processing 216 * it through all the filters, and if 217 * the verdict is `true` then transforms 218 * the message via all transformers 219 * and finally dispatches said message 220 * to all attached handlers 221 * 222 * Params: 223 * message = the message 224 */ 225 public final void log(Message message) 226 { 227 scope(exit) 228 { 229 this.lock.unlock(); 230 } 231 232 this.lock.lock(); 233 234 foreach(Filter filter; this.filters) 235 { 236 if(!filter.filter(message)) 237 { 238 return; 239 } 240 } 241 242 Message curMessage = message; 243 foreach(Transform transform; this.transforms) 244 { 245 curMessage = transform.transform(curMessage); 246 } 247 248 foreach(Handler handler; this.handlers) 249 { 250 handler.handle(curMessage); 251 } 252 } 253 }