diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go
index 967985426b..63ae9b5d5a 100644
--- a/api/v1alpha1/backendtrafficpolicy_types.go
+++ b/api/v1alpha1/backendtrafficpolicy_types.go
@@ -126,6 +126,24 @@ type BackendTelemetry struct {
//
// +optional
Tracing *Tracing `json:"tracing,omitempty"`
+ // Metrics defines metrics configuration for the backend or Route.
+ //
+ // +optional
+ Metrics *BackendMetrics `json:"metrics,omitempty"`
+}
+
+type BackendMetrics struct {
+ // RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
+ // 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
+ // The supported operators for this pattern are:
+ // %ROUTE_NAME%: name of Gateway API xRoute resource
+ // %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+ // %ROUTE_KIND%: kind of Gateway API xRoute resource
+ // Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
+ // Disabled by default.
+ //
+ // +optional
+ RouteStatName *string `json:"routeStatName,omitempty"`
}
// ProtocolUpgradeConfig specifies the configuration for protocol upgrades.
diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go
index 66230e4bda..6715a050a0 100644
--- a/api/v1alpha1/validation/envoyproxy_validate.go
+++ b/api/v1alpha1/validation/envoyproxy_validate.go
@@ -19,6 +19,8 @@ import (
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
)
+var statNameRegex = regexp.MustCompile("%[^%]*%")
+
// ValidateEnvoyProxy validates the provided EnvoyProxy.
func ValidateEnvoyProxy(proxy *egv1a1.EnvoyProxy) error {
var errs []error
@@ -213,8 +215,8 @@ func validateProxyTelemetry(spec *egv1a1.EnvoyProxySpec) []error {
}
if spec.Telemetry.Metrics.ClusterStatName != nil {
- if clusterStatErrs := validateClusterStatName(*spec.Telemetry.Metrics.ClusterStatName); clusterStatErrs != nil {
- errs = append(errs, clusterStatErrs...)
+ if clusterStatErr := ValidateClusterStatName(*spec.Telemetry.Metrics.ClusterStatName); clusterStatErr != nil {
+ errs = append(errs, clusterStatErr)
}
}
}
@@ -294,7 +296,22 @@ func validateFilterOrder(filterOrder []egv1a1.FilterPosition) error {
return nil
}
-func validateClusterStatName(clusterStatName string) []error {
+func ValidateRouteStatName(routeStatName string) error {
+ supportedOperators := map[string]bool{
+ egv1a1.StatFormatterRouteName: true,
+ egv1a1.StatFormatterRouteNamespace: true,
+ egv1a1.StatFormatterRouteKind: true,
+ egv1a1.StatFormatterRouteRuleName: true,
+ }
+
+ if err := validateStatName(routeStatName, supportedOperators); err != nil {
+ return fmt.Errorf("unable to configure Route Stat Name: %w", err)
+ }
+
+ return nil
+}
+
+func ValidateClusterStatName(clusterStatName string) error {
supportedOperators := map[string]bool{
egv1a1.StatFormatterRouteName: true,
egv1a1.StatFormatterRouteNamespace: true,
@@ -304,15 +321,25 @@ func validateClusterStatName(clusterStatName string) []error {
egv1a1.StatFormatterBackendRefs: true,
}
- var errs []error
- re := regexp.MustCompile("%[^%]*%")
- matches := re.FindAllString(clusterStatName, -1)
+ if err := validateStatName(clusterStatName, supportedOperators); err != nil {
+ return fmt.Errorf("unable to configure Cluster Stat Name: %w", err)
+ }
+
+ return nil
+}
+
+func validateStatName(statName string, supportedOperators map[string]bool) error {
+ var unsupportedOperators []string
+ matches := statNameRegex.FindAllString(statName, -1)
for _, operator := range matches {
if _, ok := supportedOperators[operator]; !ok {
- err := fmt.Errorf("unable to configure Cluster Stat Name with unsupported operator: %s", operator)
- errs = append(errs, err)
+ unsupportedOperators = append(unsupportedOperators, operator)
}
}
- return errs
+ if len(unsupportedOperators) > 0 {
+ return fmt.Errorf("unsupported operators: %v", unsupportedOperators)
+ }
+
+ return nil
}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 2dd26de206..bad9c6f58e 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -458,6 +458,26 @@ func (in *BackendList) DeepCopyObject() runtime.Object {
return nil
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *BackendMetrics) DeepCopyInto(out *BackendMetrics) {
+ *out = *in
+ if in.RouteStatName != nil {
+ in, out := &in.RouteStatName, &out.RouteStatName
+ *out = new(string)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendMetrics.
+func (in *BackendMetrics) DeepCopy() *BackendMetrics {
+ if in == nil {
+ return nil
+ }
+ out := new(BackendMetrics)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BackendRef) DeepCopyInto(out *BackendRef) {
*out = *in
@@ -612,6 +632,11 @@ func (in *BackendTelemetry) DeepCopyInto(out *BackendTelemetry) {
*out = new(Tracing)
(*in).DeepCopyInto(*out)
}
+ if in.Metrics != nil {
+ in, out := &in.Metrics, &out.Metrics
+ *out = new(BackendMetrics)
+ (*in).DeepCopyInto(*out)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTelemetry.
diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
index be726b9460..5ac85b0d8c 100644
--- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
+++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
@@ -2265,6 +2265,22 @@ spec:
Telemetry configures the telemetry settings for the policy target (Gateway or xRoute).
This will override the telemetry settings in the EnvoyProxy resource.
properties:
+ metrics:
+ description: Metrics defines metrics configuration for the backend
+ or Route.
+ properties:
+ routeStatName:
+ description: |-
+ RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
+ 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
+ The supported operators for this pattern are:
+ %ROUTE_NAME%: name of Gateway API xRoute resource
+ %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+ %ROUTE_KIND%: kind of Gateway API xRoute resource
+ Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
+ Disabled by default.
+ type: string
+ type: object
tracing:
description: Tracing configures the tracing settings for the backend
or HTTPRoute.
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
index f0fa3b569c..463c189bbb 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
@@ -2264,6 +2264,22 @@ spec:
Telemetry configures the telemetry settings for the policy target (Gateway or xRoute).
This will override the telemetry settings in the EnvoyProxy resource.
properties:
+ metrics:
+ description: Metrics defines metrics configuration for the backend
+ or Route.
+ properties:
+ routeStatName:
+ description: |-
+ RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
+ 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
+ The supported operators for this pattern are:
+ %ROUTE_NAME%: name of Gateway API xRoute resource
+ %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+ %ROUTE_KIND%: kind of Gateway API xRoute resource
+ Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
+ Disabled by default.
+ type: string
+ type: object
tracing:
description: Tracing configures the tracing settings for the backend
or HTTPRoute.
diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go
index a339d3b8c8..032b39bd84 100644
--- a/internal/gatewayapi/backendtrafficpolicy.go
+++ b/internal/gatewayapi/backendtrafficpolicy.go
@@ -21,6 +21,7 @@ import (
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
+ egv1a1validation "github.com/envoyproxy/gateway/api/v1alpha1/validation"
"github.com/envoyproxy/gateway/internal/gatewayapi/resource"
"github.com/envoyproxy/gateway/internal/gatewayapi/status"
"github.com/envoyproxy/gateway/internal/ir"
@@ -705,6 +706,11 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext,
x *ir.Xds,
policyTargetListener *gwapiv1.SectionName,
) {
+ routeStatName := ""
+ if tf.Telemetry != nil && tf.Telemetry.Metrics != nil {
+ routeStatName = ptr.Deref(tf.Telemetry.Metrics.RouteStatName, "")
+ }
+
prefix := irRoutePrefix(route)
for _, tcp := range x.TCP {
// if listenerName is not nil, only apply to the specific listener
@@ -728,6 +734,7 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext,
setIfNil(&r.Timeout, tf.Timeout)
setIfNil(&r.BackendConnection, tf.BackendConnection)
setIfNil(&r.DNS, tf.DNS)
+ setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata))
}
}
}
@@ -773,6 +780,7 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext,
continue
}
+ r.StatName = buildRouteStatName(routeStatName, r.Metadata)
if errs != nil {
// Return a 500 direct response
r.DirectResponse = &ir.CustomResponse{
@@ -889,6 +897,11 @@ func (t *Translator) buildTrafficFeatures(policy *egv1a1.BackendTrafficPolicy, r
errs = errors.Join(errs, err)
}
+ if err = validateTelemetry(policy.Spec.Telemetry); err != nil {
+ err = perr.WithMessage(err, "Telemetry")
+ errs = errors.Join(errs, err)
+ }
+
cp = buildCompression(policy.Spec.Compression, policy.Spec.Compressor)
httpUpgrade = buildHTTPProtocolUpgradeConfig(policy.Spec.HTTPUpgrade)
@@ -925,6 +938,11 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
return errs
}
+ routeStatName := ""
+ if tf.Telemetry != nil && tf.Telemetry.Metrics != nil {
+ routeStatName = ptr.Deref(tf.Telemetry.Metrics.RouteStatName, "")
+ }
+
// Apply IR to all the routes within the specific Gateway
// If the feature is already set, then skip it, since it must have
// set by a policy attaching to the route
@@ -955,6 +973,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
setIfNil(&r.TCPKeepalive, tf.TCPKeepalive)
setIfNil(&r.Timeout, tf.Timeout)
setIfNil(&r.DNS, tf.DNS)
+ setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata))
}
}
@@ -1002,6 +1021,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
continue
}
+ setIfNil(&r.StatName, buildRouteStatName(routeStatName, r.Metadata))
if errs != nil {
// Return a 500 direct response
r.DirectResponse = &ir.CustomResponse{
@@ -1613,3 +1633,33 @@ func buildHTTPProtocolUpgradeConfig(cfgs []*egv1a1.ProtocolUpgradeConfig) []ir.H
return result
}
+
+func validateTelemetry(telemetry *egv1a1.BackendTelemetry) error {
+ if telemetry == nil {
+ return nil
+ }
+
+ if telemetry.Metrics != nil && ptr.Deref(telemetry.Metrics.RouteStatName, "") != "" {
+ return egv1a1validation.ValidateRouteStatName(*telemetry.Metrics.RouteStatName)
+ }
+
+ return nil
+}
+
+func buildRouteStatName(routeStatName string, metadata *ir.ResourceMetadata) *string {
+ if routeStatName == "" || metadata == nil {
+ return nil
+ }
+
+ statName := strings.ReplaceAll(routeStatName, egv1a1.StatFormatterRouteName, metadata.Name)
+ statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteNamespace, metadata.Namespace)
+ statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteKind, metadata.Kind)
+
+ if metadata.SectionName == "" {
+ statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, "-")
+ } else {
+ statName = strings.ReplaceAll(statName, egv1a1.StatFormatterRouteRuleName, metadata.SectionName)
+ }
+
+ return &statName
+}
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index a8a20d4ed7..da384ca9de 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -1256,6 +1256,7 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour
Settings: destSettings,
Metadata: buildResourceMetadata(tlsRoute, nil),
},
+ Metadata: buildResourceMetadata(tlsRoute, nil),
}
irListener.Routes = append(irListener.Routes, irRoute)
@@ -1554,9 +1555,9 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
Destination: &ir.RouteDestination{
Name: destName,
Settings: destSettings,
- // tcpRoute Must have a single rule, so can use index 0.
Metadata: buildResourceMetadata(tcpRoute, tcpRoute.Spec.Rules[0].Name),
},
+ Metadata: buildResourceMetadata(tcpRoute, nil),
}
if irListener.TLS != nil {
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.in.yaml
new file mode 100644
index 0000000000..f97458e671
--- /dev/null
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.in.yaml
@@ -0,0 +1,118 @@
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ namespace: envoy-gateway
+ name: gateway-1
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - name: http
+ protocol: HTTP
+ port: 80
+ allowedRoutes:
+ namespaces:
+ from: All
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ namespace: envoy-gateway
+ name: gateway-2
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - name: http
+ protocol: HTTP
+ port: 80
+ allowedRoutes:
+ namespaces:
+ from: All
+grpcRoutes:
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+ kind: GRPCRoute
+ metadata:
+ namespace: default
+ name: grpcroute-1
+ spec:
+ parentRefs:
+ - namespace: envoy-gateway
+ name: gateway-1
+ sectionName: http
+ rules:
+ - backendRefs:
+ - name: service-1
+ port: 8080
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+ kind: GRPCRoute
+ metadata:
+ namespace: default
+ name: grpcroute-2
+ spec:
+ parentRefs:
+ - namespace: envoy-gateway
+ name: gateway-1
+ sectionName: http
+ rules:
+ - backendRefs:
+ - name: service-1
+ port: 8080
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: HTTPRoute
+ metadata:
+ namespace: default
+ name: httproute-1
+ spec:
+ hostnames:
+ - gateway.envoyproxy.io
+ parentRefs:
+ - namespace: envoy-gateway
+ name: gateway-2
+ sectionName: http
+ rules:
+ - matches:
+ - path:
+ value: "/test"
+ backendRefs:
+ - name: service-1
+ port: 8080
+backendTrafficPolicies:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: BackendTrafficPolicy
+ metadata:
+ namespace: envoy-gateway
+ name: policy-for-gateway
+ spec:
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: Gateway
+ name: gateway-1
+ telemetry:
+ metrics:
+ routeStatName: "%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_NAME%"
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: BackendTrafficPolicy
+ metadata:
+ namespace: default
+ name: policy-for-route
+ spec:
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ name: httproute-1
+ telemetry:
+ metrics:
+ routeStatName: "route=/test,kind=%ROUTE_KIND%,ns=%ROUTE_NAMESPACE%,name=%ROUTE_NAME%"
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: BackendTrafficPolicy
+ metadata:
+ namespace: default
+ name: policy-for-route-rewrite
+ spec:
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: GRPCRoute
+ name: grpcroute-2
+ telemetry:
+ metrics:
+ routeStatName: "route=rewrite"
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml
new file mode 100644
index 0000000000..3c6d55786f
--- /dev/null
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml
@@ -0,0 +1,496 @@
+backendTrafficPolicies:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: BackendTrafficPolicy
+ metadata:
+ name: policy-for-route
+ namespace: default
+ spec:
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ name: httproute-1
+ telemetry:
+ metrics:
+ routeStatName: route=/test,kind=%ROUTE_KIND%,ns=%ROUTE_NAMESPACE%,name=%ROUTE_NAME%
+ status:
+ ancestors:
+ - ancestorRef:
+ group: gateway.networking.k8s.io
+ kind: Gateway
+ name: gateway-2
+ namespace: envoy-gateway
+ sectionName: http
+ conditions:
+ - lastTransitionTime: null
+ message: Policy has been accepted.
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: BackendTrafficPolicy
+ metadata:
+ name: policy-for-route-rewrite
+ namespace: default
+ spec:
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: GRPCRoute
+ name: grpcroute-2
+ telemetry:
+ metrics:
+ routeStatName: route=rewrite
+ status:
+ ancestors:
+ - ancestorRef:
+ group: gateway.networking.k8s.io
+ kind: Gateway
+ name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+ conditions:
+ - lastTransitionTime: null
+ message: Policy has been accepted.
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: BackendTrafficPolicy
+ metadata:
+ name: policy-for-gateway
+ namespace: envoy-gateway
+ spec:
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: Gateway
+ name: gateway-1
+ telemetry:
+ metrics:
+ routeStatName: '%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_NAME%'
+ status:
+ ancestors:
+ - ancestorRef:
+ group: gateway.networking.k8s.io
+ kind: Gateway
+ name: gateway-1
+ namespace: envoy-gateway
+ conditions:
+ - lastTransitionTime: null
+ message: Policy has been accepted.
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: 'This policy is being overridden by other backendTrafficPolicies
+ for these routes: [default/grpcroute-2]'
+ reason: Overridden
+ status: "True"
+ type: Overridden
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ name: gateway-1
+ namespace: envoy-gateway
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - allowedRoutes:
+ namespaces:
+ from: All
+ name: http
+ port: 80
+ protocol: HTTP
+ status:
+ listeners:
+ - attachedRoutes: 2
+ conditions:
+ - lastTransitionTime: null
+ message: Sending translated listener configuration to the data plane
+ reason: Programmed
+ status: "True"
+ type: Programmed
+ - lastTransitionTime: null
+ message: Listener has been successfully translated
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Listener references have been resolved
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ name: http
+ supportedKinds:
+ - group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ - group: gateway.networking.k8s.io
+ kind: GRPCRoute
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ name: gateway-2
+ namespace: envoy-gateway
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - allowedRoutes:
+ namespaces:
+ from: All
+ name: http
+ port: 80
+ protocol: HTTP
+ status:
+ listeners:
+ - attachedRoutes: 1
+ conditions:
+ - lastTransitionTime: null
+ message: Sending translated listener configuration to the data plane
+ reason: Programmed
+ status: "True"
+ type: Programmed
+ - lastTransitionTime: null
+ message: Listener has been successfully translated
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Listener references have been resolved
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ name: http
+ supportedKinds:
+ - group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ - group: gateway.networking.k8s.io
+ kind: GRPCRoute
+grpcRoutes:
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+ kind: GRPCRoute
+ metadata:
+ name: grpcroute-1
+ namespace: default
+ spec:
+ parentRefs:
+ - name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+ rules:
+ - backendRefs:
+ - name: service-1
+ port: 8080
+ status:
+ parents:
+ - conditions:
+ - lastTransitionTime: null
+ message: Route is accepted
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Resolved all the Object references for the Route
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+ parentRef:
+ name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+ kind: GRPCRoute
+ metadata:
+ name: grpcroute-2
+ namespace: default
+ spec:
+ parentRefs:
+ - name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+ rules:
+ - backendRefs:
+ - name: service-1
+ port: 8080
+ status:
+ parents:
+ - conditions:
+ - lastTransitionTime: null
+ message: Route is accepted
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Resolved all the Object references for the Route
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+ parentRef:
+ name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: HTTPRoute
+ metadata:
+ name: httproute-1
+ namespace: default
+ spec:
+ hostnames:
+ - gateway.envoyproxy.io
+ parentRefs:
+ - name: gateway-2
+ namespace: envoy-gateway
+ sectionName: http
+ rules:
+ - backendRefs:
+ - name: service-1
+ port: 8080
+ matches:
+ - path:
+ value: /test
+ status:
+ parents:
+ - conditions:
+ - lastTransitionTime: null
+ message: Route is accepted
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Resolved all the Object references for the Route
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+ parentRef:
+ name: gateway-2
+ namespace: envoy-gateway
+ sectionName: http
+infraIR:
+ envoy-gateway/gateway-1:
+ proxy:
+ listeners:
+ - address: null
+ name: envoy-gateway/gateway-1/http
+ ports:
+ - containerPort: 10080
+ name: http-80
+ protocol: HTTP
+ servicePort: 80
+ metadata:
+ labels:
+ gateway.envoyproxy.io/owning-gateway-name: gateway-1
+ gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+ ownerReference:
+ kind: GatewayClass
+ name: envoy-gateway-class
+ name: envoy-gateway/gateway-1
+ namespace: envoy-gateway-system
+ envoy-gateway/gateway-2:
+ proxy:
+ listeners:
+ - address: null
+ name: envoy-gateway/gateway-2/http
+ ports:
+ - containerPort: 10080
+ name: http-80
+ protocol: HTTP
+ servicePort: 80
+ metadata:
+ labels:
+ gateway.envoyproxy.io/owning-gateway-name: gateway-2
+ gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+ ownerReference:
+ kind: GatewayClass
+ name: envoy-gateway-class
+ name: envoy-gateway/gateway-2
+ namespace: envoy-gateway-system
+xdsIR:
+ envoy-gateway/gateway-1:
+ accessLog:
+ json:
+ - path: /dev/stdout
+ globalResources:
+ proxyServiceCluster:
+ metadata:
+ name: envoy-envoy-gateway-gateway-1-196ae069
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-1
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.6.5.4
+ port: 8080
+ zone: zone1
+ metadata:
+ name: envoy-envoy-gateway-gateway-1-196ae069
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-1
+ protocol: TCP
+ http:
+ - address: 0.0.0.0
+ externalPort: 80
+ hostnames:
+ - '*'
+ isHTTP2: true
+ metadata:
+ kind: Gateway
+ name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+ name: envoy-gateway/gateway-1/http
+ path:
+ escapedSlashesAction: UnescapeAndRedirect
+ mergeSlashes: true
+ port: 10080
+ routes:
+ - destination:
+ metadata:
+ kind: GRPCRoute
+ name: grpcroute-1
+ namespace: default
+ name: grpcroute/default/grpcroute-1/rule/0
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.7.7.7
+ port: 8080
+ metadata:
+ name: service-1
+ namespace: default
+ sectionName: "8080"
+ name: grpcroute/default/grpcroute-1/rule/0/backend/0
+ protocol: GRPC
+ weight: 1
+ hostname: '*'
+ isHTTP2: true
+ metadata:
+ kind: GRPCRoute
+ name: grpcroute-1
+ namespace: default
+ name: grpcroute/default/grpcroute-1/rule/0/match/-1/*
+ statName: GRPCRoute/default/grpcroute-1/grpcroute-1
+ traffic:
+ telemetry:
+ metrics:
+ routeStatName: '%ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME%/%ROUTE_NAME%'
+ - destination:
+ metadata:
+ kind: GRPCRoute
+ name: grpcroute-2
+ namespace: default
+ name: grpcroute/default/grpcroute-2/rule/0
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.7.7.7
+ port: 8080
+ metadata:
+ name: service-1
+ namespace: default
+ sectionName: "8080"
+ name: grpcroute/default/grpcroute-2/rule/0/backend/0
+ protocol: GRPC
+ weight: 1
+ hostname: '*'
+ isHTTP2: true
+ metadata:
+ kind: GRPCRoute
+ name: grpcroute-2
+ namespace: default
+ name: grpcroute/default/grpcroute-2/rule/0/match/-1/*
+ statName: route=rewrite
+ traffic:
+ telemetry:
+ metrics:
+ routeStatName: route=rewrite
+ readyListener:
+ address: 0.0.0.0
+ ipFamily: IPv4
+ path: /ready
+ port: 19003
+ envoy-gateway/gateway-2:
+ accessLog:
+ json:
+ - path: /dev/stdout
+ globalResources:
+ proxyServiceCluster:
+ metadata:
+ name: envoy-envoy-gateway-gateway-2-4a0e4eb9
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-2
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.6.5.4
+ port: 8080
+ zone: zone1
+ metadata:
+ name: envoy-envoy-gateway-gateway-2-4a0e4eb9
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-2
+ protocol: TCP
+ http:
+ - address: 0.0.0.0
+ externalPort: 80
+ hostnames:
+ - '*'
+ isHTTP2: false
+ metadata:
+ kind: Gateway
+ name: gateway-2
+ namespace: envoy-gateway
+ sectionName: http
+ name: envoy-gateway/gateway-2/http
+ path:
+ escapedSlashesAction: UnescapeAndRedirect
+ mergeSlashes: true
+ port: 10080
+ routes:
+ - destination:
+ metadata:
+ kind: HTTPRoute
+ name: httproute-1
+ namespace: default
+ name: httproute/default/httproute-1/rule/0
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.7.7.7
+ port: 8080
+ metadata:
+ name: service-1
+ namespace: default
+ sectionName: "8080"
+ name: httproute/default/httproute-1/rule/0/backend/0
+ protocol: HTTP
+ weight: 1
+ hostname: gateway.envoyproxy.io
+ isHTTP2: false
+ metadata:
+ kind: HTTPRoute
+ name: httproute-1
+ namespace: default
+ name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
+ pathMatch:
+ distinct: false
+ name: ""
+ prefix: /test
+ statName: route=/test,kind=HTTPRoute,ns=default,name=httproute-1
+ traffic:
+ telemetry:
+ metrics:
+ routeStatName: route=/test,kind=%ROUTE_KIND%,ns=%ROUTE_NAMESPACE%,name=%ROUTE_NAME%
+ readyListener:
+ address: 0.0.0.0
+ ipFamily: IPv4
+ path: /ready
+ port: 19003
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml
index baec7d2e32..8f52dd299b 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml
@@ -317,6 +317,10 @@ xdsIR:
loadBalancer:
consistentHash:
sourceIP: true
+ metadata:
+ kind: TCPRoute
+ name: tls-app-1
+ namespace: default
name: tcproute/default/tls-app-1
proxyProtocol:
version: V2
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml
index 4200ea08f4..55a421e4b9 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml
@@ -389,6 +389,10 @@ xdsIR:
loadBalancer:
consistentHash:
sourceIP: true
+ metadata:
+ kind: TCPRoute
+ name: tcp-app-1
+ namespace: default
name: tcproute/default/tcp-app-1
proxyProtocol:
version: V2
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml
index bf50ae96ea..1a58c909c1 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-for-tcp-listeners.out.yaml
@@ -244,6 +244,10 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
tls:
terminate:
@@ -321,6 +325,10 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
tcpKeepalive:
idleTime: 1200
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml
index 588f2d27b1..0e45ef5ca2 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml
@@ -1008,6 +1008,10 @@ xdsIR:
name: tcproute/default/tcp-route-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcp-route-1
+ namespace: default
name: tcproute/default/tcp-route-1
default/gateway-2:
accessLog:
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml
index ee8d3f2784..a158e59366 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification-expired-crl.out.yaml
@@ -713,6 +713,10 @@ xdsIR:
name: tcproute/envoy-gateway/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: envoy-gateway
name: tcproute/envoy-gateway/tcproute-1
tls:
terminate:
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml
index e8ba0842d9..e15b3cd957 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-client-verification.out.yaml
@@ -693,6 +693,10 @@ xdsIR:
name: tcproute-1
namespace: envoy-gateway
name: tcproute/envoy-gateway/tcproute-1/rule/-1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: envoy-gateway
name: tcproute/envoy-gateway/tcproute-1
tls:
terminate:
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml
index c4b3ff1fd0..48528439b1 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-proxyprotocol-legacy-mixed.out.yaml
@@ -327,6 +327,10 @@ xdsIR:
name: tcproute-1
namespace: envoy-gateway
name: tcproute/envoy-gateway/tcproute-1/rule/-1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: envoy-gateway
name: tcproute/envoy-gateway/tcproute-1
envoy-gateway/gateway-new-api-only:
accessLog:
diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml
index 0504b17b9b..214a30e219 100644
--- a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml
@@ -304,6 +304,10 @@ xdsIR:
name: envoy-gateway
namespace: envoy-gateway
name: tcproute/envoy-gateway/envoy-gateway/rule/-1
+ metadata:
+ kind: TCPRoute
+ name: envoy-gateway
+ namespace: envoy-gateway
name: tcproute/envoy-gateway/envoy-gateway
tls:
terminate:
diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml
index 5a34dbf42c..e615766d31 100644
--- a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml
@@ -303,6 +303,10 @@ xdsIR:
name: envoy-gateway
namespace: envoy-gateway
name: tcproute/envoy-gateway/envoy-gateway/rule/-1
+ metadata:
+ kind: TCPRoute
+ name: envoy-gateway
+ namespace: envoy-gateway
name: tcproute/envoy-gateway/envoy-gateway
tls:
terminate:
diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml
index 224f3037d1..9e05786f2e 100644
--- a/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml
@@ -376,6 +376,10 @@ xdsIR:
sni: example.com
useSystemTrustStore: true
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: envoy-gateway
+ namespace: envoy-gateway
name: tcproute/envoy-gateway/envoy-gateway
tls:
terminate:
diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml
index ea35dd7b3f..5ff656e57e 100644
--- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml
@@ -133,4 +133,8 @@ xdsIR:
name: tcproute-1
namespace: default
name: tcproute/default/tcproute-1/rule/-1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml
index 5f2266f888..c766ddd253 100644
--- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-multiple-backends.out.yaml
@@ -160,4 +160,8 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/1
protocol: TCP
weight: 50
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml
index ac36a5006a..87b3b8f300 100644
--- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml
@@ -277,6 +277,10 @@ xdsIR:
name: tlsroute/default/tlsroute-1/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-1
+ namespace: default
name: tlsroute/default/tlsroute-1
tls:
inspector:
diff --git a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml
index ea02c5a35a..5328580cf8 100644
--- a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-tcproutes.out.yaml
@@ -175,4 +175,8 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml
index e999f83660..a7c87a8580 100644
--- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml
@@ -169,4 +169,8 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml
index d050c9e785..35d815b18e 100644
--- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml
@@ -262,4 +262,8 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml
index e8910b4d62..d7bb13d864 100644
--- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-with-sectionname.out.yaml
@@ -213,6 +213,10 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
- address: 0.0.0.0
externalPort: 163
@@ -242,4 +246,8 @@ xdsIR:
name: tcproute/default/tcproute-2/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-2
+ namespace: default
name: tcproute/default/tcproute-2
diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml
index 5010701ecc..d096feae49 100644
--- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-tcproutes-without-sectionname.out.yaml
@@ -209,6 +209,10 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
- address: 0.0.0.0
externalPort: 162
@@ -238,4 +242,8 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml
index 44c12650cf..673ae28de1 100644
--- a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml
+++ b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml
@@ -219,6 +219,10 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
tls:
terminate:
@@ -261,6 +265,10 @@ xdsIR:
name: tcproute/default/tcproute-2/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-2
+ namespace: default
name: tcproute/default/tcproute-2
tls:
inspector:
diff --git a/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml b/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml
index 483e399825..8cc3269631 100644
--- a/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml
+++ b/internal/gatewayapi/testdata/tcproute-rule-with-multiple-backends-and-zero-weights.out.yaml
@@ -177,4 +177,8 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/2
protocol: TCP
weight: 3
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml b/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml
index 36479a2d7b..f13c4c29b6 100644
--- a/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml
+++ b/internal/gatewayapi/testdata/tcproute-securitypolicy-with-authorization-client-cidr.out.yaml
@@ -664,6 +664,10 @@ xdsIR:
name: tcproute/default/tcpr-app-mixed/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcpr-app-mixed
+ namespace: default
name: tcproute/default/tcpr-app-mixed
envoy-gateway/gateway-tcp:
accessLog:
@@ -734,6 +738,10 @@ xdsIR:
name: tcproute/default/tcpr-app-foo/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcpr-app-foo
+ namespace: default
name: tcproute/default/tcpr-app-foo
- address: 0.0.0.0
externalPort: 8089
@@ -775,4 +783,8 @@ xdsIR:
name: tcproute/default/tcpr-app-bar/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcpr-app-bar
+ namespace: default
name: tcproute/default/tcpr-app-bar
diff --git a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
index b249e08e79..67fa72d926 100644
--- a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
+++ b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
@@ -166,4 +166,8 @@ xdsIR:
name: tcproute/default/tcproute-1/rule/-1/backend/0
protocol: TCP
weight: 1
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml b/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml
index a8fe5b6f6a..01bdeae294 100644
--- a/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml
+++ b/internal/gatewayapi/testdata/tlsroute-attaching-to-gateway.out.yaml
@@ -148,6 +148,10 @@ xdsIR:
name: tlsroute/default/tlsroute-1/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-1
+ namespace: default
name: tlsroute/default/tlsroute-1
tls:
inspector:
diff --git a/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml b/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml
index 0321c3838e..b33107517a 100644
--- a/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml
+++ b/internal/gatewayapi/testdata/tlsroute-multiple.out.yaml
@@ -181,6 +181,10 @@ xdsIR:
name: tlsroute/default/tlsroute-1/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-1
+ namespace: default
name: tlsroute/default/tlsroute-1
tls:
inspector:
@@ -204,6 +208,10 @@ xdsIR:
name: tlsroute/default/tlsroute-2/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-2
+ namespace: default
name: tlsroute/default/tlsroute-2
tls:
inspector:
diff --git a/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml
index 169a573168..72bf40abfd 100644
--- a/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml
+++ b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml
@@ -167,6 +167,10 @@ xdsIR:
name: tlsroute/default/tlsroute-1/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-1
+ namespace: default
name: tlsroute/default/tlsroute-1
tls:
inspector:
diff --git a/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml
index f97c452239..e11ea1a209 100644
--- a/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml
+++ b/internal/gatewayapi/testdata/tlsroute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml
@@ -150,6 +150,10 @@ xdsIR:
name: tlsroute/default/tlsroute-1/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-1
+ namespace: default
name: tlsroute/default/tlsroute-1
tls:
inspector:
diff --git a/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml
index 1a74865afd..efe46b743c 100644
--- a/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml
+++ b/internal/gatewayapi/testdata/tlsroute-with-empty-hostname.out.yaml
@@ -147,6 +147,10 @@ xdsIR:
name: tlsroute/default/tlsroute-1/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-1
+ namespace: default
name: tlsroute/default/tlsroute-1
tls:
inspector:
diff --git a/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml
index 91e837f19f..216140209d 100644
--- a/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml
+++ b/internal/gatewayapi/testdata/tlsroute-with-empty-listener-hostname.out.yaml
@@ -149,6 +149,10 @@ xdsIR:
name: tlsroute/default/tlsroute-1/rule/-1/backend/0
protocol: HTTPS
weight: 1
+ metadata:
+ kind: TLSRoute
+ name: tlsroute-1
+ namespace: default
name: tlsroute/default/tlsroute-1
tls:
inspector:
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 2e801c4dec..bc4f6175a3 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -766,6 +766,8 @@ type HTTPClientTimeout struct {
type HTTPRoute struct {
// Name of the HTTPRoute
Name string `json:"name" yaml:"name"`
+ // StatName is the name of the route used for statistics and metrics.
+ StatName *string `json:"statName,omitempty" yaml:"statName,omitempty"`
// Hostname that the route matches against
Hostname string `json:"hostname" yaml:"hostname,omitempty"`
// IsHTTP2 is set if the route is configured to serve HTTP2 traffic
@@ -2038,6 +2040,8 @@ type TCPListener struct {
type TCPRoute struct {
// Name of the TCPRoute.
Name string `json:"name" yaml:"name"`
+ // StatName is the name of the route used for statistics and metrics.
+ StatName *string `json:"statName,omitempty" yaml:"statName,omitempty"`
// TLS holds information for configuring TLS on a listener
TLS *TLS `json:"tls,omitempty" yaml:"tls,omitempty"`
// Destinations associated with TCP traffic to the service.
@@ -2054,6 +2058,8 @@ type TCPRoute struct {
HealthCheck *HealthCheck `json:"healthCheck,omitempty" yaml:"healthCheck,omitempty"`
// Proxy Protocol Settings
ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty"`
+ // Metadata is used to enrich envoy route metadata with user and provider-specific information
+ Metadata *ResourceMetadata `json:"metadata,omitempty" yaml:"metadata,omitempty"`
// settings of upstream connection
BackendConnection *BackendConnection `json:"backendConnection,omitempty" yaml:"backendConnection,omitempty"`
// Preconnect configures preconnecting to upstream endpoints
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index f1e4d5addc..8870551a59 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -1795,6 +1795,11 @@ func (in *HTTPPathModifier) DeepCopy() *HTTPPathModifier {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
*out = *in
+ if in.StatName != nil {
+ in, out := &in.StatName, &out.StatName
+ *out = new(string)
+ **out = **in
+ }
if in.PathMatch != nil {
in, out := &in.PathMatch, &out.PathMatch
*out = new(StringMatch)
@@ -3745,6 +3750,11 @@ func (in *TCPListener) DeepCopy() *TCPListener {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TCPRoute) DeepCopyInto(out *TCPRoute) {
*out = *in
+ if in.StatName != nil {
+ in, out := &in.StatName, &out.StatName
+ *out = new(string)
+ **out = **in
+ }
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(TLS)
@@ -3785,6 +3795,11 @@ func (in *TCPRoute) DeepCopyInto(out *TCPRoute) {
*out = new(ProxyProtocol)
**out = **in
}
+ if in.Metadata != nil {
+ in, out := &in.Metadata, &out.Metadata
+ *out = new(ResourceMetadata)
+ (*in).DeepCopyInto(*out)
+ }
if in.BackendConnection != nil {
in, out := &in.BackendConnection, &out.BackendConnection
*out = new(BackendConnection)
diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go
index 9ace0038c4..896306b5de 100644
--- a/internal/xds/translator/listener.go
+++ b/internal/xds/translator/listener.go
@@ -629,17 +629,20 @@ func (t *Translator) addXdsTCPFilterChain(
isTLSPassthrough := irRoute.TLS != nil && irRoute.TLS.TLSInspectorConfig != nil
isTLSTerminate := irRoute.TLS != nil && irRoute.TLS.Terminate != nil
- statPrefix := "tcp"
- if isTLSPassthrough {
- statPrefix = "tls-passthrough"
- }
+ statPrefix := ptr.Deref(irRoute.StatName, "")
+ if statPrefix == "" {
+ statPrefix = "tcp"
+ if isTLSPassthrough {
+ statPrefix = "tls-passthrough"
+ }
- if isTLSTerminate {
- statPrefix = "tls-terminate"
- }
+ if isTLSTerminate {
+ statPrefix = "tls-terminate"
+ }
- // Append port to the statPrefix.
- statPrefix = strings.Join([]string{statPrefix, strconv.Itoa(int(xdsListener.Address.GetSocketAddress().GetPortValue()))}, "-")
+ // Append port to the statPrefix.
+ statPrefix = strings.Join([]string{statPrefix, strconv.Itoa(int(xdsListener.Address.GetSocketAddress().GetPortValue()))}, "-")
+ }
filterChain, err := buildTCPFilterChain(
irRoute,
diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go
index c255e5f01f..350c169adb 100644
--- a/internal/xds/translator/route.go
+++ b/internal/xds/translator/route.go
@@ -20,6 +20,7 @@ import (
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/wrapperspb"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/utils/ptr"
"github.com/envoyproxy/gateway/internal/ir"
"github.com/envoyproxy/gateway/internal/utils/proto"
@@ -140,6 +141,9 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute, httpListener *ir.HTTPListener) (*rou
}
}
+ // Metrics
+ router.StatPrefix = ptr.Deref(httpRoute.StatName, "")
+
// Add per route filter configs to the route, if needed.
if err := patchRouteWithPerRouteConfig(router, httpRoute, httpListener); err != nil {
return nil, err
diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-metrics-stat.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-metrics-stat.yaml
new file mode 100644
index 0000000000..83c8ea3153
--- /dev/null
+++ b/internal/xds/translator/testdata/in/xds-ir/http-route-metrics-stat.yaml
@@ -0,0 +1,74 @@
+http:
+- name: "first-listener"
+ address: "::"
+ port: 10080
+ hostnames:
+ - "*"
+ path:
+ mergeSlashes: true
+ escapedSlashesAction: UnescapeAndRedirect
+ routes:
+ - name: "first-route"
+ metadata:
+ kind: HTTPRoute
+ name: httproute-1
+ namespace: default
+ pathMatch:
+ prefix: "/first/"
+ statName: "route=/first,kind=HTTPRoute,ns=default,name=httproute-1"
+ hostname: "*"
+ destination:
+ name: "first-route-dest"
+ settings:
+ - endpoints:
+ - host: "1.1.1.1"
+ port: 50001
+ weight: 20
+ name: "first-route-dest/backend/0"
+ - endpoints:
+ - host: "2.2.2.2"
+ port: 50002
+ weight: 40
+ name: "first-route-dest/backend/1"
+ - endpoints:
+ - host: "3.3.3.3"
+ port: 50003
+ weight: 20
+ name: "first-route-dest/backend/2"
+ - endpoints:
+ - host: "4.4.4.4"
+ port: 50004
+ weight: 20
+ name: "first-route-dest/backend/3"
+ - name: "second-route"
+ hostname: "*"
+ metadata:
+ kind: HTTPRoute
+ name: httproute-2
+ namespace: default
+ pathMatch:
+ prefix: "/second/"
+ statName: "route=/second,kind=HTTPRoute,ns=default,name=httproute-2"
+ destination:
+ name: "second-route-dest"
+ settings:
+ - endpoints:
+ - host: "1.1.1.1"
+ port: 50001
+ weight: 20
+ name: "second-route-dest/backend/0"
+ - endpoints:
+ - host: "2.2.2.2"
+ port: 50002
+ weight: 40
+ name: "second-route-dest/backend/1"
+ - endpoints:
+ - host: "3.3.3.3"
+ port: 50003
+ weight: 20
+ name: "second-route-dest/backend/2"
+ - endpoints:
+ - host: "4.4.4.4"
+ port: 50004
+ weight: 20
+ name: "second-route-dest/backend/3"
diff --git a/internal/xds/translator/testdata/in/xds-ir/tcp-route-metrics-stat.yaml b/internal/xds/translator/testdata/in/xds-ir/tcp-route-metrics-stat.yaml
new file mode 100644
index 0000000000..3f5183dadd
--- /dev/null
+++ b/internal/xds/translator/testdata/in/xds-ir/tcp-route-metrics-stat.yaml
@@ -0,0 +1,20 @@
+tcp:
+- name: "tcp-listener-simple"
+ address: "::"
+ port: 10080
+ routes:
+ - name: "tcp-route-simple"
+ metadata:
+ kind: TCPRoute
+ name: tcproute-1
+ namespace: default
+ destination:
+ name: "tcp-route-simple-dest"
+ settings:
+ - endpoints:
+ - host: "1.2.3.4"
+ port: 50000
+ - host: "5.6.7.8"
+ port: 50001
+ name: "tcp-route-simple-dest/backend/0"
+ statName: "route=/test,kind=TCPRoute,ns=default,name=tcproute-1"
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.clusters.yaml
new file mode 100644
index 0000000000..7e9eb80719
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.clusters.yaml
@@ -0,0 +1,48 @@
+- circuitBreakers:
+ thresholds:
+ - maxRetries: 1024
+ commonLbConfig: {}
+ connectTimeout: 10s
+ dnsLookupFamily: V4_PREFERRED
+ edsClusterConfig:
+ edsConfig:
+ ads: {}
+ resourceApiVersion: V3
+ serviceName: first-route-dest
+ ignoreHealthOnHostRemoval: true
+ lbPolicy: LEAST_REQUEST
+ loadBalancingPolicy:
+ policies:
+ - typedExtensionConfig:
+ name: envoy.load_balancing_policies.least_request
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
+ localityLbConfig:
+ localityWeightedLbConfig: {}
+ name: first-route-dest
+ perConnectionBufferLimitBytes: 32768
+ type: EDS
+- circuitBreakers:
+ thresholds:
+ - maxRetries: 1024
+ commonLbConfig: {}
+ connectTimeout: 10s
+ dnsLookupFamily: V4_PREFERRED
+ edsClusterConfig:
+ edsConfig:
+ ads: {}
+ resourceApiVersion: V3
+ serviceName: second-route-dest
+ ignoreHealthOnHostRemoval: true
+ lbPolicy: LEAST_REQUEST
+ loadBalancingPolicy:
+ policies:
+ - typedExtensionConfig:
+ name: envoy.load_balancing_policies.least_request
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
+ localityLbConfig:
+ localityWeightedLbConfig: {}
+ name: second-route-dest
+ perConnectionBufferLimitBytes: 32768
+ type: EDS
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.endpoints.yaml
new file mode 100644
index 0000000000..7e9e33dae5
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.endpoints.yaml
@@ -0,0 +1,84 @@
+- clusterName: first-route-dest
+ endpoints:
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 1.1.1.1
+ portValue: 50001
+ loadBalancingWeight: 1
+ loadBalancingWeight: 20
+ locality:
+ region: first-route-dest/backend/0
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 2.2.2.2
+ portValue: 50002
+ loadBalancingWeight: 1
+ loadBalancingWeight: 40
+ locality:
+ region: first-route-dest/backend/1
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 3.3.3.3
+ portValue: 50003
+ loadBalancingWeight: 1
+ loadBalancingWeight: 20
+ locality:
+ region: first-route-dest/backend/2
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 4.4.4.4
+ portValue: 50004
+ loadBalancingWeight: 1
+ loadBalancingWeight: 20
+ locality:
+ region: first-route-dest/backend/3
+- clusterName: second-route-dest
+ endpoints:
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 1.1.1.1
+ portValue: 50001
+ loadBalancingWeight: 1
+ loadBalancingWeight: 20
+ locality:
+ region: second-route-dest/backend/0
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 2.2.2.2
+ portValue: 50002
+ loadBalancingWeight: 1
+ loadBalancingWeight: 40
+ locality:
+ region: second-route-dest/backend/1
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 3.3.3.3
+ portValue: 50003
+ loadBalancingWeight: 1
+ loadBalancingWeight: 20
+ locality:
+ region: second-route-dest/backend/2
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 4.4.4.4
+ portValue: 50004
+ loadBalancingWeight: 1
+ loadBalancingWeight: 20
+ locality:
+ region: second-route-dest/backend/3
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.listeners.yaml
new file mode 100644
index 0000000000..5dd5e46e3c
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.listeners.yaml
@@ -0,0 +1,35 @@
+- address:
+ socketAddress:
+ address: '::'
+ portValue: 10080
+ defaultFilterChain:
+ filters:
+ - name: envoy.filters.network.http_connection_manager
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+ commonHttpProtocolOptions:
+ headersWithUnderscoresAction: REJECT_REQUEST
+ http2ProtocolOptions:
+ initialConnectionWindowSize: 1048576
+ initialStreamWindowSize: 65536
+ maxConcurrentStreams: 100
+ httpFilters:
+ - name: envoy.filters.http.router
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+ suppressEnvoyHeaders: true
+ mergeSlashes: true
+ normalizePath: true
+ pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT
+ rds:
+ configSource:
+ ads: {}
+ resourceApiVersion: V3
+ routeConfigName: first-listener
+ serverHeaderTransformation: PASS_THROUGH
+ statPrefix: http-10080
+ useRemoteAddress: true
+ name: first-listener
+ maxConnectionsToAcceptPerSocketEvent: 1
+ name: first-listener
+ perConnectionBufferLimitBytes: 32768
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.routes.yaml
new file mode 100644
index 0000000000..c032a95046
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-metrics-stat.routes.yaml
@@ -0,0 +1,37 @@
+- ignorePortInHostMatching: true
+ name: first-listener
+ virtualHosts:
+ - domains:
+ - '*'
+ name: first-listener/*
+ routes:
+ - match:
+ pathSeparatedPrefix: /first
+ metadata:
+ filterMetadata:
+ envoy-gateway:
+ resources:
+ - kind: HTTPRoute
+ name: httproute-1
+ namespace: default
+ name: first-route
+ route:
+ cluster: first-route-dest
+ upgradeConfigs:
+ - upgradeType: websocket
+ statPrefix: route=/first,kind=HTTPRoute,ns=default,name=httproute-1
+ - match:
+ pathSeparatedPrefix: /second
+ metadata:
+ filterMetadata:
+ envoy-gateway:
+ resources:
+ - kind: HTTPRoute
+ name: httproute-2
+ namespace: default
+ name: second-route
+ route:
+ cluster: second-route-dest
+ upgradeConfigs:
+ - upgradeType: websocket
+ statPrefix: route=/second,kind=HTTPRoute,ns=default,name=httproute-2
diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.clusters.yaml
new file mode 100644
index 0000000000..b66d2ea80c
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.clusters.yaml
@@ -0,0 +1,24 @@
+- circuitBreakers:
+ thresholds:
+ - maxRetries: 1024
+ commonLbConfig: {}
+ connectTimeout: 10s
+ dnsLookupFamily: V4_PREFERRED
+ edsClusterConfig:
+ edsConfig:
+ ads: {}
+ resourceApiVersion: V3
+ serviceName: tcp-route-simple-dest
+ ignoreHealthOnHostRemoval: true
+ lbPolicy: LEAST_REQUEST
+ loadBalancingPolicy:
+ policies:
+ - typedExtensionConfig:
+ name: envoy.load_balancing_policies.least_request
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
+ localityLbConfig:
+ localityWeightedLbConfig: {}
+ name: tcp-route-simple-dest
+ perConnectionBufferLimitBytes: 32768
+ type: EDS
diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.endpoints.yaml
new file mode 100644
index 0000000000..7eb06a08f4
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.endpoints.yaml
@@ -0,0 +1,18 @@
+- clusterName: tcp-route-simple-dest
+ endpoints:
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 1.2.3.4
+ portValue: 50000
+ loadBalancingWeight: 1
+ - endpoint:
+ address:
+ socketAddress:
+ address: 5.6.7.8
+ portValue: 50001
+ loadBalancingWeight: 1
+ loadBalancingWeight: 1
+ locality:
+ region: tcp-route-simple-dest/backend/0
diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.listeners.yaml
new file mode 100644
index 0000000000..388ebd6088
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.listeners.yaml
@@ -0,0 +1,15 @@
+- address:
+ socketAddress:
+ address: '::'
+ portValue: 10080
+ filterChains:
+ - filters:
+ - name: envoy.filters.network.tcp_proxy
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
+ cluster: tcp-route-simple-dest
+ statPrefix: route=/test,kind=TCPRoute,ns=default,name=tcproute-1
+ name: tcp-route-simple
+ maxConnectionsToAcceptPerSocketEvent: 1
+ name: tcp-listener-simple
+ perConnectionBufferLimitBytes: 32768
diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.routes.yaml
new file mode 100644
index 0000000000..fe51488c70
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-metrics-stat.routes.yaml
@@ -0,0 +1 @@
+[]
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 1d1086fb7d..00ba1403e4 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -368,6 +368,20 @@ _Appears in:_
| `zone` | _string_ | false | | Zone defines the service zone of the backend endpoint. |
+#### BackendMetrics
+
+
+
+
+
+_Appears in:_
+- [BackendTelemetry](#backendtelemetry)
+
+| Field | Type | Required | Default | Description |
+| --- | --- | --- | --- | --- |
+| `routeStatName` | _string_ | false | | RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
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
The supported operators for this pattern are:
%ROUTE_NAME%: name of Gateway API xRoute resource
%ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
%ROUTE_KIND%: kind of Gateway API xRoute resource
Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
Disabled by default. |
+
+
#### BackendRef
@@ -478,6 +492,7 @@ _Appears in:_
| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `tracing` | _[Tracing](#tracing)_ | false | | Tracing configures the tracing settings for the backend or HTTPRoute. |
+| `metrics` | _[BackendMetrics](#backendmetrics)_ | false | | Metrics defines metrics configuration for the backend or Route. |
#### BackendTrafficPolicy
diff --git a/test/e2e/testdata/httproute-metrics-stat.yaml b/test/e2e/testdata/httproute-metrics-stat.yaml
new file mode 100644
index 0000000000..678ef0abcd
--- /dev/null
+++ b/test/e2e/testdata/httproute-metrics-stat.yaml
@@ -0,0 +1,31 @@
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: http-route-stat-name
+ namespace: gateway-conformance-infra
+spec:
+ parentRefs:
+ - name: same-namespace
+ rules:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /foo
+ backendRefs:
+ - name: infra-backend-v1
+ port: 8080
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+ name: http-route-stat-name
+ namespace: gateway-conformance-infra
+spec:
+ targetRefs:
+ - group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ name: http-route-stat-name
+ telemetry:
+ metrics:
+ routeStatName: "%ROUTE_NAMESPACE%/%ROUTE_NAME%"
diff --git a/test/e2e/testdata/tcproute-metrics-stat.yaml b/test/e2e/testdata/tcproute-metrics-stat.yaml
new file mode 100644
index 0000000000..553901bfd5
--- /dev/null
+++ b/test/e2e/testdata/tcproute-metrics-stat.yaml
@@ -0,0 +1,42 @@
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: Gateway
+metadata:
+ name: tcp-stat-name-backend-gateway
+ namespace: gateway-conformance-infra
+spec:
+ gatewayClassName: "{GATEWAY_CLASS_NAME}"
+ listeners:
+ - name: ip
+ protocol: TCP
+ port: 8080
+ allowedRoutes:
+ kinds:
+ - kind: TCPRoute
+---
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: TCPRoute
+metadata:
+ name: tcp-route-stat-name
+ namespace: gateway-conformance-infra
+spec:
+ parentRefs:
+ - name: tcp-stat-name-backend-gateway
+ sectionName: ip
+ rules:
+ - backendRefs:
+ - name: infra-backend-v1
+ port: 8080
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+ name: tcp-route-stat-name
+ namespace: gateway-conformance-infra
+spec:
+ targetRefs:
+ - group: gateway.networking.k8s.io
+ kind: TCPRoute
+ name: tcp-route-stat-name
+ telemetry:
+ metrics:
+ routeStatName: "%ROUTE_NAMESPACE%/%ROUTE_NAME%"
diff --git a/test/e2e/tests/stat_name.go b/test/e2e/tests/stat_name.go
index 9012c2099b..754b2476c8 100644
--- a/test/e2e/tests/stat_name.go
+++ b/test/e2e/tests/stat_name.go
@@ -25,11 +25,11 @@ import (
)
func init() {
- ConformanceTests = append(ConformanceTests, StatNameTest)
+ ConformanceTests = append(ConformanceTests, ClusterStatNameTest, HTTPRouteStatNameTest, TCPRouteStatNameTest)
}
-var StatNameTest = suite.ConformanceTest{
- ShortName: "StatName",
+var ClusterStatNameTest = suite.ConformanceTest{
+ ShortName: "ClusterStatName",
Description: "Make sure metric is working",
Manifests: []string{"testdata/envoyproxy-stat-name.yaml"},
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
@@ -85,3 +85,78 @@ var StatNameTest = suite.ConformanceTest{
})
},
}
+
+var HTTPRouteStatNameTest = suite.ConformanceTest{
+ ShortName: "HTTPRouteStatNameTest",
+ Description: "Make sure per http route metrics is working",
+ Manifests: []string{"testdata/httproute-metrics-stat.yaml"},
+ Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+ ns := "gateway-conformance-infra"
+ routeNN := types.NamespacedName{Name: "http-route-stat-name", Namespace: ns}
+ gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
+ gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+ t.Run("prometheus", func(t *testing.T) {
+ expectedResponse := httputils.ExpectedResponse{
+ Request: httputils.Request{
+ Path: "/foo",
+ },
+ Response: httputils.Response{
+ StatusCode: 200,
+ },
+ Namespace: ns,
+ }
+ // make sure listener is ready
+ httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+ verifyMetrics(t, suite, `envoy_vhost_route_upstream_rq{envoy_route="gateway-conformance-infra/http-route-stat-name"}`)
+ })
+ },
+}
+
+var TCPRouteStatNameTest = suite.ConformanceTest{
+ ShortName: "TCPRouteStatNameTest",
+ Description: "Make sure per tcp route metrics is working",
+ Manifests: []string{"testdata/tcproute-metrics-stat.yaml"},
+ Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+ ns := "gateway-conformance-infra"
+ routeNN := types.NamespacedName{Name: "tcp-route-stat-name", Namespace: ns}
+ gwNN := types.NamespacedName{Name: "tcp-stat-name-backend-gateway", Namespace: ns}
+ gwAddr := GatewayAndTCPRoutesMustBeAccepted(t, suite.Client, &suite.TimeoutConfig, suite.ControllerName, NewGatewayRef(gwNN), routeNN)
+
+ t.Run("prometheus", func(t *testing.T) {
+ expectedResponse := httputils.ExpectedResponse{
+ Request: httputils.Request{
+ Path: "/foo",
+ },
+ Response: httputils.Response{
+ StatusCode: 200,
+ },
+ Namespace: ns,
+ }
+
+ // make sure listener is ready
+ httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
+ verifyMetrics(t, suite, `envoy_tcp_downstream_cx_total{envoy_tcp_prefix="gateway-conformance-infra/tcp-route-stat-name"}`)
+ })
+ },
+}
+
+func verifyMetrics(t *testing.T, suite *suite.ConformanceTestSuite, promQuery string) {
+ if err := wait.PollUntilContextTimeout(context.TODO(), 3*time.Second, time.Minute, true, func(ctx context.Context) (done bool, err error) {
+ v, err := prometheus.QueryPrometheus(suite.Client, promQuery)
+ if err != nil {
+ tlog.Logf(t, "failed to query prometheus: %v", err)
+ return false, err
+ }
+ if v != nil && v.Type() == model.ValVector {
+ vectorVal := v.(model.Vector)
+ if len(vectorVal) == 1 {
+ tlog.Logf(t, "got expected value: %v", v)
+ return true, nil
+ }
+ }
+ return false, nil
+ }); err != nil {
+ t.Errorf("failed to get expected response for the last (fourth) request: %v", err)
+ }
+}
diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml
index 63dc101fdd..d577712bf0 100644
--- a/test/helm/gateway-crds-helm/all.out.yaml
+++ b/test/helm/gateway-crds-helm/all.out.yaml
@@ -23398,6 +23398,22 @@ spec:
Telemetry configures the telemetry settings for the policy target (Gateway or xRoute).
This will override the telemetry settings in the EnvoyProxy resource.
properties:
+ metrics:
+ description: Metrics defines metrics configuration for the backend
+ or Route.
+ properties:
+ routeStatName:
+ description: |-
+ RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
+ 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
+ The supported operators for this pattern are:
+ %ROUTE_NAME%: name of Gateway API xRoute resource
+ %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+ %ROUTE_KIND%: kind of Gateway API xRoute resource
+ Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
+ Disabled by default.
+ type: string
+ type: object
tracing:
description: Tracing configures the tracing settings for the backend
or HTTPRoute.
diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
index ae2d5c6e12..849cea47cc 100644
--- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
+++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
@@ -2742,6 +2742,22 @@ spec:
Telemetry configures the telemetry settings for the policy target (Gateway or xRoute).
This will override the telemetry settings in the EnvoyProxy resource.
properties:
+ metrics:
+ description: Metrics defines metrics configuration for the backend
+ or Route.
+ properties:
+ routeStatName:
+ description: |-
+ RouteStatName defines the value of the Route stat_prefix, determining how the route stats are named.
+ 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
+ The supported operators for this pattern are:
+ %ROUTE_NAME%: name of Gateway API xRoute resource
+ %ROUTE_NAMESPACE%: namespace of Gateway API xRoute resource
+ %ROUTE_KIND%: kind of Gateway API xRoute resource
+ Example: %ROUTE_KIND%/%ROUTE_NAMESPACE%/%ROUTE_NAME% => httproute/my-ns/my-route
+ Disabled by default.
+ type: string
+ type: object
tracing:
description: Tracing configures the tracing settings for the backend
or HTTPRoute.