| ... | ... | @@ -100,6 +100,23 @@ pub const Level = enum { |
| 100 | 100 | info, |
| 101 | 101 | /// Debug: messages only useful for debugging. |
| 102 | 102 | debug, |
| 103 | |
| 104 | /// Returns a string literal of the given level in full text form. |
| 105 | pub fn asText(comptime self: Level) switch (self) { |
| 106 | .emerg => @TypeOf("emergency"), |
| 107 | .crit => @TypeOf("critical"), |
| 108 | .err => @TypeOf("error"), |
| 109 | .warn => @TypeOf("warning"), |
| 110 | else => @TypeOf(@tagName(self)), |
| 111 | } { |
| 112 | return switch (self) { |
| 113 | .emerg => "emergency", |
| 114 | .crit => "critical", |
| 115 | .err => "error", |
| 116 | .warn => "warning", |
| 117 | else => @tagName(self), |
| 118 | }; |
| 119 | } |
| 103 | 120 | }; |
| 104 | 121 | |
| 105 | 122 | /// The default log level is based on build mode. |
| ... | ... | @@ -145,30 +162,34 @@ fn log( |
| 145 | 162 | if (@typeInfo(@TypeOf(root.log)) != .Fn) |
| 146 | 163 | @compileError("Expected root.log to be a function"); |
| 147 | 164 | root.log(message_level, scope, format, args); |
| 148 | | } else if (std.Target.current.os.tag == .freestanding) { |
| 149 | | // On freestanding one must provide a log function; we do not have |
| 150 | | // any I/O configured. |
| 151 | | return; |
| 152 | 165 | } else { |
| 153 | | const level_txt = switch (message_level) { |
| 154 | | .emerg => "emergency", |
| 155 | | .alert => "alert", |
| 156 | | .crit => "critical", |
| 157 | | .err => "error", |
| 158 | | .warn => "warning", |
| 159 | | .notice => "notice", |
| 160 | | .info => "info", |
| 161 | | .debug => "debug", |
| 162 | | }; |
| 163 | | const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; |
| 164 | | const stderr = std.io.getStdErr().writer(); |
| 165 | | const held = std.debug.getStderrMutex().acquire(); |
| 166 | | defer held.release(); |
| 167 | | nosuspend stderr.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; |
| 166 | defaultLog(message_level, scope, format, args); |
| 168 | 167 | } |
| 169 | 168 | } |
| 170 | 169 | } |
| 171 | 170 | |
| 171 | /// The default implementation for root.log. root.log may forward log messages |
| 172 | /// to this function. |
| 173 | pub fn defaultLog( |
| 174 | comptime message_level: Level, |
| 175 | comptime scope: @Type(.EnumLiteral), |
| 176 | comptime format: []const u8, |
| 177 | args: anytype, |
| 178 | ) void { |
| 179 | if (std.Target.current.os.tag == .freestanding) { |
| 180 | // On freestanding one must provide a log function; we do not have |
| 181 | // any I/O configured. |
| 182 | return; |
| 183 | } |
| 184 | |
| 185 | const level_txt = comptime message_level.asText(); |
| 186 | const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; |
| 187 | const stderr = std.io.getStdErr().writer(); |
| 188 | const held = std.debug.getStderrMutex().acquire(); |
| 189 | defer held.release(); |
| 190 | nosuspend stderr.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; |
| 191 | } |
| 192 | |
| 172 | 193 | /// Returns a scoped logging namespace that logs all messages using the scope |
| 173 | 194 | /// provided here. |
| 174 | 195 | pub fn scoped(comptime scope: @Type(.EnumLiteral)) type { |