milestone 13 discrepancies: redact credentials from urls in logs, metrics and cli output
This commit is contained in:
+60
-2
@@ -18,13 +18,35 @@ comptime {
|
||||
_ = @import("cli.zig");
|
||||
}
|
||||
|
||||
/// Streaming, never positional, and this is load-bearing rather than a default
|
||||
/// worth changing back.
|
||||
///
|
||||
/// `File.writer` builds a `.positional` writer: it keeps an offset of its own,
|
||||
/// starting at zero, and pwrites there. `std.log` writes to the same descriptor
|
||||
/// directly and shares the descriptor's offset. With stderr redirected to a
|
||||
/// regular file the two disagree about where the end is, so the runner's first
|
||||
/// flush lands on top of whatever the log already wrote at the start and the
|
||||
/// operator loses those lines. `writerStreaming` uses the descriptor's own
|
||||
/// offset, so both writers append.
|
||||
///
|
||||
/// A terminal and a pipe are unaffected either way, because neither is seekable
|
||||
/// and the positional writer falls back to streaming on them. `2>file` is where
|
||||
/// it shows, and `nxdns run 2>logfile` is an ordinary way to run this program.
|
||||
/// `>>` needs it too: pwrite ignores `O_APPEND`.
|
||||
///
|
||||
/// Takes the `File` rather than naming stdout and stderr inside, so a test can
|
||||
/// hand it a real file and read back what an operator would have.
|
||||
fn runnerWriter(file: std.Io.File, io: std.Io, buffer: []u8) std.Io.File.Writer {
|
||||
return file.writerStreaming(io, buffer);
|
||||
}
|
||||
|
||||
pub fn main(init: std.process.Init) u8 {
|
||||
// Both `File.Writer` values are self-referential and must not move, so they
|
||||
// stay in these `var` slots for the whole of `main`.
|
||||
var out_buffer: [4096]u8 = undefined;
|
||||
var err_buffer: [4096]u8 = undefined;
|
||||
var out = std.Io.File.stdout().writer(init.io, &out_buffer);
|
||||
var err = std.Io.File.stderr().writer(init.io, &err_buffer);
|
||||
var out = runnerWriter(std.Io.File.stdout(), init.io, &out_buffer);
|
||||
var err = runnerWriter(std.Io.File.stderr(), init.io, &err_buffer);
|
||||
|
||||
const runner: cli.Runner = .{
|
||||
.io = init.io,
|
||||
@@ -55,3 +77,39 @@ pub fn main(init: std.process.Init) u8 {
|
||||
.help => cli.runHelp(runner),
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test "a runner writer appends after what std.log already put in a redirected file" {
|
||||
// Reproduced live before this test existed: `nxdns run --config <bad file>
|
||||
// 2> file` lost `info(migrations): config.db migrated from schema version 0
|
||||
// to 2`, because the runner's error writer pwrote its first flush at offset
|
||||
// zero, over the line the log had already written. Down a pipe the same run
|
||||
// kept both lines, which is why a terminal never showed this.
|
||||
var threaded: std.Io.Threaded = .init(std.testing.allocator, .{});
|
||||
defer threaded.deinit();
|
||||
const io = threaded.io();
|
||||
const gpa = std.testing.allocator;
|
||||
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var file = try tmp.dir.createFile(io, "stderr.txt", .{});
|
||||
defer file.close(io);
|
||||
|
||||
// What the log sink does: a direct write on the shared descriptor, which
|
||||
// moves the descriptor's offset. A positional writer does not see it.
|
||||
const log_line = "info(migrations): config.db migrated from schema version 0 to 2\n";
|
||||
try file.writeStreamingAll(io, log_line);
|
||||
|
||||
const runner_line = "nxdns run failed: MissingDefaultGroup\n";
|
||||
var buffer: [4096]u8 = undefined;
|
||||
var w = runnerWriter(file, io, &buffer);
|
||||
try w.interface.writeAll(runner_line);
|
||||
try w.interface.flush();
|
||||
|
||||
const seen = try tmp.dir.readFileAlloc(io, "stderr.txt", gpa, .limited(4096));
|
||||
defer gpa.free(seen);
|
||||
try std.testing.expectEqualStrings(log_line ++ runner_line, seen);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user