Fix metrics bucket key high cardinality
This commit is contained in:
parent
2d56be0ebb
commit
4da33c2bc2
|
@ -438,3 +438,11 @@ To enable HTTP/3 on an EntryPoint, please check out the [HTTP/3 configuration](.
|
||||||
In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) of the specification and
|
In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) of the specification and
|
||||||
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
|
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
|
||||||
Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated.
|
Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated.
|
||||||
|
|
||||||
|
## v2.6.0 to v2.6.1
|
||||||
|
|
||||||
|
In `v2.6.1`, the metrics system does not support any more custom HTTP method verbs to prevent potential metrics cardinality overhead.
|
||||||
|
In consequence, for metrics having the method label,
|
||||||
|
if the HTTP method verb of a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
|
||||||
|
or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`),
|
||||||
|
the value for the method label becomes `EXTENSION_METHOD`, instead of the request's one.
|
||||||
|
|
|
@ -61,7 +61,7 @@ traefik_config_last_reload_success
|
||||||
|
|
||||||
The expiration date of certificates.
|
The expiration date of certificates.
|
||||||
|
|
||||||
Available labels: `cn`, `sans`, `serial`.
|
[Labels](#labels): `cn`, `sans`, `serial`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
tls.certs.notAfterTimestamp
|
tls.certs.notAfterTimestamp
|
||||||
|
@ -93,7 +93,7 @@ traefik_tls_certs_not_after
|
||||||
|
|
||||||
The total count of HTTP requests received by an entrypoint.
|
The total count of HTTP requests received by an entrypoint.
|
||||||
|
|
||||||
Available labels: `code`, `method`, `protocol`, `entrypoint`.
|
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
entrypoint.request.total
|
entrypoint.request.total
|
||||||
|
@ -116,7 +116,7 @@ traefik_entrypoint_requests_total
|
||||||
|
|
||||||
The total count of HTTPS requests received by an entrypoint.
|
The total count of HTTPS requests received by an entrypoint.
|
||||||
|
|
||||||
Available labels: `tls_version`, `tls_cipher`, `entrypoint`.
|
[Labels](#labels): `tls_version`, `tls_cipher`, `entrypoint`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
entrypoint.request.tls.total
|
entrypoint.request.tls.total
|
||||||
|
@ -139,7 +139,7 @@ traefik_entrypoint_requests_tls_total
|
||||||
|
|
||||||
Request processing duration histogram on an entrypoint.
|
Request processing duration histogram on an entrypoint.
|
||||||
|
|
||||||
Available labels: `code`, `method`, `protocol`, `entrypoint`.
|
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
entrypoint.request.duration
|
entrypoint.request.duration
|
||||||
|
@ -162,7 +162,7 @@ traefik_entrypoint_request_duration_seconds
|
||||||
|
|
||||||
The current count of open connections on an entrypoint.
|
The current count of open connections on an entrypoint.
|
||||||
|
|
||||||
Available labels: `method`, `protocol`, `entrypoint`.
|
[Labels](#labels): `method`, `protocol`, `entrypoint`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
entrypoint.connections.open
|
entrypoint.connections.open
|
||||||
|
@ -194,7 +194,7 @@ traefik_entrypoint_open_connections
|
||||||
|
|
||||||
The total count of HTTP requests handled by a router.
|
The total count of HTTP requests handled by a router.
|
||||||
|
|
||||||
Available labels: `code`, `method`, `protocol`, `router`, `service`.
|
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
router.request.total
|
router.request.total
|
||||||
|
@ -217,7 +217,7 @@ traefik_router_requests_total
|
||||||
|
|
||||||
The total count of HTTPS requests handled by a router.
|
The total count of HTTPS requests handled by a router.
|
||||||
|
|
||||||
Available labels: `tls_version`, `tls_cipher`, `router`, `service`.
|
[Labels](#labels): `tls_version`, `tls_cipher`, `router`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
router.request.tls.total
|
router.request.tls.total
|
||||||
|
@ -240,7 +240,7 @@ traefik_router_requests_tls_total
|
||||||
|
|
||||||
Request processing duration histogram on a router.
|
Request processing duration histogram on a router.
|
||||||
|
|
||||||
Available labels: `code`, `method`, `protocol`, `router`, `service`.
|
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
router.request.duration
|
router.request.duration
|
||||||
|
@ -263,7 +263,7 @@ traefik_router_request_duration_seconds
|
||||||
|
|
||||||
The current count of open connections on a router.
|
The current count of open connections on a router.
|
||||||
|
|
||||||
Available labels: `method`, `protocol`, `router`, `service`.
|
[Labels](#labels): `method`, `protocol`, `router`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
router.connections.open
|
router.connections.open
|
||||||
|
@ -297,7 +297,7 @@ traefik_router_open_connections
|
||||||
|
|
||||||
The total count of HTTP requests processed on a service.
|
The total count of HTTP requests processed on a service.
|
||||||
|
|
||||||
Available labels: `code`, `method`, `protocol`, `service`.
|
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
service.request.total
|
service.request.total
|
||||||
|
@ -320,7 +320,7 @@ traefik_service_requests_total
|
||||||
|
|
||||||
The total count of HTTPS requests processed on a service.
|
The total count of HTTPS requests processed on a service.
|
||||||
|
|
||||||
Available labels: `tls_version`, `tls_cipher`, `service`.
|
[Labels](#labels): `tls_version`, `tls_cipher`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
router.service.tls.total
|
router.service.tls.total
|
||||||
|
@ -343,7 +343,7 @@ traefik_service_requests_tls_total
|
||||||
|
|
||||||
Request processing duration histogram on a service.
|
Request processing duration histogram on a service.
|
||||||
|
|
||||||
Available labels: `code`, `method`, `protocol`, `service`.
|
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
service.request.duration
|
service.request.duration
|
||||||
|
@ -366,7 +366,7 @@ traefik_service_request_duration_seconds
|
||||||
|
|
||||||
The current count of open connections on a service.
|
The current count of open connections on a service.
|
||||||
|
|
||||||
Available labels: `method`, `protocol`, `service`.
|
[Labels](#labels): `method`, `protocol`, `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
service.connections.open
|
service.connections.open
|
||||||
|
@ -389,7 +389,7 @@ traefik_service_open_connections
|
||||||
|
|
||||||
The count of requests retries on a service.
|
The count of requests retries on a service.
|
||||||
|
|
||||||
Available labels: `service`.
|
[Labels](#labels): `service`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
service.retries.total
|
service.retries.total
|
||||||
|
@ -412,7 +412,7 @@ traefik_service_retries_total
|
||||||
|
|
||||||
Current service's server status, described by a gauge with a value of 0 for a down server or a value of 1 for an up server.
|
Current service's server status, described by a gauge with a value of 0 for a down server or a value of 1 for an up server.
|
||||||
|
|
||||||
Available labels: `service`, `url`.
|
[Labels](#labels): `service`, `url`.
|
||||||
|
|
||||||
```dd tab="Datadog"
|
```dd tab="Datadog"
|
||||||
service.server.up
|
service.server.up
|
||||||
|
@ -430,3 +430,28 @@ traefik_service_server_up
|
||||||
# Default prefix: "traefik"
|
# Default prefix: "traefik"
|
||||||
{prefix}.service.server.up
|
{prefix}.service.server.up
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Labels
|
||||||
|
|
||||||
|
Here is a comprehensive list of labels that are provided by the metrics:
|
||||||
|
|
||||||
|
| Label | Description | example |
|
||||||
|
|---------------|---------------------------------------|----------------------------|
|
||||||
|
| `cn` | Certificate Common Name | "example.com" |
|
||||||
|
| `code` | Request code | "200" |
|
||||||
|
| `entrypoint` | Entrypoint that handled the request | "example_entrypoint" |
|
||||||
|
| `method` | Request Method | "GET" |
|
||||||
|
| `protocol` | Request protocol | "http" |
|
||||||
|
| `router` | Router that handled the request | "example_router" |
|
||||||
|
| `sans` | Certificate Subject Alternative NameS | "example.com" |
|
||||||
|
| `serial` | Certificate Serial Number | "123..." |
|
||||||
|
| `service` | Service that handled the request | "example_service@provider" |
|
||||||
|
| `tls_cipher` | TLS cipher used for the request | "TLS_FALLBACK_SCSV" |
|
||||||
|
| `tls_version` | TLS version used for the request | "1.0" |
|
||||||
|
| `url` | Service server url | "http://example.com" |
|
||||||
|
|
||||||
|
!!! info "`method` label value"
|
||||||
|
|
||||||
|
If the HTTP method verb on a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
|
||||||
|
or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`),
|
||||||
|
then the value for the method label becomes `EXTENSION_METHOD`.
|
||||||
|
|
|
@ -159,12 +159,27 @@ func containsHeader(req *http.Request, name, value string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getMethod returns the request's method.
|
||||||
|
// It checks whether the method is a valid UTF-8 string.
|
||||||
|
// To restrict the (potentially infinite) number of accepted values for the method,
|
||||||
|
// and avoid unbounded memory issues,
|
||||||
|
// values that are not part of the set of HTTP verbs are replaced with EXTENSION_METHOD.
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc2616/#section-5.1.1.
|
||||||
func getMethod(r *http.Request) string {
|
func getMethod(r *http.Request) string {
|
||||||
if !utf8.ValidString(r.Method) {
|
if !utf8.ValidString(r.Method) {
|
||||||
log.Warnf("Invalid HTTP method encoding: %s", r.Method)
|
log.WithoutContext().Warnf("Invalid HTTP method encoding: %s", r.Method)
|
||||||
return "NON_UTF8_HTTP_METHOD"
|
return "NON_UTF8_HTTP_METHOD"
|
||||||
}
|
}
|
||||||
return r.Method
|
|
||||||
|
switch r.Method {
|
||||||
|
case "HEAD", "GET", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", // https://datatracker.ietf.org/doc/html/rfc7231#section-4
|
||||||
|
"PATCH", // https://datatracker.ietf.org/doc/html/rfc5789#section-2
|
||||||
|
"PRI": // https://datatracker.ietf.org/doc/html/rfc7540#section-11.6
|
||||||
|
return r.Method
|
||||||
|
default:
|
||||||
|
return "EXTENSION_METHOD"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type retryMetrics interface {
|
type retryMetrics interface {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-kit/kit/metrics"
|
"github.com/go-kit/kit/metrics"
|
||||||
|
@ -98,3 +99,33 @@ func TestCloseNotifier(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_getMethod(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
method string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
method: http.MethodGet,
|
||||||
|
expected: http.MethodGet,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: strings.ToLower(http.MethodGet),
|
||||||
|
expected: "EXTENSION_METHOD",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: "THIS_IS_NOT_A_VALID_METHOD",
|
||||||
|
expected: "EXTENSION_METHOD",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.method, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
request := httptest.NewRequest(test.method, "http://example.com", nil)
|
||||||
|
assert.Equal(t, test.expected, getMethod(request))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue