milestone 25: client names learned over reverse dns
Gates / test (push) Successful in 2m58s
Gates / frontend (push) Successful in 3m57s
Gates / test-aarch64 (push) Successful in 8m20s
Gates / package (push) Successful in 7m27s
Gates / container (push) Successful in 17s
CI / gates (push) Successful in 19m9s
Gates / test (push) Successful in 2m58s
Gates / frontend (push) Successful in 3m57s
Gates / test-aarch64 (push) Successful in 8m20s
Gates / package (push) Successful in 7m27s
Gates / container (push) Successful in 17s
CI / gates (push) Successful in 19m9s
This commit is contained in:
@@ -24,6 +24,7 @@ const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const cert_store = @import("../server/cert_store.zig");
|
||||
const client_names = @import("../server/client_names.zig");
|
||||
const clients = @import("../server/clients.zig");
|
||||
const dns_cache = @import("../cache/dns_cache.zig");
|
||||
const dns_handler = @import("../server/handler.zig");
|
||||
@@ -122,6 +123,7 @@ pub const Sample = struct {
|
||||
cache: ?CacheSample = null,
|
||||
limiter: ?LimiterSample = null,
|
||||
tracker: ?TrackerSample = null,
|
||||
client_names: ?client_names.Resolver.Stats = null,
|
||||
retention: ?retention_mod.Stats = null,
|
||||
blocklist: ?BlocklistSample = null,
|
||||
disk: ?DiskSample = null,
|
||||
@@ -193,6 +195,8 @@ pub fn collect(state: *server.WebState, io: std.Io, arena: Allocator) Allocator.
|
||||
.pending_clients = tracker.pendingClients(io),
|
||||
};
|
||||
|
||||
if (state.client_names) |names| sample.client_names = names.snapshotStats(io);
|
||||
|
||||
if (state.retention) |retention| sample.retention = retention.snapshotStats();
|
||||
|
||||
if (state.manager) |manager| {
|
||||
@@ -340,6 +344,10 @@ pub fn render(w: *std.Io.Writer, sample: Sample) std.Io.Writer.Error!void {
|
||||
);
|
||||
}
|
||||
|
||||
if (sample.client_names) |names| {
|
||||
try counterGroup(w, "nxdns_client_names_", "Learned client name counter", names);
|
||||
}
|
||||
|
||||
if (sample.retention) |retention| {
|
||||
try counterGroup(w, "nxdns_retention_", "Query log retention counter", retention);
|
||||
}
|
||||
@@ -594,6 +602,7 @@ fn writeLabelValue(w: *std.Io.Writer, value: []const u8) std.Io.Writer.Error!voi
|
||||
// tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const local_tables = @import("../server/local_tables.zig");
|
||||
const logger_mod = @import("../storage/logger.zig");
|
||||
const testing = std.testing;
|
||||
|
||||
@@ -645,6 +654,7 @@ test "a full sample renders the whole exposition, byte for byte" {
|
||||
.stats = .{ .tracked = 4, .flushed = 3, .dropped_full = 0, .pruned = 1, .flush_failures = 0 },
|
||||
.pending_clients = 2,
|
||||
},
|
||||
.client_names = .{ .attempted = 6, .answered = 3, .nxdomain = 1, .no_zone = 2, .invalid = 0, .failed = 0, .read_failures = 0, .write_failures = 1 },
|
||||
.retention = .{ .passes = 7, .rows_pruned = 100, .checkpoints = 7, .vacuums = 1 },
|
||||
.blocklist = .{ .refreshes_gated = 2, .generation = 4 },
|
||||
.disk = .{
|
||||
@@ -681,6 +691,9 @@ test "a full sample renders the whole exposition, byte for byte" {
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_dns_rate_limit_tracked_clients 3\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_clients_dropped_full_total 0\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_clients_pending 2\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_client_names_no_zone_total 2\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_client_names_answered_total 3\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_client_names_write_failures_total 1\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_retention_rows_pruned_total 100\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_blocklist_refreshes_gated_total 2\n"));
|
||||
try testing.expect(std.mem.containsAtLeast(u8, text, 1, "nxdns_blocklist_generation 4\n"));
|
||||
@@ -1242,12 +1255,17 @@ test "collect reads the live counters of the components it is given" {
|
||||
|
||||
var tracker: clients.Tracker = .init(30);
|
||||
var retention: retention_mod.Retention = .init(.{});
|
||||
var tables: local_tables.LocalTables = .empty;
|
||||
var names: client_names.Resolver = .init(&tables);
|
||||
names.stats.no_zone = 4;
|
||||
names.stats.attempted = 4;
|
||||
|
||||
var state: server.WebState = .{
|
||||
.gpa = testing.allocator,
|
||||
.handler = &handler,
|
||||
.logger = &query_logger,
|
||||
.tracker = &tracker,
|
||||
.client_names = &names,
|
||||
.retention = &retention,
|
||||
};
|
||||
|
||||
@@ -1263,6 +1281,7 @@ test "collect reads the live counters of the components it is given" {
|
||||
try testing.expectEqual(@as(u64, 3), sample.limiter.?.stats.refused);
|
||||
try testing.expectEqual(@as(u64, 90), sample.logger.rows_written);
|
||||
try testing.expectEqual(@as(u64, 0), sample.tracker.?.pending_clients);
|
||||
try testing.expectEqual(@as(u64, 4), sample.client_names.?.no_zone);
|
||||
try testing.expectEqual(@as(u64, 0), sample.retention.?.passes);
|
||||
try testing.expectEqual(@as(?BlocklistSample, null), sample.blocklist);
|
||||
try testing.expectEqual(@as(usize, 0), sample.upstreams.len);
|
||||
|
||||
@@ -2024,13 +2024,20 @@ components:
|
||||
|
||||
Client:
|
||||
type: object
|
||||
required: [id, ip, name, group_id, group, hand_edited, first_seen, last_seen]
|
||||
required: [id, ip, name, learned_name, group_id, group, hand_edited, first_seen, last_seen]
|
||||
properties:
|
||||
id: { type: integer }
|
||||
ip: { type: string }
|
||||
name:
|
||||
type: string
|
||||
description: Empty when the client was never named.
|
||||
learned_name:
|
||||
type: string
|
||||
description: |
|
||||
The name learned over reverse DNS, or empty when nothing was
|
||||
learned. Display-only runtime state: `name` wins whenever it is
|
||||
non-empty, and a learned name never appears in an export. The
|
||||
server writes it; a client cannot.
|
||||
group_id: { type: integer }
|
||||
group: { type: string }
|
||||
hand_edited: { type: boolean }
|
||||
|
||||
@@ -25,6 +25,7 @@ const address = @import("../platform/address.zig");
|
||||
const api_limiter = @import("api_limiter.zig");
|
||||
const auth = @import("auth.zig");
|
||||
const cert_store = @import("../server/cert_store.zig");
|
||||
const client_names = @import("../server/client_names.zig");
|
||||
const clients = @import("../server/clients.zig");
|
||||
const db = @import("../storage/db.zig");
|
||||
const disk_monitor = @import("../storage/disk_monitor.zig");
|
||||
@@ -130,6 +131,8 @@ pub const WebState = struct {
|
||||
handler: ?*dns_handler.Handler = null,
|
||||
pause: ?*pause_mod.Pause = null,
|
||||
tracker: ?*clients.Tracker = null,
|
||||
/// The learned-name resolver, for `metrics.collect` (milestone-25 ruling 9).
|
||||
client_names: ?*client_names.Resolver = null,
|
||||
manager: ?*manager_mod.Manager = null,
|
||||
pool: ?*pool_mod.Pool = null,
|
||||
monitor: ?*disk_monitor.Monitor = null,
|
||||
|
||||
Reference in New Issue
Block a user