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)!
This commit is contained in:
2024-08-29 16:36:58 +02:00
parent b03c770b59
commit 7889a6ec7a
3 changed files with 46 additions and 15 deletions

View File

@@ -89,6 +89,7 @@ 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: 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. - _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 ## Tips

View File

@@ -6,9 +6,13 @@ const std = @import("std");
pub fn build(b: *std.Build) void { pub fn build(b: *std.Build) void {
// build options to customize the log message formating // 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 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(); const options = b.addOptions();
options.addOption(bool, "timestamp", include_timestamp); options.addOption(bool, "timestamp", include_timestamp);
options.addOption(bool, "stderr", stderr);
options.addOption([]const u8, "file", file);
const options_module = options.createModule(); const options_module = options.createModule();

View File

@@ -15,26 +15,52 @@ fn logFn(
) void { ) void {
// TODO: provide build time configuration to allow tweaking corresponding output // TODO: provide build time configuration to allow tweaking corresponding output
// - change output file for writing messages to (default `stderr`) // - change output file for writing messages to (default `stderr`)
// write into own file for each level?
const level_txt = comptime message_level.asText(); const level_txt = comptime message_level.asText();
const prefix = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; const prefix = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
const stderr = std.io.getStdErr().writer(); const fmt = level_txt ++ prefix ++ format ++ "\n";
var bw = std.io.bufferedWriter(stderr); if (comptime build_options.file.len != 0) blk: {
const writer = bw.writer(); // 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(); var buffer = std.io.bufferedWriter(file.writer());
defer std.debug.unlockStdErr(); defer buffer.flush() catch {};
nosuspend {
if (build_options.timestamp) {
const curtime = c_time.time(null);
const tm = c_time.localtime(&curtime);
var buf: [32]u8 = undefined; const writer = buffer.writer();
_ = c_time.strftime(@ptrCast(&buf), 32, "%F %R", tm); log_writing(writer, fmt, args);
writer.print("[{s}] ", .{buf}) catch return;
}
writer.print(level_txt ++ prefix ++ format ++ "\n", args) catch return;
bw.flush() catch return;
} }
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 { pub fn pretty_format(object: anytype, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {