1 /** 2 * This module defines a set of logging functions that can be used in any 3 * application. There is a set of basic `log` functions that accept any logging 4 * level, as well as pre-defined functions for the standard SLF4D logging 5 * levels. 6 * 7 * ### Basic Log Functions 8 * --- 9 * log(Levels.WARN, "Warning message"); 10 * log(Levels.ERROR, new Exception("Oh no!")); 11 * logF!"Info message: %d"(Levels.INFO, 42); 12 * --- 13 */ 14 module slf4d.log_functions; 15 16 import slf4d.level; 17 import slf4d : getLogger; 18 19 /** 20 * Writes a log message. 21 * Params: 22 * level = The logging level. 23 * msg = The message. 24 * exception = An optional exception to log. 25 * attributes = Key-value pairs of additional user-defined attributes. 26 * moduleName = The name of the module where this log message was written. 27 * functionName = The name of the function where this log message was written. 28 * fileName = The name of the source file where this log message was written. 29 * lineNumber = The line number where this log message was written. 30 */ 31 public void log( 32 Level level, 33 string msg, 34 Exception exception = null, 35 string[string] attributes = string[string].init, 36 string moduleName = __MODULE__, 37 string functionName = __PRETTY_FUNCTION__, 38 string fileName = __FILE__, 39 size_t lineNumber = __LINE__ 40 ) { 41 getLogger(moduleName).log(level, msg, exception, attributes, moduleName, functionName, fileName, lineNumber); 42 } 43 44 /** 45 * Writes an exception log message. 46 * Params: 47 * level = The logging level. 48 * exception = The exception to log. 49 * attributes = Key-value pairs of additional user-defined attributes. 50 * moduleName = The name of the module where this log message was written. 51 * functionName = The name of the function where this log message was written. 52 * fileName = The name of the source file where this log message was written. 53 * lineNumber = The line number where this log message was written. 54 */ 55 public void log( 56 Level level, 57 Exception exception, 58 string[string] attributes = string[string].init, 59 string moduleName = __MODULE__, 60 string functionName = __PRETTY_FUNCTION__, 61 string fileName = __FILE__, 62 size_t lineNumber = __LINE__ 63 ) { 64 getLogger(moduleName).log(level, exception, attributes, moduleName, functionName, fileName, lineNumber); 65 } 66 67 /** 68 * Writes a formatted log message. 69 * Params: 70 * level = The logging level. 71 * args = The arguments to provide to the format string. 72 * exception = An optional exception to log. 73 * attributes = Key-value pairs of additional user-defined attributes. 74 * moduleName = The name of the module where this log message was written. 75 * functionName = The name of the function where this log message was written. 76 * fileName = The name of the source file where this log message was written. 77 * lineNumber = The line number where this log message was written. 78 */ 79 public void logF(string fmt, T...)( 80 Level level, 81 T args, 82 Exception exception = null, 83 string[string] attributes = string[string].init, 84 string moduleName = __MODULE__, 85 string functionName = __PRETTY_FUNCTION__, 86 string fileName = __FILE__, 87 size_t lineNumber = __LINE__ 88 ) { 89 auto logger = getLogger(moduleName); 90 if (logger.level.value <= level.value) { 91 import std.format : format; 92 logger.log(level, format!(fmt)(args), exception, attributes, moduleName, functionName, fileName, lineNumber); 93 } 94 } 95 96 /** 97 * Writes a trace log message. 98 * Params: 99 * msg = The message. 100 * exception = An optional exception to log. 101 * attributes = Key-value pairs of additional user-defined attributes. 102 * moduleName = The name of the module where this log message was written. 103 * functionName = The name of the function where this log message was written. 104 * fileName = The name of the source file where this log message was written. 105 * lineNumber = The line number where this log message was written. 106 */ 107 public void trace( 108 string msg, 109 Exception exception = null, 110 string[string] attributes = string[string].init, 111 string moduleName = __MODULE__, 112 string functionName = __PRETTY_FUNCTION__, 113 string fileName = __FILE__, 114 size_t lineNumber = __LINE__ 115 ) { 116 log(Levels.TRACE, msg, exception, attributes, moduleName, functionName, fileName, lineNumber); 117 } 118 119 /** 120 * Writes an exception trace log message. 121 * Params: 122 * level = The logging level. 123 * exception = The exception to log. 124 * attributes = Key-value pairs of additional user-defined attributes. 125 * moduleName = The name of the module where this log message was written. 126 * functionName = The name of the function where this log message was written. 127 * fileName = The name of the source file where this log message was written. 128 * lineNumber = The line number where this log message was written. 129 */ 130 public void trace( 131 Exception exception, 132 string[string] attributes = string[string].init, 133 string moduleName = __MODULE__, 134 string functionName = __PRETTY_FUNCTION__, 135 string fileName = __FILE__, 136 size_t lineNumber = __LINE__ 137 ) { 138 log(Levels.TRACE, exception, attributes, moduleName, functionName, fileName, lineNumber); 139 } 140 141 /** 142 * Writes a formatted trace log message. 143 * Params: 144 * level = The logging level. 145 * args = The arguments to provide to the format string. 146 * exception = An optional exception to log. 147 * attributes = Key-value pairs of additional user-defined attributes. 148 * moduleName = The name of the module where this log message was written. 149 * functionName = The name of the function where this log message was written. 150 * fileName = The name of the source file where this log message was written. 151 * lineNumber = The line number where this log message was written. 152 */ 153 public void traceF(string fmt, T...)( 154 T args, 155 Exception exception = null, 156 string[string] attributes = string[string].init, 157 string moduleName = __MODULE__, 158 string functionName = __PRETTY_FUNCTION__, 159 string fileName = __FILE__, 160 size_t lineNumber = __LINE__ 161 ) { 162 auto logger = getLogger(moduleName); 163 if (logger.level.value <= Levels.TRACE.value) { 164 import std.format : format; 165 logger.log(Levels.TRACE, format!(fmt)(args), exception, attributes, moduleName, functionName, fileName, lineNumber); 166 } 167 } 168 169 /** 170 * Writes a debug log message. 171 * Params: 172 * msg = The message. 173 * exception = An optional exception to log. 174 * attributes = Key-value pairs of additional user-defined attributes. 175 * moduleName = The name of the module where this log message was written. 176 * functionName = The name of the function where this log message was written. 177 * fileName = The name of the source file where this log message was written. 178 * lineNumber = The line number where this log message was written. 179 */ 180 public void debug_( 181 string msg, 182 Exception exception = null, 183 string[string] attributes = string[string].init, 184 string moduleName = __MODULE__, 185 string functionName = __PRETTY_FUNCTION__, 186 string fileName = __FILE__, 187 size_t lineNumber = __LINE__ 188 ) { 189 log(Levels.DEBUG, msg, exception, attributes, moduleName, functionName, fileName, lineNumber); 190 } 191 192 /** 193 * Writes an exception debug log message. 194 * Params: 195 * level = The logging level. 196 * exception = The exception to log. 197 * attributes = Key-value pairs of additional user-defined attributes. 198 * moduleName = The name of the module where this log message was written. 199 * functionName = The name of the function where this log message was written. 200 * fileName = The name of the source file where this log message was written. 201 * lineNumber = The line number where this log message was written. 202 */ 203 public void debug_( 204 Exception exception, 205 string[string] attributes = string[string].init, 206 string moduleName = __MODULE__, 207 string functionName = __PRETTY_FUNCTION__, 208 string fileName = __FILE__, 209 size_t lineNumber = __LINE__ 210 ) { 211 log(Levels.DEBUG, exception, attributes, moduleName, functionName, fileName, lineNumber); 212 } 213 214 /** 215 * Writes a formatted debug log message. 216 * Params: 217 * level = The logging level. 218 * args = The arguments to provide to the format string. 219 * exception = An optional exception to log. 220 * attributes = Key-value pairs of additional user-defined attributes. 221 * moduleName = The name of the module where this log message was written. 222 * functionName = The name of the function where this log message was written. 223 * fileName = The name of the source file where this log message was written. 224 * lineNumber = The line number where this log message was written. 225 */ 226 public void debugF(string fmt, T...)( 227 T args, 228 Exception exception = null, 229 string[string] attributes = string[string].init, 230 string moduleName = __MODULE__, 231 string functionName = __PRETTY_FUNCTION__, 232 string fileName = __FILE__, 233 size_t lineNumber = __LINE__ 234 ) { 235 auto logger = getLogger(moduleName); 236 if (logger.level.value <= Levels.DEBUG.value) { 237 import std.format : format; 238 logger.log(Levels.DEBUG, format!(fmt)(args), exception, attributes, moduleName, functionName, fileName, lineNumber); 239 } 240 } 241 242 /** 243 * Writes an info log message. 244 * Params: 245 * msg = The message. 246 * exception = An optional exception to log. 247 * attributes = Key-value pairs of additional user-defined attributes. 248 * moduleName = The name of the module where this log message was written. 249 * functionName = The name of the function where this log message was written. 250 * fileName = The name of the source file where this log message was written. 251 * lineNumber = The line number where this log message was written. 252 */ 253 public void info( 254 string msg, 255 Exception exception = null, 256 string[string] attributes = string[string].init, 257 string moduleName = __MODULE__, 258 string functionName = __PRETTY_FUNCTION__, 259 string fileName = __FILE__, 260 size_t lineNumber = __LINE__ 261 ) { 262 log(Levels.INFO, msg, exception, attributes, moduleName, functionName, fileName, lineNumber); 263 } 264 265 /** 266 * Writes an exception info log message. 267 * Params: 268 * level = The logging level. 269 * exception = The exception to log. 270 * attributes = Key-value pairs of additional user-defined attributes. 271 * moduleName = The name of the module where this log message was written. 272 * functionName = The name of the function where this log message was written. 273 * fileName = The name of the source file where this log message was written. 274 * lineNumber = The line number where this log message was written. 275 */ 276 public void info( 277 Exception exception, 278 string[string] attributes = string[string].init, 279 string moduleName = __MODULE__, 280 string functionName = __PRETTY_FUNCTION__, 281 string fileName = __FILE__, 282 size_t lineNumber = __LINE__ 283 ) { 284 log(Levels.INFO, exception, attributes, moduleName, functionName, fileName, lineNumber); 285 } 286 287 /** 288 * Writes a formatted info log message. 289 * Params: 290 * level = The logging level. 291 * args = The arguments to provide to the format string. 292 * exception = An optional exception to log. 293 * attributes = Key-value pairs of additional user-defined attributes. 294 * moduleName = The name of the module where this log message was written. 295 * functionName = The name of the function where this log message was written. 296 * fileName = The name of the source file where this log message was written. 297 * lineNumber = The line number where this log message was written. 298 */ 299 public void infoF(string fmt, T...)( 300 T args, 301 Exception exception = null, 302 string[string] attributes = string[string].init, 303 string moduleName = __MODULE__, 304 string functionName = __PRETTY_FUNCTION__, 305 string fileName = __FILE__, 306 size_t lineNumber = __LINE__ 307 ) { 308 auto logger = getLogger(moduleName); 309 if (logger.level.value <= Levels.INFO.value) { 310 import std.format : format; 311 logger.log(Levels.INFO, format!(fmt)(args), exception, attributes, moduleName, functionName, fileName, lineNumber); 312 } 313 } 314 315 /** 316 * Writes a warn log message. 317 * Params: 318 * msg = The message. 319 * exception = An optional exception to log. 320 * attributes = Key-value pairs of additional user-defined attributes. 321 * moduleName = The name of the module where this log message was written. 322 * functionName = The name of the function where this log message was written. 323 * fileName = The name of the source file where this log message was written. 324 * lineNumber = The line number where this log message was written. 325 */ 326 public void warn( 327 string msg, 328 Exception exception = null, 329 string[string] attributes = string[string].init, 330 string moduleName = __MODULE__, 331 string functionName = __PRETTY_FUNCTION__, 332 string fileName = __FILE__, 333 size_t lineNumber = __LINE__ 334 ) { 335 log(Levels.WARN, msg, exception, attributes, moduleName, functionName, fileName, lineNumber); 336 } 337 338 /** 339 * Writes an exception warn log message. 340 * Params: 341 * level = The logging level. 342 * exception = The exception to log. 343 * attributes = Key-value pairs of additional user-defined attributes. 344 * moduleName = The name of the module where this log message was written. 345 * functionName = The name of the function where this log message was written. 346 * fileName = The name of the source file where this log message was written. 347 * lineNumber = The line number where this log message was written. 348 */ 349 public void warn( 350 Exception exception, 351 string[string] attributes = string[string].init, 352 string moduleName = __MODULE__, 353 string functionName = __PRETTY_FUNCTION__, 354 string fileName = __FILE__, 355 size_t lineNumber = __LINE__ 356 ) { 357 log(Levels.WARN, exception, attributes, moduleName, functionName, fileName, lineNumber); 358 } 359 360 /** 361 * Writes a formatted warn log message. 362 * Params: 363 * level = The logging level. 364 * args = The arguments to provide to the format string. 365 * exception = An optional exception to log. 366 * attributes = Key-value pairs of additional user-defined attributes. 367 * moduleName = The name of the module where this log message was written. 368 * functionName = The name of the function where this log message was written. 369 * fileName = The name of the source file where this log message was written. 370 * lineNumber = The line number where this log message was written. 371 */ 372 public void warnF(string fmt, T...)( 373 T args, 374 Exception exception = null, 375 string[string] attributes = string[string].init, 376 string moduleName = __MODULE__, 377 string functionName = __PRETTY_FUNCTION__, 378 string fileName = __FILE__, 379 size_t lineNumber = __LINE__ 380 ) { 381 auto logger = getLogger(moduleName); 382 if (logger.level.value <= Levels.WARN.value) { 383 import std.format : format; 384 logger.log(Levels.WARN, format!(fmt)(args), exception, attributes, moduleName, functionName, fileName, lineNumber); 385 } 386 } 387 388 /** 389 * Writes an error log message. 390 * Params: 391 * msg = The message. 392 * exception = An optional exception to log. 393 * attributes = Key-value pairs of additional user-defined attributes. 394 * moduleName = The name of the module where this log message was written. 395 * functionName = The name of the function where this log message was written. 396 * fileName = The name of the source file where this log message was written. 397 * lineNumber = The line number where this log message was written. 398 */ 399 public void error( 400 string msg, 401 Exception exception = null, 402 string[string] attributes = string[string].init, 403 string moduleName = __MODULE__, 404 string functionName = __PRETTY_FUNCTION__, 405 string fileName = __FILE__, 406 size_t lineNumber = __LINE__ 407 ) { 408 log(Levels.ERROR, msg, exception, attributes, moduleName, functionName, fileName, lineNumber); 409 } 410 411 /** 412 * Writes an exception error log message. 413 * Params: 414 * level = The logging level. 415 * exception = The exception to log. 416 * attributes = Key-value pairs of additional user-defined attributes. 417 * moduleName = The name of the module where this log message was written. 418 * functionName = The name of the function where this log message was written. 419 * fileName = The name of the source file where this log message was written. 420 * lineNumber = The line number where this log message was written. 421 */ 422 public void error( 423 Exception exception, 424 string[string] attributes = string[string].init, 425 string moduleName = __MODULE__, 426 string functionName = __PRETTY_FUNCTION__, 427 string fileName = __FILE__, 428 size_t lineNumber = __LINE__ 429 ) { 430 log(Levels.ERROR, exception, attributes, moduleName, functionName, fileName, lineNumber); 431 } 432 433 /** 434 * Writes a formatted error log message. 435 * Params: 436 * level = The logging level. 437 * args = The arguments to provide to the format string. 438 * exception = An optional exception to log. 439 * attributes = Key-value pairs of additional user-defined attributes. 440 * moduleName = The name of the module where this log message was written. 441 * functionName = The name of the function where this log message was written. 442 * fileName = The name of the source file where this log message was written. 443 * lineNumber = The line number where this log message was written. 444 */ 445 public void errorF(string fmt, T...)( 446 T args, 447 Exception exception = null, 448 string[string] attributes = string[string].init, 449 string moduleName = __MODULE__, 450 string functionName = __PRETTY_FUNCTION__, 451 string fileName = __FILE__, 452 size_t lineNumber = __LINE__ 453 ) { 454 auto logger = getLogger(moduleName); 455 if (logger.level.value <= Levels.ERROR.value) { 456 import std.format : format; 457 logger.log(Levels.ERROR, format!(fmt)(args), exception, attributes, moduleName, functionName, fileName, lineNumber); 458 } 459 } 460 461 import slf4d.logger : LogBuilder; 462 463 public LogBuilder logBuilder(string moduleName = __MODULE__){ 464 return getLogger(moduleName).builder(); 465 } 466 467 unittest { 468 import slf4d.test; 469 synchronized (loggingTestingMutex) { 470 TestingLoggingProvider provider = getTestingProvider(); 471 472 // Test formatted functions without any format specifiers. 473 logF!"Testing"(Levels.INFO); 474 provider.assertHasMessage("Testing"); 475 traceF!"Testing trace"(); 476 provider.assertHasMessage("Testing trace"); 477 debugF!"Testing debug"(); 478 provider.assertHasMessage("Testing debug"); 479 infoF!"Testing info"(); 480 provider.assertHasMessage("Testing info"); 481 warnF!"Testing warn"(); 482 provider.assertHasMessage("Testing warn"); 483 errorF!"Testing error"(); 484 provider.assertHasMessage("Testing error"); 485 provider.reset(); 486 487 // Test formatted functions with argument and an exception. 488 Exception exc = new Exception("Uh oh"); 489 490 // Test calling the builder function. 491 logBuilder() 492 .lvl(Levels.DEBUG) 493 .msg("Testing builder") 494 .attr("test", "yes") 495 .log(); 496 provider.assertHasMessage("Testing builder"); 497 LogMessage msg = provider.messages[0]; 498 assert(msg.level == Levels.DEBUG); 499 assert(msg.attributes["test"] == "yes"); 500 501 resetLoggingState(); 502 } 503 }