diff --git a/src/browser/webapi/Console.zig b/src/browser/webapi/Console.zig index 81fdc54b..5fe4f80a 100644 --- a/src/browser/webapi/Console.zig +++ b/src/browser/webapi/Console.zig @@ -52,6 +52,15 @@ const ValueWriter = struct { try writer.print("\n stack: {s}", .{self.page.js.stackTrace() catch |err| @errorName(err) orelse "???"}); } } + + pub fn logFmt(self: ValueWriter, _: []const u8, writer: anytype) !void { + var buf: [32]u8 = undefined; + for (self.values, 0..) |value, i| { + const name = try std.fmt.bufPrint(&buf, "param.{d}", .{i}); + try writer.write(name, try value.toString()); + } + } + pub fn jsonStringify(self: ValueWriter, writer: *std.json.Stringify) !void { try writer.beginArray(); for (self.values) |value| { diff --git a/src/log.zig b/src/log.zig index d3ab7c76..0f25809b 100644 --- a/src/log.zig +++ b/src/log.zig @@ -154,17 +154,22 @@ fn logTo(comptime scope: Scope, level: Level, comptime msg: []const u8, data: an } } -fn logLogfmt(comptime scope: Scope, level: Level, comptime msg: []const u8, data: anytype, writer: anytype) !void { +fn logLogfmt(comptime scope: Scope, level: Level, comptime msg: []const u8, data: anytype, writer: *std.Io.Writer) !void { try logLogFmtPrefix(scope, level, msg, writer); inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |f| { - const key = " " ++ f.name ++ "="; - try writer.writeAll(key); - try writeValue(.logfmt, @field(data, f.name), writer); + const value = @field(data, f.name); + if (std.meta.hasMethod(@TypeOf(value), "logFmt")) { + try value.logFmt(f.name, LogFormatWriter{.writer = writer}); + } else { + const key = " " ++ f.name ++ "="; + try writer.writeAll(key); + try writeValue(.logfmt, value, writer); + } } try writer.writeByte('\n'); } -fn logLogFmtPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8, writer: anytype) !void { +fn logLogFmtPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8, writer: *std.Io.Writer) !void { try writer.writeAll("$time="); try writer.print("{d}", .{timestamp(.clock)}); @@ -185,7 +190,7 @@ fn logLogFmtPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8 try writer.writeAll(full_msg); } -fn logPretty(comptime scope: Scope, level: Level, comptime msg: []const u8, data: anytype, writer: anytype) !void { +fn logPretty(comptime scope: Scope, level: Level, comptime msg: []const u8, data: anytype, writer: *std.Io.Writer) !void { try logPrettyPrefix(scope, level, msg, writer); inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |f| { const key = " " ++ f.name ++ " = "; @@ -196,7 +201,7 @@ fn logPretty(comptime scope: Scope, level: Level, comptime msg: []const u8, data try writer.writeByte('\n'); } -fn logPrettyPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8, writer: anytype) !void { +fn logPrettyPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8, writer: *std.Io.Writer) !void { if (scope == .console and level == .fatal and comptime std.mem.eql(u8, msg, "lightpanda")) { try writer.writeAll("\x1b[0;104mWARN "); } else { @@ -228,7 +233,7 @@ fn logPrettyPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8 } } -pub fn writeValue(comptime format: Format, value: anytype, writer: anytype) !void { +pub fn writeValue(comptime format: Format, value: anytype, writer: *std.Io.Writer) !void { const T = @TypeOf(value); if (std.meta.hasMethod(T, "format")) { return writer.print("{f}", .{value}); @@ -271,7 +276,7 @@ pub fn writeValue(comptime format: Format, value: anytype, writer: anytype) !voi @compileError("cannot log a: " ++ @typeName(T)); } -fn writeString(comptime format: Format, value: []const u8, writer: anytype) !void { +fn writeString(comptime format: Format, value: []const u8, writer: *std.Io.Writer) !void { if (format == .pretty) { return writer.writeAll(value); } @@ -325,6 +330,16 @@ fn writeString(comptime format: Format, value: []const u8, writer: anytype) !voi return writer.writeByte('"'); } +pub const LogFormatWriter = struct { + writer: *std.Io.Writer, + + pub fn write(self: LogFormatWriter, key: []const u8, value: []const u8) !void { + const writer = self.writer; + try writer.print(" {s}=", .{key}); + try writeString(.logfmt, value, writer); + } +}; + var first_log: u64 = 0; fn elapsed() struct { time: f64, unit: []const u8 } { const now = timestamp(.monotonic);