PRE-RELEASE v0.8.2
This commit is contained in:
@@ -128,6 +128,12 @@ Each requirement carries a unique identifier (`FR-X.Y` or `NFR-X.Y`) so that lat
|
||||
codes are observed. Operators who need a full per-code breakdown SHOULD enable `ipng_stats_logtail` (FR-8) and derive the per-code
|
||||
view from the access-log stream off the hot path; the stats zone intentionally trades that resolution for a much smaller scrape
|
||||
response.
|
||||
- **FR-2.7** The module MUST additionally maintain, per `(source, vip)` pair, three point-in-time gauges of requests currently in
|
||||
flight: `active` (observed at `POST_READ` but not yet finalized), `reading` (in the pre-response phases — rewrite/access/content),
|
||||
and `writing` (past the header-send transition). The invariant `reading + writing = active` MUST hold at any instant. Subrequests
|
||||
and internal redirects MUST NOT double-count the parent request. Updates to the gauges are atomic increments/decrements on the
|
||||
request lifecycle hooks — no slab lock after the first time a `(source, vip)` pair is seen — so the hot-path rule in FR-4.1 still
|
||||
holds for ordinary counter updates while gauges are maintained lock-free.
|
||||
|
||||
**FR-3 Scrape endpoint**
|
||||
|
||||
@@ -147,6 +153,8 @@ Each requirement carries a unique identifier (`FR-X.Y` or `NFR-X.Y`) so that lat
|
||||
`source_tag` and `vip`. Counter metrics (`nginx_ipng_requests_total`, `nginx_ipng_bytes_{in,out}_total`, `nginx_ipng_latency_total`)
|
||||
additionally carry a `code` label with a class value (`1xx`..`5xx`/`unknown`). Histogram series (duration, upstream response,
|
||||
request/response byte size) MUST NOT carry a `code` label — they aggregate across all classes for a given `(source, vip)` pair.
|
||||
Gauge series (`nginx_ipng_active`, `nginx_ipng_reading`, `nginx_ipng_writing`) MUST be labelled with `source_tag` and `vip` only
|
||||
(no `code`) and MUST be typed as `gauge` in the exposition preamble.
|
||||
|
||||
**FR-4 Hot path and flush**
|
||||
|
||||
@@ -407,6 +415,12 @@ Histogram lanes are kept per `(source, vip, class)` in storage, then summed acro
|
||||
A parallel table keyed by `(source_id, vip_id)` — one row per VIP — holds the EWMAs for instantaneous rate. EWMAs are floats but updated
|
||||
only from the flush tick, so there is no float contention on the request path.
|
||||
|
||||
A second, smaller rbtree lives alongside the counter tree — one node per `(source_id, vip_id)` pair — holding three atomic gauge
|
||||
lanes (`active`, `reading`, `writing`; FR-2.7). Unlike the counter path, gauges are updated from request lifecycle hooks
|
||||
(`POST_READ`, header filter, pool cleanup) with atomic inc/dec directly on the shared node. The slab mutex is taken only the first
|
||||
time a `(source, vip)` pair is seen; subsequent transitions on that pair are lock-free. Gauge nodes are never evicted — their
|
||||
cardinality equals the number of distinct `(source, vip)` pairs and is small in practice.
|
||||
|
||||
The module also keeps a small string interning table for source and VIP strings, keyed by the integer IDs above, so that the scrape
|
||||
endpoint can recover the original strings without re-parsing configuration.
|
||||
|
||||
|
||||
@@ -249,6 +249,14 @@ nginx_ipng_bytes_in_total{source_tag="mg1",vip="192.0.2.10",code="2xx"} 9876543
|
||||
# Histogram series (request_duration, upstream_response, bytes_in, bytes_out)
|
||||
# do NOT carry a `code` label — they aggregate across classes per (source, vip).
|
||||
nginx_ipng_request_duration_seconds_bucket{source_tag="mg1",vip="192.0.2.10",le="0.050"} 11200
|
||||
|
||||
# In-flight gauges per (source, vip). These are point-in-time request counts,
|
||||
# not rates: `active` = requests observed at POST_READ that haven't finalized
|
||||
# yet; `reading` = in pre-response phases (rewrite/access/content); `writing`
|
||||
# = past header send. reading + writing = active at any instant.
|
||||
nginx_ipng_active{source_tag="mg1",vip="192.0.2.10"} 3
|
||||
nginx_ipng_reading{source_tag="mg1",vip="192.0.2.10"} 1
|
||||
nginx_ipng_writing{source_tag="mg1",vip="192.0.2.10"} 2
|
||||
```
|
||||
|
||||
For JSON output instead, set the `Accept` header:
|
||||
@@ -300,6 +308,11 @@ sum by (vip) (rate(nginx_ipng_requests_total[5m]))
|
||||
# p95 request duration per (source_tag, vip):
|
||||
histogram_quantile(0.95,
|
||||
sum by (source_tag, vip, le) (rate(nginx_ipng_request_duration_seconds_bucket[5m])))
|
||||
|
||||
# In-flight concurrency per (source_tag, vip). Gauges are exported as-is;
|
||||
# use max_over_time for load-shedding alerts or avg_over_time for capacity
|
||||
# planning:
|
||||
max_over_time(nginx_ipng_active[5m])
|
||||
```
|
||||
|
||||
## 6. Set up a global logtail access log
|
||||
|
||||
Reference in New Issue
Block a user