Compare commits

..

2 Commits

Author SHA1 Message Date
7889a6ec7a mod(options): build options to log to stderr and/or a file
All checks were successful
Run Tests / test (push) Successful in 43s
Run Tests / lint (push) Successful in 39s
NOTE: file logging will not work correctly yet due to opening files
appending using the std is currently not implemented (as of zig version
0.13.0)!
2024-08-29 16:36:58 +02:00
b03c770b59 doc: add tips section in README 2024-08-29 14:59:45 +02:00
3 changed files with 62 additions and 15 deletions

View File

@@ -89,3 +89,20 @@ This will result in the following output:
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. **NOTE**: 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 0.13.0! 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);
};
```

View File

@@ -6,9 +6,13 @@ const std = @import("std");
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 stderr = b.option(bool, "stderr", "Print all log messages to stderr (default: true)") orelse true;
const file = b.option([]const u8, "file", "Print all log messages to the provided file.") orelse "";
const options = b.addOptions();
options.addOption(bool, "timestamp", include_timestamp);
options.addOption(bool, "stderr", stderr);
options.addOption([]const u8, "file", file);
const options_module = options.createModule();

View File

@@ -15,26 +15,52 @@ fn logFn(
) void {
// TODO: provide build time configuration to allow tweaking corresponding output
// - change output file for writing messages to (default `stderr`)
// write into own file for each level?
const level_txt = comptime message_level.asText();
const prefix = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
const stderr = std.io.getStdErr().writer();
var bw = std.io.bufferedWriter(stderr);
const writer = bw.writer();
const fmt = level_txt ++ prefix ++ format ++ "\n";
if (comptime build_options.file.len != 0) blk: {
// NOTE: with zig 0.13.0 there is currently no way to open files to append (except to use libc or talk directly to posix, which this lib should not have to do)
const file = std.fs.openFileAbsolute(build_options.file, .{
.mode = .read_write,
}) catch std.fs.createFileAbsolute(build_options.file, .{
.truncate = false,
}) catch break :blk;
defer file.close();
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 buffer = std.io.bufferedWriter(file.writer());
defer buffer.flush() catch {};
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;
const writer = buffer.writer();
log_writing(writer, fmt, args);
}
if (comptime build_options.stderr) {
var buffer = std.io.bufferedWriter(std.io.getStdErr().writer());
defer buffer.flush() catch {};
std.debug.lockStdErr();
defer std.debug.unlockStdErr();
const writer = buffer.writer();
log_writing(writer, fmt, args);
}
}
fn log_writing(writer: anytype, comptime fmt: []const u8, args: anytype) void {
nosuspend {
if (build_options.timestamp) log_timestamp(writer);
writer.print(fmt, args) catch return;
}
}
fn log_timestamp(writer: anytype) void {
const curtime = c_time.time(null);
const tm = c_time.localtime(&curtime);
var buffer: [32]u8 = undefined;
_ = c_time.strftime(@ptrCast(&buffer), 32, "%F %R", tm);
writer.print("[{s}] ", .{buffer}) catch return;
}
pub fn pretty_format(object: anytype, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {