Skip to content

Commit b086308

Browse files
authored
feat: route stat name (#6310)
* rebase Signed-off-by: i.makarychev <[email protected]>
1 parent c9c7340 commit b086308

File tree

57 files changed

+1508
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1508
-22
lines changed

api/v1alpha1/backendtrafficpolicy_types.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,24 @@ type BackendTelemetry struct {
128128
//
129129
// +optional
130130
Tracing *Tracing `json:"tracing,omitempty"`
131+
// Metrics defines metrics configuration for the backend or Route.
132+
//
133+
// +optional
134+
Metrics *BackendMetrics `json:"metrics,omitempty"`
135+
}
136+
137+
type BackendMetrics struct {
138+
// RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
139+
// For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route
140+
// The supported operators for this pattern are:
141+
// %ROUTE_NAME%: name of Gateway API xRoute resource
142+
// %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
143+
// %ROUTE_KIND%: kind of Gateway API xRoute resource
144+
// Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
145+
// Disabled by default.
146+
//
147+
// +optional
148+
RouteStatName *string `json:"routeStatName,omitempty"`
131149
}
132150

133151
// ProtocolUpgradeConfig specifies the configuration for protocol upgrades.

api/v1alpha1/validation/envoyproxy_validate.go

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
2020
)
2121

22+
var statNameRegex = regexp.MustCompile("%[^%]*%")
23+
2224
// ValidateEnvoyProxy validates the provided EnvoyProxy.
2325
func ValidateEnvoyProxy(proxy *egv1a1.EnvoyProxy) error {
2426
var errs []error
@@ -213,8 +215,8 @@ func validateProxyTelemetry(spec *egv1a1.EnvoyProxySpec) []error {
213215
}
214216

215217
if spec.Telemetry.Metrics.ClusterStatName != nil {
216-
if clusterStatErrs := validateClusterStatName(*spec.Telemetry.Metrics.ClusterStatName); clusterStatErrs != nil {
217-
errs = append(errs, clusterStatErrs...)
218+
if clusterStatErr := ValidateClusterStatName(*spec.Telemetry.Metrics.ClusterStatName); clusterStatErr != nil {
219+
errs = append(errs, clusterStatErr)
218220
}
219221
}
220222
}
@@ -294,7 +296,22 @@ func validateFilterOrder(filterOrder []egv1a1.FilterPosition) error {
294296
return nil
295297
}
296298

297-
func validateClusterStatName(clusterStatName string) []error {
299+
func ValidateRouteStatName(routeStatName string) error {
300+
supportedOperators := map[string]bool{
301+
egv1a1.StatFormatterRouteName: true,
302+
egv1a1.StatFormatterRouteNamespace: true,
303+
egv1a1.StatFormatterRouteKind: true,
304+
egv1a1.StatFormatterRouteRuleName: true,
305+
}
306+
307+
if err := validateStatName(routeStatName, supportedOperators); err != nil {
308+
return fmt.Errorf("unable to configure Route Stat Name: %w", err)
309+
}
310+
311+
return nil
312+
}
313+
314+
func ValidateClusterStatName(clusterStatName string) error {
298315
supportedOperators := map[string]bool{
299316
egv1a1.StatFormatterRouteName: true,
300317
egv1a1.StatFormatterRouteNamespace: true,
@@ -304,15 +321,25 @@ func validateClusterStatName(clusterStatName string) []error {
304321
egv1a1.StatFormatterBackendRefs: true,
305322
}
306323

307-
var errs []error
308-
re := regexp.MustCompile("%[^%]*%")
309-
matches := re.FindAllString(clusterStatName, -1)
324+
if err := validateStatName(clusterStatName, supportedOperators); err != nil {
325+
return fmt.Errorf("unable to configure Cluster Stat Name: %w", err)
326+
}
327+
328+
return nil
329+
}
330+
331+
func validateStatName(statName string, supportedOperators map[string]bool) error {
332+
var unsupportedOperators []string
333+
matches := statNameRegex.FindAllString(statName, -1)
310334
for _, operator := range matches {
311335
if _, ok := supportedOperators[operator]; !ok {
312-
err := fmt.Errorf("unable to configure Cluster Stat Name with unsupported operator: %s", operator)
313-
errs = append(errs, err)
336+
unsupportedOperators = append(unsupportedOperators, operator)
314337
}
315338
}
316339

317-
return errs
340+
if len(unsupportedOperators) > 0 {
341+
return fmt.Errorf("unsupported operators: %v", unsupportedOperators)
342+
}
343+
344+
return nil
318345
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,6 +2265,22 @@ spec:
22652265
Telemetry configures the telemetry settings for the policy target (Gateway or xRoute).
22662266
This will override the telemetry settings in the EnvoyProxy resource.
22672267
properties:
2268+
metrics:
2269+
description: Metrics defines metrics configuration for the backend
2270+
or Route.
2271+
properties:
2272+
routeStatName:
2273+
description: |-
2274+
RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
2275+
For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route
2276+
The supported operators for this pattern are:
2277+
%ROUTE_NAME%: name of Gateway API xRoute resource
2278+
%ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
2279+
%ROUTE_KIND%: kind of Gateway API xRoute resource
2280+
Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
2281+
Disabled by default.
2282+
type: string
2283+
type: object
22682284
tracing:
22692285
description: Tracing configures the tracing settings for the backend
22702286
or HTTPRoute.

charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,22 @@ spec:
22642264
Telemetry configures the telemetry settings for the policy target (Gateway or xRoute).
22652265
This will override the telemetry settings in the EnvoyProxy resource.
22662266
properties:
2267+
metrics:
2268+
description: Metrics defines metrics configuration for the backend
2269+
or Route.
2270+
properties:
2271+
routeStatName:
2272+
description: |-
2273+
RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
2274+
For more details, see envoy docs: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-route
2275+
The supported operators for this pattern are:
2276+
%ROUTE_NAME%: name of Gateway API xRoute resource
2277+
%ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
2278+
%ROUTE_KIND%: kind of Gateway API xRoute resource
2279+
Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
2280+
Disabled by default.
2281+
type: string
2282+
type: object
22672283
tracing:
22682284
description: Tracing configures the tracing settings for the backend
22692285
or HTTPRoute.

internal/gatewayapi/backendtrafficpolicy.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
2222

2323
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
24+
egv1a1validation "github.com/envoyproxy/gateway/api/v1alpha1/validation"
2425
"github.com/envoyproxy/gateway/internal/gatewayapi/resource"
2526
"github.com/envoyproxy/gateway/internal/gatewayapi/status"
2627
"github.com/envoyproxy/gateway/internal/ir"
@@ -705,6 +706,11 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext,
705706
x *ir.Xds,
706707
policyTargetListener *gwapiv1.SectionName,
707708
) {
709+
routeStatName := ""
710+
if tf.Telemetry != nil && tf.Telemetry.Metrics != nil {
711+
routeStatName = ptr.Deref(tf.Telemetry.Metrics.RouteStatName, "")
712+
}
713+
708714
prefix := irRoutePrefix(route)
709715
for _, tcp := range x.TCP {
710716
// if listenerName is not nil, only apply to the specific listener
@@ -728,6 +734,7 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext,
728734
setIfNil(&r.Timeout, tf.Timeout)
729735
setIfNil(&r.BackendConnection, tf.BackendConnection)
730736
setIfNil(&r.DNS, tf.DNS)
737+
setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata))
731738
}
732739
}
733740
}
@@ -773,6 +780,7 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext,
773780
continue
774781
}
775782

783+
r.StatName = buildRouteStatName(routeStatName, r.Metadata)
776784
if errs != nil {
777785
// Return a 500 direct response
778786
r.DirectResponse = &ir.CustomResponse{
@@ -889,6 +897,11 @@ func (t *Translator) buildTrafficFeatures(policy *egv1a1.BackendTrafficPolicy, r
889897
errs = errors.Join(errs, err)
890898
}
891899

900+
if err = validateTelemetry(policy.Spec.Telemetry); err != nil {
901+
err = perr.WithMessage(err, "Telemetry")
902+
errs = errors.Join(errs, err)
903+
}
904+
892905
cp = buildCompression(policy.Spec.Compression, policy.Spec.Compressor)
893906
httpUpgrade = buildHTTPProtocolUpgradeConfig(policy.Spec.HTTPUpgrade)
894907

@@ -925,6 +938,11 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
925938
return errs
926939
}
927940

941+
routeStatName := ""
942+
if tf.Telemetry != nil && tf.Telemetry.Metrics != nil {
943+
routeStatName = ptr.Deref(tf.Telemetry.Metrics.RouteStatName, "")
944+
}
945+
928946
// Apply IR to all the routes within the specific Gateway
929947
// If the feature is already set, then skip it, since it must have
930948
// set by a policy attaching to the route
@@ -955,6 +973,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
955973
setIfNil(&r.TCPKeepalive, tf.TCPKeepalive)
956974
setIfNil(&r.Timeout, tf.Timeout)
957975
setIfNil(&r.DNS, tf.DNS)
976+
setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata))
958977
}
959978
}
960979

@@ -1002,6 +1021,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
10021021
continue
10031022
}
10041023

1024+
setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata))
10051025
if errs != nil {
10061026
// Return a 500 direct response
10071027
r.DirectResponse = &ir.CustomResponse{
@@ -1613,3 +1633,33 @@ func buildHTTPProtocolUpgradeConfig(cfgs []*egv1a1.ProtocolUpgradeConfig) []ir.H
16131633

16141634
return result
16151635
}
1636+
1637+
func validateTelemetry(telemetry *egv1a1.BackendTelemetry) error {
1638+
if telemetry == nil {
1639+
return nil
1640+
}
1641+
1642+
if telemetry.Metrics != nil && ptr.Deref(telemetry.Metrics.RouteStatName, "") != "" {
1643+
return egv1a1validation.ValidateRouteStatName(*telemetry.Metrics.RouteStatName)
1644+
}
1645+
1646+
return nil
1647+
}
1648+
1649+
func buildRouteStatName(routeStatName string, metadata *ir.ResourceMetadata) *string {
1650+
if routeStatName == "" || metadata == nil {
1651+
return nil
1652+
}
1653+
1654+
statName := strings.ReplaceAll(routeStatName, egv1a1.StatFormatterRouteName, metadata.Name)
1655+
statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteNamespace, metadata.Namespace)
1656+
statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteKind, metadata.Kind)
1657+
1658+
if metadata.SectionName == "" {
1659+
statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, "-")
1660+
} else {
1661+
statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, metadata.SectionName)
1662+
}
1663+
1664+
return &statName
1665+
}

internal/gatewayapi/route.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,7 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour
12561256
Settings: destSettings,
12571257
Metadata: buildResourceMetadata(tlsRoute, nil),
12581258
},
1259+
Metadata: buildResourceMetadata(tlsRoute, nil),
12591260
}
12601261
irListener.Routes = append(irListener.Routes, irRoute)
12611262

@@ -1554,9 +1555,9 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
15541555
Destination: &ir.RouteDestination{
15551556
Name: destName,
15561557
Settings: destSettings,
1557-
// tcpRoute Must have a single rule, so can use index 0.
15581558
Metadata: buildResourceMetadata(tcpRoute, tcpRoute.Spec.Rules[0].Name),
15591559
},
1560+
Metadata: buildResourceMetadata(tcpRoute, nil),
15601561
}
15611562

15621563
if irListener.TLS != nil {

0 commit comments

Comments
 (0)