All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m27s
114 lines
4.1 KiB
Markdown
114 lines
4.1 KiB
Markdown
# zlog
|
||
|
||
Standard Library log wrapper. `zlog` provides adjusted `std.log` output and a pretty print function for easy overwriting of user defined types (`struct`, `enum`, `union` and `vector`).
|
||
|
||
> [!CAUTION]
|
||
> Only builds using the zig master version are tested to work.
|
||
|
||
## Usage
|
||
|
||
The following snippet shows an example usage of `zlog` to change the default log format and add pretty printing to both user defined types (`Options` and `Struct`):
|
||
|
||
```zig
|
||
const std = @import("std");
|
||
const zlog = @import("zlog");
|
||
|
||
// use this to overwrite the default log format of `std.log`
|
||
pub const std_options = zlog.std_options;
|
||
|
||
const Options = enum {
|
||
a,
|
||
b,
|
||
c,
|
||
|
||
// copy and paste this function into your user defined types to enable pretty printing for these types
|
||
pub fn format(value: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||
try zlog.pretty_format(value, fmt, options, writer);
|
||
}
|
||
};
|
||
|
||
const Struct = struct {
|
||
a: usize = 42,
|
||
b: bool = true,
|
||
c: [5]u16 = .{ 1, 2, 3, 4, 5 },
|
||
d: []const u8 = "string",
|
||
e: Options = Options.b,
|
||
|
||
// same function as above...
|
||
pub fn format(value: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||
try zlog.pretty_format(value, fmt, options, writer);
|
||
}
|
||
};
|
||
|
||
pub fn main() void {
|
||
// initialize zlog with the scope of `main`
|
||
const log = std.log.scoped(.main);
|
||
// NOTE: the scope of `default` will result in no scoping being printed in
|
||
// the resulting output (default behavior of `std.log.defaultLog`)
|
||
|
||
// some variables to log
|
||
const int_var = 42;
|
||
const array_var = [_]i32{ 1, 2, 3, 4 };
|
||
const string_var = "This is a test";
|
||
const option_var = Options.a;
|
||
const struct_var: Struct = .{};
|
||
|
||
// NOTE: Depending on the optimization target some of these log messages
|
||
// will not show, which is inline with the behavior of `std.log`.
|
||
log.debug("Debug message {any}", .{int_var});
|
||
log.info("Info message {any}", .{array_var});
|
||
log.info("Info message \"{s}\"", .{string_var});
|
||
log.warn("Warning message {any}", .{option_var});
|
||
log.err("Error message {any}", .{struct_var});
|
||
}
|
||
```
|
||
|
||
This will result in the following output:
|
||
|
||
```
|
||
[[1m2025-02-24 13:00:08[0m] [[38;5;12mdebug[0m]([2mmain[0m): Debug message 42
|
||
[[1m2025-02-24 13:00:08[0m] [[38;5;10minfo[0m]([2mmain[0m): Info message { 1, 2, 3, 4 }
|
||
[[1m2025-02-24 13:00:08[0m] [[38;5;10minfo[0m]([2mmain[0m): Info message "This is a test"
|
||
[[1m2025-02-24 13:00:08[0m] [[38;5;11mwarning[0m]([2mmain[0m): Warning message main.Options = enum {
|
||
a,
|
||
b,
|
||
c,
|
||
} = a
|
||
[[1m2025-02-24 13:00:08[0m] [[38;5;9merror[0m]([2mmain[0m): Error message main.Struct = struct {
|
||
.a = 42,
|
||
.b = true,
|
||
.c = []u16: { 1, 2, 3, 4, 5 },
|
||
.d = { 115, 116, 114, 105, 110, 103 },
|
||
.e = main.Options = enum {
|
||
a,
|
||
b,
|
||
c,
|
||
} = 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.
|
||
- _stderr_ (default: `true`): Print log messages to stderr.
|
||
> [!CAUTION]
|
||
> Currently not working as log output is not appended and only the last log message will be in the resulting log file! This is a not-yet-implemented feature of the standard library of zig! See this [issue](https://github.com/ziglang/zig/issues/14375) for more details.
|
||
|
||
## Tips
|
||
|
||
The following list shows some tips on how to use logging more effectively. These tips do not apply just to `zlog` (and not even only to zig code).
|
||
|
||
- Use `errdefer` to directly print messages on failures in the same function they occur:
|
||
```zig
|
||
// assume log is already defined before (with the corresponding scope)
|
||
const port = port: {
|
||
errdefer |err| log.err("failed to read the port number: {}", .{err});
|
||
|
||
var buf: [fmt.count("{}\n", .{maxInt(u16)})]u8 = undefined;
|
||
const len = try process.stdout.?.readAll(&buf);
|
||
break :port try fmt.parseInt(u16, buf[0 .. len -| 1], 10);
|
||
};
|
||
```
|