Add logtail if=$variable filtering and update log format examples

- ipng_stats_logtail now accepts an optional if=$variable parameter
  that suppresses log lines when the variable is empty or "0",
  following the same semantics as nginx's access_log if=. The
  condition is checked before format rendering for zero overhead on
  filtered requests. Filtered requests are still counted by stats.
- Log format examples updated to include $scheme for http/https
  visibility, and renamed to ipng_stats_logtail to match production.
- Robot test added for the if= filter (19 tests, 19 pass).
- FR-8.5 added to design doc for the if= semantics.
This commit is contained in:
2026-04-16 18:49:13 +02:00
parent 5a7e2f77f1
commit 87050bcf13
6 changed files with 124 additions and 30 deletions

View File

@@ -261,13 +261,13 @@ would add unwanted I/O pressure. For file-based access logging, use nginx's buil
Add a `log_format` declaration inside the `http { ... }` block, **before** the `ipng_stats_logtail` directive that references it:
```nginx
log_format logtail '$host\t$remote_addr\t$ipng_source_tag\t$server_addr\t'
'$request_method\t$request_uri\t$status\t$body_bytes_sent\t'
'$request_time';
log_format ipng_stats_logtail '$host\t$remote_addr\t$request_method\t$request_uri\t'
'$status\t$body_bytes_sent\t'
'$ipng_source_tag\t$server_addr\t$scheme';
```
Any nginx variable is usable here, including `$ipng_source_tag` (the device attribution tag, FR-6.1) and `$server_addr` (the VIP
that received the request).
Any nginx variable is usable here, including `$ipng_source_tag` (the device attribution tag, FR-6.1), `$server_addr` (the VIP
that received the request), and `$scheme` (`http` or `https` — useful since `$server_addr` alone doesn't distinguish ports).
### Configuration
@@ -275,17 +275,17 @@ that received the request).
http {
ipng_stats_zone ipng:4m;
log_format logtail '$host\t$remote_addr\t$ipng_source_tag\t$server_addr\t'
'$request_method\t$request_uri\t$status\t$body_bytes_sent\t'
'$request_time';
log_format ipng_stats_logtail '$host\t$remote_addr\t$request_method\t$request_uri\t'
'$status\t$body_bytes_sent\t'
'$ipng_source_tag\t$server_addr\t$scheme';
ipng_stats_logtail logtail udp://127.0.0.1:9514 buffer=16k flush=1s;
ipng_stats_logtail ipng_stats_logtail udp://127.0.0.1:9514 buffer=16k flush=1s;
server { ... }
}
```
- **`logtail`** (first argument) — the `log_format` name.
- **`ipng_stats_logtail`** (first argument) — the `log_format` name.
- **`udp://127.0.0.1:9514`** — destination as a `udp://host:port` URI. `host` must be a literal IPv4 address (no hostnames, no IPv6
in v0.1).
- **`buffer=16k`** — per-worker write buffer. Lines are held in memory until the buffer fills, the flush timer fires, or the worker
@@ -304,6 +304,25 @@ lost datagrams are acceptable and disk I/O is not.
configured buffer sizes. On routed paths, path MTU applies.
- There is no acknowledgment, retry, or sequence number. If the receiver is down, the data is gone.
### Filtering with `if=`
High-frequency requests like health checks can be suppressed from the logtail stream using the `if=$variable` parameter. Use a `map`
block to define which requests should be logged:
```nginx
map $request_uri $logtail_enabled {
~^/\.well-known/ipng/healthz 0;
default 1;
}
ipng_stats_logtail ipng_stats_logtail udp://127.0.0.1:9514 buffer=16k flush=1s if=$logtail_enabled;
```
Filtered requests are still counted by the stats module — only the logtail output is suppressed. The condition is checked before the
log format is rendered, so filtered requests have zero logtail overhead. Multiple conditions can be combined using nested `map` blocks.
See [`config-guide.md`](config-guide.md#conditional-logging-with-if) for the full semantics.
**Starting a receiver** is trivial:
```bash
@@ -317,10 +336,11 @@ datagram stream and processes it into structured log output.
A typical received log line (with the format above, tab-separated) looks like:
```
example.com 203.0.113.42 mg1 192.0.2.10 GET /index.html 200 4321 0.003
example.com 203.0.113.42 GET /index.html 200 4321 mg1 192.0.2.10 https
```
The third field (`mg1`) comes from `$ipng_source_tag` — free per-device attribution in every log line.
The `mg1` field comes from `$ipng_source_tag` and `https` from `$scheme` — free per-device attribution and protocol visibility in
every log line.
### Why this complements per-server `access_log`