Files
zlog/README.md
Yves Biener a21d84cfcf
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m27s
feat(zlog): colored level text and styled timestamps and scopes
2025-02-24 14:01:49 +01:00

114 lines
4.1 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```
[2025-02-24 13:00:08] [debug](main): Debug message 42
[2025-02-24 13:00:08] [info](main): Info message { 1, 2, 3, 4 }
[2025-02-24 13:00:08] [info](main): Info message "This is a test"
[2025-02-24 13:00:08] [warning](main): Warning message main.Options = enum {
a,
b,
c,
} = a
[2025-02-24 13:00:08] [error](main): 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);
};
```