Skip to content

Commit e3cfd26

Browse files
committed
add ability to encode logs as JSON (in addition to the existing logfmt support)
1 parent eb10e62 commit e3cfd26

10 files changed

+1910
-416
lines changed

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
F=
12
.PHONY: t
23
t:
3-
zig build test --summary all
4+
TEST_FILTER="${F}" zig build test -freference-trace --summary all

build.zig

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub fn build(b: *std.Build) !void {
1212
.root_source_file = .{ .path = "src/logz.zig" },
1313
.target = target,
1414
.optimize = optimize,
15+
.test_runner = "test_runner.zig",
1516
});
1617
const run_test = b.addRunArtifact(lib_test);
1718
run_test.has_side_effects = true;

readme.md

+18-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Structured Logging for Zig
22

3-
logz is an opinionated structured logger that outputs to stdout using the logfmt format. It aims to minimize runtime memory allocation by using a pool of pre-allocated loggers.
3+
logz is an opinionated structured logger that outputs to stdout using logfmt or JSON. It aims to minimize runtime memory allocation by using a pool of pre-allocated loggers.
44

55
# Installation
66
This library supports native Zig module (introduced in 0.11). Add a "logz" dependency to your `build.zig.zon`.
@@ -135,11 +135,13 @@ pub const Config = struct {
135135
136136
// Where to write the output: can be either .stdout or .stderr
137137
output: Output = .stdout,
138+
139+
encoding: Encoding = .kv, // or .json
138140
};
139141
```
140142

141143
### Timestamp and Level
142-
When using the `debug`, `info`, `warn`, `err` or `fatal` functions, logs will always begin with `@ts=$MILLISECONDS_SINCE_JAN1_1970_UTC @l=$LEVEL`, such as: `@ts=1679473882025 @l=INFO`.
144+
When using the `debug`, `info`, `warn`, `err` or `fatal` functions, logs will always begin with `@ts=$MILLISECONDS_SINCE_JAN1_1970_UTC @l=$LEVEL`, such as: `@ts=1679473882025 @l=INFO`. With JSON encoding, the object will always have the `"@ts"` and `"@l"` fields.
143145

144146
### Logger Life cycle
145147
The logger is implicitly returned to the pool when `log`, `logTo` or `tryLog` is called. In rare cases where `log`, `logTo` or `tryLog` are not called, the logger must be explicitly released using its `release()` function:
@@ -148,6 +150,8 @@ The logger is implicitly returned to the pool when `log`, `logTo` or `tryLog` is
148150
// This is a contrived example to show explicit release
149151
var l = logz.info();
150152
_ = l.string("key", "value");
153+
154+
// actually, on second thought, I don't want to log anything
151155
l.release();
152156
```
153157

@@ -205,7 +209,7 @@ pub fn main() !void {
205209
### Prefixes
206210
A pool can be configured with a prefix by setting the `prefix` field of the configuration. When set, all log entries generated by loggers of this pool will contain the prefix.
207211

208-
The prefix is written as-is, with no escape and no enforcement of being a key=value.
212+
The prefix is written as-is.
209213

210214
```zig
211215
// prefix can be anything []const u8. It doesn't have to be a key=value
@@ -218,8 +222,18 @@ p.info().boolean("tea", true).log();
218222

219223
The above will generate a log line: `keemun @ts=TIMESTAMP @l=INFO tea=Y"`
220224

225+
When using `.json` encoding, your prefix must begin the object:
226+
227+
```zig:
228+
var p = try logz.Pool.init(allocator, .{.prefix = "=={"});
229+
defer p.deinit();
230+
231+
p.info().boolean("tea", true).log();
232+
```
233+
The above will generate a log line: `=={"@ts":TIMESTAMP, "@l":"INFO", "tea":true}`
234+
221235
### Multi-Use Logger
222-
Rather than having a logger automatically returned to the pool when `.log()` or `tryLog()` are called, it is possible to flag the logger for "multi-use". In such cases, the logger must be explicitly returned to the pool using `logger.release()`. This can be enabled by calling `multiuse` on the logger. Important, and the reason this feature exists, is logs by the same logger will share the same attributes up to the point where multiuse was called:
236+
Rather than having a logger automatically returned to the pool when `.log()` or `tryLog()` are called, it is possible to flag the logger for "multi-use". In such cases, the logger must be explicitly returned to the pool using `logger.release()`. This can be enabled by calling `multiuse` on the logger. Logs created by the logger will share the same attributes up to the point where multiuse was called:
223237

224238
```zig
225239
var logger = logz.logger().string("request_id", request_id).multiuse();

src/config.zig

+6
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ pub const Config = struct {
66
level: logz.Level = .Info,
77
prefix: ?[]const u8 = null,
88
output: Output = .stdout,
9+
encoding: Encoding = .logfmt,
910

1011
const Output = enum {
1112
stdout,
1213
stderr,
1314
};
15+
16+
const Encoding = enum {
17+
json,
18+
logfmt,
19+
};
1420
};

0 commit comments

Comments
 (0)