diff --git a/README.md b/README.md index 08963d4..d9b0a8d 100644 --- a/README.md +++ b/README.md @@ -63,15 +63,15 @@ pub fn main() void { This will result in the following output: ``` -debug(main): Debug message 42 -info(main): Info message { 1, 2, 3, 4 } -info(main): Info message "This is a test" -warning(main): Warning message main.Options = enum { +[2024-08-28 22:22] debug(main): Debug message 42 +[2024-08-28 22:22] info(main): Info message { 1, 2, 3, 4 } +[2024-08-28 22:22] info(main): Info message "This is a test" +[2024-08-28 22:22] warning(main): Warning message main.Options = enum { a, b, c, } = a -error(main): Error message main.Struct = struct { +[2024-08-28 22:22] error(main): Error message main.Struct = struct { .a = 42, .b = true, .c = []u16: { 1, 2, 3, 4, 5 }, @@ -83,3 +83,9 @@ error(main): Error message main.Struct = struct { } = b, } ``` + +## Customization + +For more details about the output customization see the configuration options of the `zlog` module. Following options are available: + +- _timestamp_ (default: `true`): Prepend the current timestamp before each log message. diff --git a/build.zig b/build.zig index 6667936..2e8f7e5 100644 --- a/build.zig +++ b/build.zig @@ -4,6 +4,14 @@ const std = @import("std"); // declaratively construct a build graph that will be executed by an external // runner. pub fn build(b: *std.Build) void { + // build options to customize the log message formating + const include_timestamp = b.option(bool, "timestamp", "Enable inclusion of timestamps in log messages (default: true)") orelse true; + + const options = b.addOptions(); + options.addOption(bool, "timestamp", include_timestamp); + + const options_module = options.createModule(); + // Standard target options allows the person running `zig build` to choose // what target to build for. Here we do not override the defaults, which // means any target is allowed, and the default is native. Other options @@ -21,7 +29,9 @@ pub fn build(b: *std.Build) void { .root_source_file = b.path("src/zlog.zig"), .target = target, .optimize = optimize, + .link_libc = include_timestamp, // uses c std library }); + zlog_module.addImport("build_options", options_module); const exe = b.addExecutable(.{ .name = "zlog", diff --git a/src/zlog.zig b/src/zlog.zig index d19a30f..01122a1 100644 --- a/src/zlog.zig +++ b/src/zlog.zig @@ -1,13 +1,7 @@ +const build_options = @import("build_options"); +const c_time = if (build_options.timestamp) @cImport(@cInclude("time.h")) else null; const std = @import("std"); -// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void -// TODO: provide comptime helper function to add format function for user types: -// - pretty printing -// - compact printing -// - show types of struct members -// Maybe the corresponding configurations for the `format` function could also -// be effected by build time configurations - pub const std_options: std.Options = .{ .logFn = logFn, }; @@ -20,15 +14,9 @@ fn logFn( args: anytype, ) void { // TODO: provide build time configuration to allow tweaking corresponding output - // - add timestamp to all log messages // - change output file for writing messages to (default `stderr`) - - // TODO: improve formatting output, such that the resulting log has a good feel - // - should there be indenting? - // - should there be spacing? - // - should the messages be aligned (left, center, right)? const level_txt = comptime message_level.asText(); - const prefix = if (scope == .default) ":\t" else "(" ++ @tagName(scope) ++ "):\t"; + const prefix = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; const stderr = std.io.getStdErr().writer(); var bw = std.io.bufferedWriter(stderr); const writer = bw.writer(); @@ -36,6 +24,14 @@ fn logFn( std.debug.lockStdErr(); defer std.debug.unlockStdErr(); nosuspend { + if (build_options.timestamp) { + const curtime = c_time.time(null); + const tm = c_time.localtime(&curtime); + + var buf: [32]u8 = undefined; + _ = c_time.strftime(@ptrCast(&buf), 32, "%F %R", tm); + writer.print("[{s}] ", .{buf}) catch return; + } writer.print(level_txt ++ prefix ++ format ++ "\n", args) catch return; bw.flush() catch return; }