milestone 26: upstream health answers for the selected period
This commit is contained in:
@@ -30,6 +30,7 @@ const dns_cache = @import("../cache/dns_cache.zig");
|
||||
const dns_handler = @import("../server/handler.zig");
|
||||
const disk_monitor = @import("../storage/disk_monitor.zig");
|
||||
const dot_server = @import("../server/dot_server.zig");
|
||||
const history_mod = @import("../upstream/history.zig");
|
||||
const http_util = @import("http_util.zig");
|
||||
const logging = @import("../platform/logging.zig");
|
||||
const pool_mod = @import("../upstream/pool.zig");
|
||||
@@ -125,6 +126,9 @@ pub const Sample = struct {
|
||||
tracker: ?TrackerSample = null,
|
||||
client_names: ?client_names.Resolver.Stats = null,
|
||||
retention: ?retention_mod.Stats = null,
|
||||
/// The upstream-history flush loop's counters (m26 ruling 7). Absent while
|
||||
/// no accumulator is wired, like every other collaborator.
|
||||
history: ?history_mod.Accumulator.Stats = null,
|
||||
blocklist: ?BlocklistSample = null,
|
||||
disk: ?DiskSample = null,
|
||||
/// One entry per enabled TLS endpoint (milestone-10 ruling 10). Rendered
|
||||
@@ -199,6 +203,8 @@ pub fn collect(state: *server.WebState, io: std.Io, arena: Allocator) Allocator.
|
||||
|
||||
if (state.retention) |retention| sample.retention = retention.snapshotStats();
|
||||
|
||||
if (state.history) |history| sample.history = history.snapshotStats(io);
|
||||
|
||||
if (state.manager) |manager| {
|
||||
const generation: ?u64 = if (manager.acquire(io)) |acquired| gen: {
|
||||
defer acquired.release(io);
|
||||
@@ -352,6 +358,36 @@ pub fn render(w: *std.Io.Writer, sample: Sample) std.Io.Writer.Error!void {
|
||||
try counterGroup(w, "nxdns_retention_", "Query log retention counter", retention);
|
||||
}
|
||||
|
||||
if (sample.history) |history| {
|
||||
// Written out rather than reflected over `Accumulator.Stats`: three of
|
||||
// its fields are counters, one is a gauge, and two — the drop watermark
|
||||
// and the current flush state — are not exposition numbers at all.
|
||||
try counter(
|
||||
w,
|
||||
"nxdns_upstream_history_flushes_total",
|
||||
"Upstream history flush transactions that committed.",
|
||||
history.flushes,
|
||||
);
|
||||
try counter(
|
||||
w,
|
||||
"nxdns_upstream_history_flush_failures_total",
|
||||
"Upstream history flush attempts that failed; the rows are retried on the next pass.",
|
||||
history.flush_failures,
|
||||
);
|
||||
try counter(
|
||||
w,
|
||||
"nxdns_upstream_history_rows_dropped_total",
|
||||
"Upstream history minutes dropped because the accumulator was full.",
|
||||
history.rows_dropped,
|
||||
);
|
||||
try gauge(
|
||||
w,
|
||||
"nxdns_upstream_history_pending",
|
||||
"Upstream history minutes recorded but not yet flushed.",
|
||||
history.pending,
|
||||
);
|
||||
}
|
||||
|
||||
if (sample.blocklist) |blocklist| {
|
||||
try counter(
|
||||
w,
|
||||
@@ -720,6 +756,31 @@ test "a full sample renders the whole exposition, byte for byte" {
|
||||
));
|
||||
}
|
||||
|
||||
test "the upstream-history family renders three counters and one gauge" {
|
||||
const text = try renderToString(testing.allocator, .{
|
||||
.history = .{
|
||||
.flushes = 12,
|
||||
.flush_failures = 2,
|
||||
.rows_dropped = 5,
|
||||
.pending = 3,
|
||||
.last_drop_minute = 1_700_000_040,
|
||||
.last_flush_failed = true,
|
||||
},
|
||||
});
|
||||
defer testing.allocator.free(text);
|
||||
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_upstream_history_flushes_total 12\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_upstream_history_flush_failures_total 2\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_upstream_history_rows_dropped_total 5\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "# TYPE nxdns_upstream_history_pending gauge\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_upstream_history_pending 3\n"));
|
||||
|
||||
// No accumulator is an absent family, not a family of zeros.
|
||||
const bare = try renderToString(testing.allocator, .{});
|
||||
defer testing.allocator.free(bare);
|
||||
try testing.expect(!std.mem.containsAtLeast(u8, bare, 1, "nxdns_upstream_history_"));
|
||||
}
|
||||
|
||||
test "every HELP line has a TYPE line and a sample, and every sample a name" {
|
||||
const text = try renderToString(testing.allocator, .{});
|
||||
defer testing.allocator.free(text);
|
||||
|
||||
Reference in New Issue
Block a user