1 /++ 2 Logging 3 4 While D standard library’s `std.logger` “implements logging facilities” 5 (At the time of writing, this is its actual module description.), 6 this modules makes sense of them. 7 8 --- 9 import socketplate.log; 10 11 log("Hello world"); // prints a log message with text “Hello world” 12 --- 13 14 15 ## Log levels 16 17 --- 18 // set the log level of `sharedLog` to *INFO* 19 // (`sharedLog` is the globally available default logger implemented in `std.logger`) 20 setLogLevel(LogLevel.info); 21 22 logTrace("Trace/debug message"); 23 logInfo("Info message"); 24 logWarning("Warning message"); 25 logError("(Non-fatal, uncritical) error message"); 26 logCritical("(Non-fatal yet critical) error message"); 27 logFatalAndCrash("Fatal error message, also crashes the program"); 28 --- 29 30 31 ## Notable differences to `std.logger` 32 33 $(LIST 34 * The “default” log functions applys a log level of *INFO* instead of *ALL*. 35 * Logging function names are prefixed with `log`. 36 * The “fatal”-level logging function mentions in its name that it will crash the application. 37 * The hello-world example will actually print a log message out of the box. 38 ) 39 +/ 40 module socketplate.log; 41 42 import std.logger : defaultLogFunction; 43 public import std.logger : LogLevel; 44 45 @safe: 46 47 /// Logs a trace/debug message 48 alias logTrace = defaultLogFunction!(LogLevel.trace); 49 50 /// Logs an informational message 51 alias logInfo = defaultLogFunction!(LogLevel.info); 52 53 /// Logs a warning 54 alias logWarning = defaultLogFunction!(LogLevel.warning); 55 56 /// Logs an non-critical error 57 alias logError = defaultLogFunction!(LogLevel.error); 58 59 /// Logs a critical error 60 alias logCritical = defaultLogFunction!(LogLevel.critical); 61 62 /// Logs a fatal error and raises an Error to halt execution by crashing the application 63 alias logFatalAndCrash = defaultLogFunction!(LogLevel.fatal); 64 65 /// 66 alias log = logInfo; 67 68 /++ 69 Logs an exception (including a stack trace) 70 +/ 71 void logException(LogLevel logLevel = LogLevel.error, LogLevel details = LogLevel.trace)( 72 Throwable exception, 73 string description = "Exception", 74 int line = __LINE__, 75 string file = __FILE__, 76 string funcName = __FUNCTION__, 77 string prettyFuncName = __PRETTY_FUNCTION__, 78 string moduleName = __MODULE__, 79 ) 80 @safe nothrow 81 { 82 import std.logger : log; 83 import std.string : format; 84 85 try 86 { 87 log( 88 logLevel, 89 line, file, funcName, prettyFuncName, moduleName, 90 format!"%s: %s"(description, exception.msg) 91 ); 92 93 try 94 { 95 log( 96 details, 97 line, file, funcName, prettyFuncName, moduleName, 98 format!"Details: %s"(() @trusted { return exception.toString(); }()) 99 ); 100 } 101 catch (Exception ex) 102 { 103 logTrace(format!"Failed to log details: %s"(ex.msg)); 104 } 105 } 106 catch (Exception) 107 { 108 // suppress 109 } 110 } 111 112 /// 113 unittest 114 { 115 try 116 { 117 // … 118 } 119 catch (Exception ex) 120 { 121 logException(ex, "Operation XY failed."); 122 } 123 124 } 125 126 /// 127 unittest 128 { 129 try 130 { 131 // … 132 } 133 catch (Exception ex) 134 { 135 logException!(LogLevel.trace)(ex); 136 } 137 138 } 139 140 /++ 141 Sets the [LogLevel] of the default logger (also known as `sharedLog`) 142 +/ 143 void setLogLevel(LogLevel logLevel) 144 { 145 import std.logger : Logger, sharedLog; 146 147 Logger l = (() @trusted { return (cast() sharedLog); })(); 148 l.logLevel = logLevel; 149 }