feat: add per-route stat prefix support to TrafficPolicy#14409
Merged
davidjumani merged 4 commits intoJul 15, 2026
Conversation
puertomontt
force-pushed
the
feat/per-route-stat-prefix
branch
from
July 14, 2026 16:57
59fd7f3 to
73a6975
Compare
puertomontt
force-pushed
the
feat/per-route-stat-prefix
branch
from
July 14, 2026 17:09
73a6975 to
91491ba
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Adds opt-in per-route Envoy Route.stat_prefix support to the TrafficPolicy plugin, allowing operators to template route metric prefixes using targeted route metadata (route namespace/name and rule name) during translation.
Changes:
- Introduces
spec.statPrefixonTrafficPolicywith CRD validation and documentation. - Extends route IR to carry user-authored rule name (
RuleName) and wires it through HTTPRoute translation for templating. - Implements TrafficPolicy IR + merge + translation-pass application of route
stat_prefix, with unit and golden translation tests.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/pluginsdk/ir/gw2.go | Adds RuleName to route match IR for user-facing templating. |
| pkg/kgateway/translator/httproute/gateway_http_route_translator.go | Populates RuleName from the rule’s authored name during route translation. |
| pkg/kgateway/translator/gateway/testutils/outputs/traffic-policy/stat-prefix.yaml | Adds golden output verifying Envoy routes get statPrefix set. |
| pkg/kgateway/translator/gateway/testutils/inputs/traffic-policy/stat-prefix.yaml | Adds input manifests covering templated and literal statPrefix behavior. |
| pkg/kgateway/translator/gateway/gateway_translator_test.go | Registers a new gateway translator test case for statPrefix. |
| pkg/kgateway/extensions2/plugins/trafficpolicy/traffic_policy_plugin.go | Includes statPrefix in policy IR equality/validation and applies it per-route. |
| pkg/kgateway/extensions2/plugins/trafficpolicy/stat_prefix.go | Implements IR, validation, template substitution, and Envoy Route statPrefix application. |
| pkg/kgateway/extensions2/plugins/trafficpolicy/stat_prefix_test.go | Adds unit tests for validation, IR construction, and per-route application behavior. |
| pkg/kgateway/extensions2/plugins/trafficpolicy/merge.go | Adds merge support for statPrefix across attached TrafficPolicies. |
| pkg/kgateway/extensions2/plugins/trafficpolicy/constructor.go | Constructs statPrefix sub-IR during TrafficPolicy IR build. |
| install/helm/kgateway-crds/templates/gateway.kgateway.dev_trafficpolicies.yaml | Updates generated CRD schema to include statPrefix. |
| api/v1alpha1/kgateway/zz_generated.deepcopy.go | Updates deepcopy for the new StatPrefix field. |
| api/v1alpha1/kgateway/traffic_policy_types.go | Adds the StatPrefix field, docs, and kubebuilder validations. |
Files not reviewed (1)
- api/v1alpha1/kgateway/zz_generated.deepcopy.go: Generated file
Comment on lines
+120
to
+123
| // A template such as `{{rule_name}}` can resolve to an empty string when the | ||
| // rule is unnamed; trim any leading/trailing separators left behind so the | ||
| // emitted stat name stays clean. | ||
| out.StatPrefix = strings.Trim(out.GetStatPrefix(), ".") |
puertomontt
force-pushed
the
feat/per-route-stat-prefix
branch
4 times, most recently
from
July 14, 2026 17:42
6954c28 to
0d8b0e4
Compare
puertomontt
force-pushed
the
feat/per-route-stat-prefix
branch
from
July 14, 2026 18:08
0d8b0e4 to
b5bb681
Compare
Comment on lines
+97
to
+103
| // A template variable (e.g. rule_name for an unnamed rule) can resolve to an | ||
| // empty string. '.' delimits segments in Envoy stat names, so drop any empty | ||
| // '.'-separated segments this leaves behind (leading, trailing, or in the | ||
| // middle) to avoid doubled or trailing dots, which produce malformed stat | ||
| // names and blank levels in dot-hierarchy sinks such as statsd/Graphite. | ||
| out.StatPrefix = joinNonEmptyStatSegments(resolved) | ||
| } |
davidjumani
approved these changes
Jul 14, 2026
| // +kubebuilder:validation:MinLength=1 | ||
| // +kubebuilder:validation:MaxLength=256 | ||
| // +kubebuilder:validation:Pattern=`^([a-zA-Z0-9_%.-]|\{\{\s*(route_name|route_namespace|rule_name)\s*\}\})+$` | ||
| StatPrefix *string `json:"statPrefix,omitempty"` |
Contributor
There was a problem hiding this comment.
Should this have a default such as namespace.name.rule ? Would that introduce a breaking change ?
davidjumani
enabled auto-merge
July 14, 2026 19:13
puertomontt
force-pushed
the
feat/per-route-stat-prefix
branch
2 times, most recently
from
July 14, 2026 19:20
52caf96 to
1a3c286
Compare
davidjumani
approved these changes
Jul 14, 2026
Add an opt-in `spec.statPrefix` field on TrafficPolicy that sets Envoy's
route-level `stat_prefix`, enabling per-route statistics that map back to
Kubernetes resources.
The value is composed of stat-safe literal characters and/or `{{ ... }}`
template tokens (`{{route_name}}`, `{{route_namespace}}`, `{{rule_name}}`)
that are resolved at translation time from the targeted route's metadata. The
prefix is set on the Envoy Route (not the RouteAction), so it also applies to
redirect and direct-response routes.
Validation is enforced entirely by the CRD schema: the field's Pattern only
admits stat-safe literal runs and well-formed template tokens referencing a
supported variable name, and a spec-level CEL rule restricts the field to
HTTPRoute and GRPCRoute targets (it is not honored on Gateway attachments).
Because the CRD ships inside a Helm chart whose templates dir is rendered as
Go templates, codegen escapes the literal `{{ }}` tokens in the generated CRD
description so they survive `helm lint` and render back to the original text.
The Pattern uses escaped braces (`\{\{`) so it is left untouched.
Fixes kgateway-dev#13564
Signed-off-by: omar <[email protected]>
Co-authored-by: Mihir Dixit <[email protected]>
puertomontt
force-pushed
the
feat/per-route-stat-prefix
branch
from
July 14, 2026 19:55
1a3c286 to
af73c49
Compare
andy-fong
approved these changes
Jul 15, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Jul 15, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Jul 15, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Jul 15, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Jul 15, 2026
davidjumani
enabled auto-merge
July 15, 2026 19:01
sheidkamp
pushed a commit
to sheidkamp/kgateway
that referenced
this pull request
Jul 16, 2026
…v#14409) Signed-off-by: omar <[email protected]> Co-authored-by: Mihir Dixit <[email protected]> Co-authored-by: David Jumani <[email protected]>
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
Implements #13564: adds an opt-in, per-route statistics capability to
TrafficPolicy.Operators can now set a custom prefix on the Envoy route so that per-route stats are emitted, giving a clear connection between Kubernetes resources and Envoy metrics. When set, Envoy emits stats under
vhost.<vhost>.route.<statPrefix>.*.What changed
spec.statPrefixonTrafficPolicy. Opt-in: unset means no per-route stat prefix is configured (no extra metrics cardinality).{{route_name}}– the route resource name{{route_namespace}}– the route resource namespace{{rule_name}}– the matched route rule name (empty if unnamed)Route(not theRouteAction), so it also applies to redirect/direct-response routes.Gateway) at admission.Validation
Patternonly admits stat-safe literal runs ([a-zA-Z0-9_%.-]) and well-formed{{ ... }}tokens referencing a supported variable, so stray/unmatched braces, unsupported variable names, and unsafe characters are rejected at admission.MaxLengthis 256.XValidation(CEL) rule restricts the field to HTTPRoute/GRPCRoute targets..-separated segments left by an empty variable (e.g. an unnamed rule) are dropped when resolving, so no doubled/trailing dots leak into stat names.Notes for reviewers
RuleNamefield was added toir.HttpRouteRuleMatchIRto carry the user-authored Gateway APIrule.name(the existingNameis a generated, per-match unique name). GRPCRoute rules convert into the same IR, so{{rule_name}}works for both.templates/dir is rendered as Go templates, so codegen (hack/generate.sh) escapes the literal{{ }}tokens in the generated CRD description as Helm string literals; they render back to the original text (verified viahelm lint/helm template). ThePatternuses escaped braces (\{\{) so it is left untouched.Change Type
/kind feature
Changelog