Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Service renames and valid separator-containing names can produce inconsistent or missing Service attribution.
Review effort: Balanced
Findings: 1
What changed in this PR
Adds Service attribution to Stream Prometheus metrics using runtime-managed session labels.
Changes:
- Adds
serviceandservice_idlabels to four Stream metrics. - Introduces preread labeling and Service-aware metric collection.
- Updates runtime requirements, documentation, and tests.
| File | Description |
|---|---|
.requirements |
Bumps APISIX Runtime to 1.3.19. |
ci/linux-install-openresty.sh |
Updates runtime version and checksums. |
apisix/stream/plugins/prometheus.lua |
Registers the preread handler. |
apisix/plugins/prometheus/exporter.lua |
Resolves, records, and exports Service labels. |
docs/en/latest/plugins/prometheus.md |
Documents Stream Service labels. |
docs/zh/latest/plugins/prometheus.md |
Adds corresponding Chinese documentation. |
t/stream-plugin/prometheus.t |
Updates expected connection labels. |
t/stream-plugin/prometheus-metrics.t |
Updates assertions and adds Service cases. |
t/stream-plugin/prometheus-metrics-service.t |
Tests live Service-split zone metrics. |
t/cli/test_prometheus_stream.sh |
Updates CLI metric assertions. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
A route with an upstream_id and a service_id fetched its service name in preread and again in the log phase, so a rename while the session was open labelled the zone with one name and the status with another. Resolve the pair once per session on ctx and reuse it.
nic-6443
approved these changes
Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Description
The Stream metrics are keyed by
listen_addr(apisix_stream_status,apisix_stream_active_connections,apisix_stream_bandwidth) or byroute(apisix_stream_connection_total). None of them says which Service a port's traffic belongs to, although a Service can own several ports and a port can carry Routes of several Services.This adds
serviceandservice_idto all four Stream metrics:apisix_stream_connection_totalroute,service,service_idapisix_stream_active_connectionslisten_addr,service,service_idapisix_stream_statuscode,listen_addr,service,service_id,nodeapisix_stream_bandwidthlisten_addr,service,service_id,type,sideLabel rule. It is the same as for the HTTP metrics:
service_idis the ID of the Service the session's Stream Route belongs to;serviceis that ID too, or the Service's name when the Route'sprometheusPlugin setsprefer_name: true.Both are empty for a session that never reached a Stream Route with a Service, for example a failed TLS handshake or no matching Route. Such sessions are only counted in the
listen_addrtotal, so summing overservicegives the same values as before.How the zone metrics get the label.
apisix_stream_active_connectionsandapisix_stream_bandwidthcome from an NGINX shared memory zone that sums every session of a listening address, so they cannot be split after the fact. api7/apisix-nginx-module#127 (released in 1.19.11) lets a session be labelled with an ordered array of values. From then on, its active count and the bytes it moves are accounted on a(listen_addr, labels)slot. The split is therefore live: a long-lived connection is visible under its Service while it runs.prometheusPlugin gains aprereadphase. It resolves{service, service_id}from the session context and its own conf, and passes them toset_labels. Core code is untouched.labels. There is no side channel between the subsystems.apisix_stream_statusandapisix_stream_connection_totalresolve the same labels in the log phase.upstream_idandservice_id. The Service is not merged into such a Route. The Route's ownservice_idstill labels it, as in the HTTP metrics.Runtime.
.requirementsmoves to APISIX-Runtime 1.3.19, the first runtime carrying apisix-nginx-module 1.19.11.ci/linux-install-openresty.shgets the matchingapisix-runtime-debugchecksums.Trade-offs
prereadby a higher-priority Stream Plugin (ip-restriction,limit-conn) is never labelled, so its active count and bytes stay in the unlabelled total.apisix_stream_statusstill reports it under its Service.prefer_namechange, gets a new zone slot; the old series stays (the gauge at 0). Slots are freed only on restart.1mholds about 760 slots. When they run out, sessions of a new Service stay in theirlisten_addrtotal, and a warning is logged once per worker.Which issue(s) this PR fixes:
N/A
Checklist
Backward compatibility. Each existing series gains
service=""andservice_id="", and per-Service series appear next to it. Aggregations overlisten_addr(orroute) return the same values. An alert on a single unaggregated series needs its selector adjusted.Tests
t/stream-plugin/prometheus-metrics.t. Existing assertions gain the two labels. New cases cover:prefer_name;upstream_idandservice_id.t/stream-plugin/prometheus-metrics-service.t(new). It covers:prefer_nameon the live series and on the status;t/stream-plugin/prometheus.t,t/cli/test_prometheus_stream.sh. Theirapisix_stream_connection_totalassertions gain the empty labels.Run locally on the released APISIX-Runtime 1.3.19 deb: every assertion in the three
t/stream-pluginfiles passes. The only failures left are the lua-resty-eventsevent worker failedlines during HUP reloads, which CI downgrades towarnafter installing the runtime.