diff --git a/lib/std/log.zig b/lib/std/log.zig index 215e611bc1..9d9271213b 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -117,13 +117,30 @@ pub const level: Level = if (@hasDecl(root, "log_level")) else default_level; +pub const ScopeLevel = struct { + scope: @Type(.EnumLiteral), + level: Level, +}; + +const scope_levels = if (@hasDecl(root, "scope_levels")) + root.scope_levels +else + [0]ScopeLevel{}; + fn log( comptime message_level: Level, comptime scope: @Type(.EnumLiteral), comptime format: []const u8, args: anytype, ) void { - if (@enumToInt(message_level) <= @enumToInt(level)) { + const effective_log_level = blk: { + inline for (scope_levels) |scope_level| { + if (scope_level.scope == scope) break :blk scope_level.level; + } + break :blk level; + }; + + if (@enumToInt(message_level) <= @enumToInt(effective_log_level)) { if (@hasDecl(root, "log")) { root.log(message_level, scope, format, args); } else if (std.Target.current.os.tag == .freestanding) { diff --git a/test/compare_output.zig b/test/compare_output.zig index a6e9835ea1..91ace76b60 100644 --- a/test/compare_output.zig +++ b/test/compare_output.zig @@ -516,4 +516,87 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { break :x tc; }); + + // It is required to override the log function in order to print to stdout instead of stderr + cases.add("std.log per scope log level override", + \\const std = @import("std"); + \\ + \\pub const log_level: std.log.Level = .debug; + \\ + \\pub const scope_levels = [_]std.log.ScopeLevel{ + \\ .{ .scope = .a, .level = .alert }, + \\ .{ .scope = .c, .level = .emerg }, + \\}; + \\ + \\const loga = std.log.scoped(.a); + \\const logb = std.log.scoped(.b); + \\const logc = std.log.scoped(.c); + \\ + \\pub fn main() !void { + \\ loga.debug("", .{}); + \\ logb.debug("", .{}); + \\ logc.debug("", .{}); + \\ + \\ loga.info("", .{}); + \\ logb.info("", .{}); + \\ logc.info("", .{}); + \\ + \\ loga.notice("", .{}); + \\ logb.notice("", .{}); + \\ logc.notice("", .{}); + \\ + \\ loga.warn("", .{}); + \\ logb.warn("", .{}); + \\ logc.warn("", .{}); + \\ + \\ loga.err("", .{}); + \\ logb.err("", .{}); + \\ logc.err("", .{}); + \\ + \\ loga.crit("", .{}); + \\ logb.crit("", .{}); + \\ logc.crit("", .{}); + \\ + \\ loga.alert("", .{}); + \\ logb.alert("", .{}); + \\ logc.alert("", .{}); + \\ + \\ loga.emerg("", .{}); + \\ logb.emerg("", .{}); + \\ logc.emerg("", .{}); + \\} + \\pub fn log( + \\ comptime level: std.log.Level, + \\ comptime scope: @TypeOf(.EnumLiteral), + \\ comptime format: []const u8, + \\ args: anytype, + \\) void { + \\ const level_txt = switch (level) { + \\ .emerg => "emergency", + \\ .alert => "alert", + \\ .crit => "critical", + \\ .err => "error", + \\ .warn => "warning", + \\ .notice => "notice", + \\ .info => "info", + \\ .debug => "debug", + \\ }; + \\ const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; + \\ const stdout = std.io.getStdOut().writer(); + \\ nosuspend stdout.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; + \\} + , + \\debug(b): + \\info(b): + \\notice(b): + \\warning(b): + \\error(b): + \\critical(b): + \\alert(a): + \\alert(b): + \\emergency(a): + \\emergency(b): + \\emergency(c): + \\ + ); }