You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ship request Host as a dedicated botlog Event field (#8)
- Add Event.Host (JSON: host) carrying the request \$host header
alongside the existing Event.ServerName (\$server_name vhost
config). Both ship side by side so receiver-side joins can pick
the right one — no silent semantic shift on serverName
- Add `host` to botlog.RequiredFields(); app.registerLogCollector
merges it into ExtractFields; Observer resolves idxHost at startup
like the other field indices
- New normalizeHost: lowercase + strip optional `:port`, handling
bracketed IPv6 literals correctly via net.SplitHostPort.
256-byte length cap applied first so a hostile 8 KB Host header
can't make SplitHostPort scan the full payload
- BuildEvent runs normalizeHost so Fields.Host can stay raw —
single source of truth; non-Observer callers don't have to know
the contract
- Reuse the existing truncate() helper instead of duplicating the
length-cap branch
- Tests: TestNormalizeHost (9 cases incl. bracketed IPv6 with/
without port and the 256-byte cap), TestObserver_HostAndServer
NameIndependent (Host normalized, ServerName raw),
TestObserver_HostMissingShipsEmpty (log_format without \$host)
- Fix stale "4 RequiredFields" wording in nginx/log.go;
docs/metrics.md gets an Event payload notes section documenting
the host vs serverName distinction and the normalization rules
Copy file name to clipboardExpand all lines: docs/metrics.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -271,6 +271,12 @@ Metrics from Angie JSON API (`/status/`). Requires `api /status/;` directive in
271
271
272
272
Opt-in. Emitted when `[BotLogs].Enabled = true`. The agent matches every parsed nginx access-log line against a built-in UA fingerprint table (38 families) and ships matched events as gzipped ndjson to the topsrv.io `/v1/bot-logs` endpoint, with disk-backed WAL spool for retry on transient send failures.
273
273
274
+
Event payload notes:
275
+
276
+
-`host` — the request `$host` header, normalized (lowercased, optional `:port` stripped, bracketed IPv6 preserved). Client-controlled. Use this when grouping by the actual domain the client requested.
277
+
-`serverName` — nginx `$server_name` of the matched virtual host (config-controlled). Use this when grouping by the operator-configured vhost.
278
+
- Both ship side by side; downstream dashboards/joins should pick the one that fits the question.
279
+
274
280
| Metric | Type | Labels | Description |
275
281
|--------|------|--------|-------------|
276
282
|`topsrv_botlog_events_total`| counter | state, reason | Event lifecycle counts. `state=enqueued` (entered queue), `sent` (acked by ingest), `spooled` (written to WAL after transient failure), `dropped` (`reason` splits cause). For non-dropped states `reason=""`. For `state=dropped` the `reason` label is one of `queue_full` (Enqueue while queue full → raise `BatchSize`), `permanent` (4xx, payload bad), `spool_write` (mkdir/write/missing SpoolDir), `spool_evict` (trim by `MaxSpoolMB` or foreign-owned file). |
0 commit comments