Merge branch v3.5 into master

This commit is contained in:
kevinpollet 2025-07-24 09:03:26 +02:00
commit 24cede62ee
No known key found for this signature in database
GPG Key ID: 0C9A5DDD1B292453
139 changed files with 1867 additions and 866 deletions

View File

@ -1,17 +1,16 @@
<!--
PLEASE READ THIS MESSAGE.
Documentation fixes or enhancements:
- for Traefik v2: use branch v2.11
- for Traefik v3: use branch v3.4
Documentation:
- for Traefik v2: use branch v2.11 (fixes only)
- for Traefik v3: use branch v3.5
Bug fixes:
- for Traefik v2: use branch v2.11
- for Traefik v3: use branch v3.4
Bug:
- for Traefik v2: use branch v2.11 (security fixes only)
- for Traefik v3: use branch v3.5
Enhancements:
- for Traefik v2: we only accept bug fixes
- for Traefik v3: use branch master
- use branch master
HOW TO WRITE A GOOD PULL REQUEST? https://doc.traefik.io/traefik/contributing/submitting-pull-requests/

View File

@ -36,7 +36,21 @@ jobs:
touch webui/static/index.html
- name: Build binary
run: make binary
run: make binary-linux-amd64
- name: Save go cache build
uses: actions/cache/save@v4
with:
path: |
~/.cache/go-build
key: ${{ runner.os }}-go-build-cache-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- name: Artifact traefik binary
uses: actions/upload-artifact@v4
with:
name: traefik
path: ./dist/linux/amd64/traefik
retention-days: 1
test-integration:
runs-on: ubuntu-latest
@ -65,8 +79,21 @@ jobs:
mkdir webui/static
touch webui/static/index.html
- name: Build binary
run: make binary
- name: Download traefik binary
uses: actions/download-artifact@v4
with:
name: traefik
path: ./dist/linux/amd64/
- name: Make binary executable
run: chmod +x ./dist/linux/amd64/traefik
- name: Restore go cache build
uses: actions/cache/restore@v4
with:
path: |
~/.cache/go-build
key: ${{ runner.os }}-go-build-cache-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- name: Generate go test Slice
id: test_split

View File

@ -1,3 +1,71 @@
## [v3.5.0](https://github.com/traefik/traefik/tree/v3.5.0) (2025-07-23)
[All Commits](https://github.com/traefik/traefik/compare/v3.5.0-rc1...v3.5.0)
**Enhancements:**
- **[acme]** OCSP stapling ([#8393](https://github.com/traefik/traefik/pull/8393) by [alekitto](https://github.com/alekitto))
- **[acme]** Add acme.httpChallenge.delay option ([#11643](https://github.com/traefik/traefik/pull/11643) by [ldez](https://github.com/ldez))
- **[acme]** Allow configuration of ACME provider http timeout ([#11637](https://github.com/traefik/traefik/pull/11637) by [tkw1536](https://github.com/tkw1536))
- **[healthcheck]** Add url option to healthcheck command ([#11711](https://github.com/traefik/traefik/pull/11711) by [Nelwhix](https://github.com/Nelwhix))
- **[healthcheck]** Add unhealthy Interval to the health check configuration ([#10610](https://github.com/traefik/traefik/pull/10610) by [sswastik02](https://github.com/sswastik02))
- **[k8s/gatewayapi]** Bump sigs.k8s.io/gateway-api to v1.3.0 ([#11719](https://github.com/traefik/traefik/pull/11719) by [rtribotte](https://github.com/rtribotte))
- **[k8s/ingress]** Make the behavior of prefix matching in Ingress consistent with Kubernetes doc ([#11203](https://github.com/traefik/traefik/pull/11203) by [charlie0129](https://github.com/charlie0129))
- **[k8s]** NGINX Ingress Provider ([#11844](https://github.com/traefik/traefik/pull/11844) by [rtribotte](https://github.com/rtribotte))
- **[middleware,authentication]** Handle context canceled in ForwardAuth middleware ([#11817](https://github.com/traefik/traefik/pull/11817) by [bengentree](https://github.com/bengentree))
- **[plugins]** Ability to enable unsafe in yaegi through plugin manifest ([#11589](https://github.com/traefik/traefik/pull/11589) by [Rydez](https://github.com/Rydez))
- **[tls]** Introduce X25519MLKEM768 for Post-Quantum-Secure TLS ([#11731](https://github.com/traefik/traefik/pull/11731) by [fzoli](https://github.com/fzoli))
- **[webui]** Migrate Traefik Proxy dashboard UI to React ([#11674](https://github.com/traefik/traefik/pull/11674) by [gndz07](https://github.com/gndz07))
- **[webui]** Improve visualization for StatusRewrites option of errors middleware ([#11806](https://github.com/traefik/traefik/pull/11806) by [sevensolutions](https://github.com/sevensolutions))
**Bug fixes:**
- **[healthcheck]** Revert 11711 adding url param to healthcheck command ([#11927](https://github.com/traefik/traefik/pull/11927) by [lbenguigui](https://github.com/lbenguigui))
- **[logs,metrics,tracing,accesslogs,otel]** Add missing resource attributes detectors ([#11874](https://github.com/traefik/traefik/pull/11874) by [rtribotte](https://github.com/rtribotte))
- **[logs,tracing,k8s,otel]** Add k8s resource attributes automatically ([#11906](https://github.com/traefik/traefik/pull/11906) by [kevinpollet](https://github.com/kevinpollet))
- **[metrics,otel]** Add resourceAttributes option to OTel metrics ([#11908](https://github.com/traefik/traefik/pull/11908) by [kevinpollet](https://github.com/kevinpollet))
- **[middleware,tracing]** Introduce trace verbosity config and produce less spans by default ([#11870](https://github.com/traefik/traefik/pull/11870) by [rtribotte](https://github.com/rtribotte))
**Documentation:**
- **[docker,ecs,docker/swarm,consulcatalog,nomad]** Add constraints key limitations for label providers ([#11893](https://github.com/traefik/traefik/pull/11893) by [bluepuma77](https://github.com/bluepuma77))
- **[k8s]** Add extended NGinX annotation support documentation ([#11920](https://github.com/traefik/traefik/pull/11920) by [nmengin](https://github.com/nmengin))
- Remove dead link to Peka blog ([#11934](https://github.com/traefik/traefik/pull/11934) by [kevinpollet](https://github.com/kevinpollet))
- Prepare release v3.5.0-rc2 ([#11899](https://github.com/traefik/traefik/pull/11899) by [kevinpollet](https://github.com/kevinpollet))
- Prepare release v3.5.0-rc1 ([#11865](https://github.com/traefik/traefik/pull/11865) by [rtribotte](https://github.com/rtribotte))
**Misc:**
- Merge branch v3.4 into v3.5 ([#11933](https://github.com/traefik/traefik/pull/11933) by [rtribotte](https://github.com/rtribotte))
- Merge branch v3.4 into v3.5 ([#11898](https://github.com/traefik/traefik/pull/11898) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.4 into master ([#11863](https://github.com/traefik/traefik/pull/11863) by [rtribotte](https://github.com/rtribotte))
- Merge branch v3.4 into master ([#11861](https://github.com/traefik/traefik/pull/11861) by [rtribotte](https://github.com/rtribotte))
- Merge branch v3.4 into master ([#11857](https://github.com/traefik/traefik/pull/11857) by [rtribotte](https://github.com/rtribotte))
- Merge branch v3.4 into master ([#11855](https://github.com/traefik/traefik/pull/11855) by [rtribotte](https://github.com/rtribotte))
- Merge branch v3.4 into master ([#11813](https://github.com/traefik/traefik/pull/11813) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v3.4 into master ([#11758](https://github.com/traefik/traefik/pull/11758) by [mmatur](https://github.com/mmatur))
- Merge v3.4 into master ([#11752](https://github.com/traefik/traefik/pull/11752) by [mmatur](https://github.com/mmatur))
- Merge branch v3.4 into master ([#11708](https://github.com/traefik/traefik/pull/11708) by [kevinpollet](https://github.com/kevinpollet))
## [v3.4.5](https://github.com/traefik/traefik/tree/v3.4.5) (2025-07-23)
[All Commits](https://github.com/traefik/traefik/compare/v3.4.4...v3.4.5)
**Bug fixes:**
- **[http3]** Bump github.com/quic-go/quic-go to v0.54.0 ([#11919](https://github.com/traefik/traefik/pull/11919) by [GreyXor](https://github.com/GreyXor))
**Documentation:**
- Fix typo in entrypoints page ([#11914](https://github.com/traefik/traefik/pull/11914) by [adk-swisstopo](https://github.com/adk-swisstopo))
**Misc:**
- Merge branch v2.11 into v3.4 ([#11930](https://github.com/traefik/traefik/pull/11930) by [kevinpollet](https://github.com/kevinpollet))
- Merge branch v2.11 into v3.4 ([#11926](https://github.com/traefik/traefik/pull/11926) by [rtribotte](https://github.com/rtribotte))
## [v2.11.28](https://github.com/traefik/traefik/tree/v2.11.28) (2025-07-23)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.27...v2.11.28)
**Bug fixes:**
- **[logs]** Redact logged install configuration ([#11907](https://github.com/traefik/traefik/pull/11907) by [jspdown](https://github.com/jspdown))
- **[plugins]** Fix client arbitrary file access during archive extraction zipslip ([#11911](https://github.com/traefik/traefik/pull/11911) by [odaysec](https://github.com/odaysec))
- **[server]** Disable MPTCP by default ([#11918](https://github.com/traefik/traefik/pull/11918) by [rtribotte](https://github.com/rtribotte))
**Documentation:**
- **[k8s/crd,k8s]** Remove all mentions of ordering for TLSOption CurvePreferences field ([#11924](https://github.com/traefik/traefik/pull/11924) by [jnoordsij](https://github.com/jnoordsij))
## [v3.5.0-rc2](https://github.com/traefik/traefik/tree/v3.5.0-rc2) (2025-07-11)
[All Commits](https://github.com/traefik/traefik/compare/v3.5.0-rc1...v3.5.0-rc2)

View File

@ -93,7 +93,7 @@ test-unit:
.PHONY: test-integration
#? test-integration: Run the integration tests
test-integration: binary
test-integration:
GOOS=$(GOOS) GOARCH=$(GOARCH) go test ./integration -test.timeout=20m -failfast -v $(TESTFLAGS)
.PHONY: test-gateway-api-conformance

View File

@ -152,7 +152,7 @@ We use [Semantic Versioning](https://semver.org/).
## Credits
Kudos to [Peka](http://peka.byethost11.com/photoblog/) for his awesome work on the gopher's logo!.
Kudos to Peka for his awesome work on the gopher's logo!.
The gopher's logo of Traefik is licensed under the Creative Commons 3.0 Attributions license.

View File

@ -2,7 +2,6 @@ package healthcheck
import (
"errors"
"flag"
"fmt"
"net/http"
"os"
@ -23,26 +22,11 @@ func NewCmd(traefikConfiguration *static.Configuration, loaders []cli.ResourceLo
}
}
func runCmd(traefikConfiguration *static.Configuration) func(args []string) error {
return func(args []string) error {
fs := flag.NewFlagSet("healthcheck", flag.ContinueOnError)
urlFlag := fs.String("url", "", "")
fs.SetOutput(os.Stderr)
if err := fs.Parse(args); err != nil {
return err
}
func runCmd(traefikConfiguration *static.Configuration) func(_ []string) error {
return func(_ []string) error {
traefikConfiguration.SetEffectiveConfiguration()
var resp *http.Response
var errPing error
if *urlFlag != "" {
client := &http.Client{Timeout: 5 * time.Second}
resp, errPing = client.Head(*urlFlag)
} else {
resp, errPing = Do(*traefikConfiguration)
}
resp, errPing := Do(*traefikConfiguration)
if resp != nil {
resp.Body.Close()
}

View File

@ -1,6 +1,7 @@
package main
import (
"context"
"errors"
"fmt"
"io"
@ -22,7 +23,7 @@ func init() {
zerolog.SetGlobalLevel(zerolog.ErrorLevel)
}
func setupLogger(staticConfiguration *static.Configuration) error {
func setupLogger(ctx context.Context, staticConfiguration *static.Configuration) error {
// Validate that the experimental flag is set up at this point,
// rather than validating the static configuration before the setupLogger call.
// This ensures that validation messages are not logged using an un-configured logger.
@ -39,16 +40,16 @@ func setupLogger(staticConfiguration *static.Configuration) error {
zerolog.SetGlobalLevel(logLevel)
// create logger
logCtx := zerolog.New(w).With().Timestamp()
logger := zerolog.New(w).With().Timestamp()
if logLevel <= zerolog.DebugLevel {
logCtx = logCtx.Caller()
logger = logger.Caller()
}
log.Logger = logCtx.Logger().Level(logLevel)
log.Logger = logger.Logger().Level(logLevel)
if staticConfiguration.Log != nil && staticConfiguration.Log.OTLP != nil {
var err error
log.Logger, err = logs.SetupOTelLogger(log.Logger, staticConfiguration.Log.OTLP)
log.Logger, err = logs.SetupOTelLogger(ctx, log.Logger, staticConfiguration.Log.OTLP)
if err != nil {
return fmt.Errorf("setting up OpenTelemetry logger: %w", err)
}

View File

@ -3,7 +3,6 @@ package main
import (
"context"
"crypto/x509"
"encoding/json"
"fmt"
"io"
stdlog "log"
@ -40,6 +39,7 @@ import (
"github.com/traefik/traefik/v3/pkg/provider/traefik"
"github.com/traefik/traefik/v3/pkg/proxy"
"github.com/traefik/traefik/v3/pkg/proxy/httputil"
"github.com/traefik/traefik/v3/pkg/redactor"
"github.com/traefik/traefik/v3/pkg/safe"
"github.com/traefik/traefik/v3/pkg/server"
"github.com/traefik/traefik/v3/pkg/server/middleware"
@ -90,7 +90,10 @@ Complete documentation is available at https://traefik.io`,
}
func runCmd(staticConfiguration *static.Configuration) error {
if err := setupLogger(staticConfiguration); err != nil {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
if err := setupLogger(ctx, staticConfiguration); err != nil {
return fmt.Errorf("setting up logger: %w", err)
}
@ -104,12 +107,11 @@ func runCmd(staticConfiguration *static.Configuration) error {
log.Info().Str("version", version.Version).
Msgf("Traefik version %s built on %s", version.Version, version.BuildDate)
jsonConf, err := json.Marshal(staticConfiguration)
redactedStaticConfiguration, err := redactor.RemoveCredentials(staticConfiguration)
if err != nil {
log.Error().Err(err).Msg("Could not marshal static configuration")
log.Debug().Interface("staticConfiguration", staticConfiguration).Msg("Static configuration loaded [struct]")
log.Error().Err(err).Msg("Could not redact static configuration")
} else {
log.Debug().RawJSON("staticConfiguration", jsonConf).Msg("Static configuration loaded [json]")
log.Debug().RawJSON("staticConfiguration", []byte(redactedStaticConfiguration)).Msg("Static configuration loaded [json]")
}
if staticConfiguration.Global.CheckNewVersion {
@ -123,8 +125,6 @@ func runCmd(staticConfiguration *static.Configuration) error {
return err
}
ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
if staticConfiguration.Ping != nil {
staticConfiguration.Ping.WithContext(ctx)
}
@ -210,8 +210,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
}
}
metricsRegistry := metrics.NewMultiRegistry(metricRegistries)
accessLog := setupAccessLog(staticConfiguration.AccessLog)
tracer, tracerCloser := setupTracing(staticConfiguration.Tracing)
accessLog := setupAccessLog(ctx, staticConfiguration.AccessLog)
tracer, tracerCloser := setupTracing(ctx, staticConfiguration.Tracing)
observabilityMgr := middleware.NewObservabilityMgr(*staticConfiguration, metricsRegistry, semConvMetricRegistry, accessLog, tracer, tracerCloser)
// Entrypoints
@ -586,12 +586,12 @@ func appendCertMetric(gauge gokitmetrics.Gauge, certificate *x509.Certificate) {
gauge.With(labels...).Set(notAfter)
}
func setupAccessLog(conf *types.AccessLog) *accesslog.Handler {
func setupAccessLog(ctx context.Context, conf *types.AccessLog) *accesslog.Handler {
if conf == nil {
return nil
}
accessLoggerMiddleware, err := accesslog.NewHandler(conf)
accessLoggerMiddleware, err := accesslog.NewHandler(ctx, conf)
if err != nil {
log.Warn().Err(err).Msg("Unable to create access logger")
return nil
@ -600,12 +600,12 @@ func setupAccessLog(conf *types.AccessLog) *accesslog.Handler {
return accessLoggerMiddleware
}
func setupTracing(conf *static.Tracing) (*tracing.Tracer, io.Closer) {
func setupTracing(ctx context.Context, conf *static.Tracing) (*tracing.Tracer, io.Closer) {
if conf == nil {
return nil, nil
}
tracer, closer, err := tracing.NewTracing(conf)
tracer, closer, err := tracing.NewTracing(ctx, conf)
if err != nil {
log.Warn().Err(err).Msg("Unable to create tracer")
return nil, nil

View File

@ -384,11 +384,11 @@ spec:
### Curve Preferences
This option allows to set the preferred elliptic curves in a specific order.
This option allows to set the enabled elliptic curves for key exchange.
The names of the curves defined by [`crypto`](https://godoc.org/crypto/tls#CurveID) (e.g. `CurveP521`) and the [RFC defined names](https://tools.ietf.org/html/rfc8446#section-4.2.7) (e. g. `secp521r1`) can be used.
See [CurveID](https://godoc.org/crypto/tls#CurveID) for more information.
See [CurvePreferences](https://godoc.org/crypto/tls#Config.CurvePreferences) and [CurveID](https://godoc.org/crypto/tls#CurveID) for more information.
```yaml tab="File (YAML)"
# Dynamic configuration

View File

@ -706,3 +706,14 @@ and Traefik now keeps them encoded to avoid any ambiguity.
| `/foo/../bar` | PathPrefix(`/bar`) | Match | Match |
| `/foo/%2E%2E/bar` | PathPrefix(`/foo`) | Match | No match |
| `/foo/%2E%2E/bar` | PathPrefix(`/bar`) | No match | Match |
## v2.11.28
### MultiPath TCP
Since `v2.11.28`, the MultiPath TCP support introduced with `v2.11.26` has been removed.
It appears that enabling MPTCP on some platforms can cause Traefik to stop with the following error logs message:
- `set tcp X.X.X.X:X->X.X.X.X:X: setsockopt: operation not supported`
However, it can be re-enabled by setting the `multipathtcp` variable in the GODEBUG environment variable, see the related [go documentation](https://go.dev/doc/godebug#go-124).

View File

@ -319,3 +319,53 @@ and Traefik now keeps them encoded to avoid any ambiguity.
| `/foo/../bar` | PathPrefix(`/bar`) | Match | Match |
| `/foo/%2E%2E/bar` | PathPrefix(`/foo`) | Match | No match |
| `/foo/%2E%2E/bar` | PathPrefix(`/bar`) | No match | Match |
## v3.4.5
### MultiPath TCP
Since `v3.4.5`, the MultiPath TCP support introduced with `v3.4.2` has been removed.
It appears that enabling MPTCP on some platforms can cause Traefik to stop with the following error logs message:
- `set tcp X.X.X.X:X->X.X.X.X:X: setsockopt: operation not supported`
However, it can be re-enabled by setting the `multipathtcp` variable in the GODEBUG environment variable, see the related [go documentation](https://go.dev/doc/godebug#go-124).
## v3.5.0
### Observability
#### TraceVerbosity on Routers and Entrypoints
Starting with `v3.5.0`, a new `traceVerbosity` option is available for both entrypoints and routers.
This option allows you to control the level of detail for tracing spans.
Routers can override the value inherited from their entrypoint.
**Impact:**
- If you rely on tracing, review your configuration to explicitly set the desired verbosity level.
- Existing configurations will default to `minimal` unless overridden, which will result in fewer spans being generated than before.
Possible values are:
- `minimal`: produces a single server span and one client span for each request processed by a router.
- `detailed`: enables the creation of additional spans for each middleware executed for each request processed by a router.
See the updated documentation for [entrypoints](../reference/install-configuration/entrypoints.md) and [dynamic routers](../reference/dynamic-configuration/file.md#observability-options).
#### K8s Resource Attributes
Since `v3.5.0`, the semconv attributes `k8s.pod.name` and `k8s.pod.uid` are injected automatically in OTel resource attributes when OTel tracing/logs/metrics are enabled.
For that purpose, the following right has to be added to the Traefik Kubernetes RBACs:
```yaml
...
- apiGroups:
- ""
resources:
- pods
verbs:
- get
...
```

View File

@ -340,6 +340,54 @@ accesslog:
The OpenTelemetry Logger exporter will export access logs to the collector using HTTPS by default to https://localhost:4318/v1/logs, see the [gRPC Section](#grpc-configuration) to use gRPC.
### `serviceName`
_Optional, Default="traefik"_
Defines the service name resource attribute.
```yaml tab="File (YAML)"
accesslog:
otlp:
serviceName: name
```
```toml tab="File (TOML)"
[accesslog]
[accesslog.otlp]
serviceName = "name"
```
```bash tab="CLI"
--accesslog.otlp.serviceName=name
```
### `ressourceAttributes`
_Optional, Default=empty_
Defines additional resource attributes to be sent to the collector.
```yaml tab="File (YAML)"
accesslog:
otlp:
resourceAttributes:
attr1: foo
attr2: bar
```
```toml tab="File (TOML)"
[accesslog]
[accesslog.otlp.resourceAttributes]
attr1 = "foo"
attr2 = "bar"
```
```bash tab="CLI"
--accesslog.otlp.resourceAttributes.attr1=foo
--accesslog.otlp.resourceAttributes.attr2=bar
```
### HTTP configuration
_Optional_

View File

@ -219,6 +219,54 @@ log:
The OpenTelemetry Logger exporter will export logs to the collector using HTTPS by default to https://localhost:4318/v1/logs, see the [gRPC Section](#grpc-configuration) to use gRPC.
### `serviceName`
_Optional, Default="traefik"_
Defines the service name resource attribute.
```yaml tab="File (YAML)"
log:
otlp:
serviceName: name
```
```toml tab="File (TOML)"
[log]
[log.otlp]
serviceName = "name"
```
```bash tab="CLI"
--log.otlp.serviceName=name
```
### `ressourceAttributes`
_Optional, Default=empty_
Defines additional resource attributes to be sent to the collector.
```yaml tab="File (YAML)"
log:
otlp:
resourceAttributes:
attr1: foo
attr2: bar
```
```toml tab="File (TOML)"
[log]
[log.otlp.resourceAttributes]
attr1 = "foo"
attr2 = "bar"
```
```bash tab="CLI"
--log.otlp.resourceAttributes.attr1=foo
--log.otlp.resourceAttributes.attr2=bar
```
### HTTP configuration
_Optional_

View File

@ -143,7 +143,7 @@ metrics:
_Optional, Default="traefik"_
OTEL service name to use.
Defines the service name resource attribute.
```yaml tab="File (YAML)"
metrics:
@ -160,6 +160,31 @@ metrics:
```bash tab="CLI"
--metrics.otlp.serviceName=name
```
#### `ressourceAttributes`
_Optional, Default=empty_
Defines additional resource attributes to be sent to the collector.
```yaml tab="File (YAML)"
metrics:
otlp:
resourceAttributes:
attr1: foo
attr2: bar
```
```toml tab="File (TOML)"
[metrics]
[metrics.otlp.resourceAttributes]
attr1 = "foo"
attr2 = "bar"
```
```bash tab="CLI"
--metrics.otlp.resourceAttributes.attr1=foo
--metrics.otlp.resourceAttributes.attr2=bar
```
### HTTP configuration

View File

@ -169,6 +169,7 @@
- "traefik.http.routers.router0.middlewares=foobar, foobar"
- "traefik.http.routers.router0.observability.accesslogs=true"
- "traefik.http.routers.router0.observability.metrics=true"
- "traefik.http.routers.router0.observability.traceverbosity=foobar"
- "traefik.http.routers.router0.observability.tracing=true"
- "traefik.http.routers.router0.priority=42"
- "traefik.http.routers.router0.rule=foobar"
@ -185,6 +186,7 @@
- "traefik.http.routers.router1.middlewares=foobar, foobar"
- "traefik.http.routers.router1.observability.accesslogs=true"
- "traefik.http.routers.router1.observability.metrics=true"
- "traefik.http.routers.router1.observability.traceverbosity=foobar"
- "traefik.http.routers.router1.observability.tracing=true"
- "traefik.http.routers.router1.priority=42"
- "traefik.http.routers.router1.rule=foobar"

View File

@ -22,8 +22,9 @@
sans = ["foobar", "foobar"]
[http.routers.Router0.observability]
accessLogs = true
tracing = true
metrics = true
tracing = true
traceVerbosity = "foobar"
[http.routers.Router1]
entryPoints = ["foobar", "foobar"]
middlewares = ["foobar", "foobar"]
@ -44,8 +45,9 @@
sans = ["foobar", "foobar"]
[http.routers.Router1.observability]
accessLogs = true
tracing = true
metrics = true
tracing = true
traceVerbosity = "foobar"
[http.services]
[http.services.Service01]
[http.services.Service01.failover]

View File

@ -27,8 +27,9 @@ http:
- foobar
observability:
accessLogs: true
tracing: true
metrics: true
tracing: true
traceVerbosity: foobar
Router1:
entryPoints:
- foobar
@ -54,8 +55,9 @@ http:
- foobar
observability:
accessLogs: true
tracing: true
metrics: true
tracing: true
traceVerbosity: foobar
services:
Service01:
failover:

View File

@ -92,10 +92,21 @@ spec:
More info: https://doc.traefik.io/traefik/v3.5/routing/routers/#observability
properties:
accessLogs:
description: AccessLogs enables access logs for this router.
type: boolean
metrics:
description: Metrics enables metrics for this router.
type: boolean
traceVerbosity:
default: minimal
description: TraceVerbosity defines the verbosity level
of the tracing for this router.
enum:
- minimal
- detailed
type: string
tracing:
description: Tracing enables tracing for this router.
type: boolean
type: object
priority:
@ -2551,7 +2562,7 @@ spec:
type: object
curvePreferences:
description: |-
CurvePreferences defines the preferred elliptic curves in a specific order.
CurvePreferences defines the preferred elliptic curves.
More info: https://doc.traefik.io/traefik/v3.5/https/tls/#curve-preferences
items:
type: string

View File

@ -15,6 +15,14 @@ rules:
- get
- list
- watch
# The pods right is needed to inject k8s.pod.uid and k8s.pod.name OTel attributes.
# When OTel tracing/logs/metrics are not enabled, this rule is not needed.
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- discovery.k8s.io
resources:

View File

@ -11,6 +11,14 @@ rules:
verbs:
- list
- watch
# The pods get right is needed to inject k8s.pod.uid and k8s.pod.name in OTel attributes.
# When OTel tracing/logs/metrics are not enabled, this rule is not needed.
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:

View File

@ -199,6 +199,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/routers/Router0/middlewares/1` | `foobar` |
| `traefik/http/routers/Router0/observability/accessLogs` | `true` |
| `traefik/http/routers/Router0/observability/metrics` | `true` |
| `traefik/http/routers/Router0/observability/traceVerbosity` | `foobar` |
| `traefik/http/routers/Router0/observability/tracing` | `true` |
| `traefik/http/routers/Router0/priority` | `42` |
| `traefik/http/routers/Router0/rule` | `foobar` |
@ -218,6 +219,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/routers/Router1/middlewares/1` | `foobar` |
| `traefik/http/routers/Router1/observability/accessLogs` | `true` |
| `traefik/http/routers/Router1/observability/metrics` | `true` |
| `traefik/http/routers/Router1/observability/traceVerbosity` | `foobar` |
| `traefik/http/routers/Router1/observability/tracing` | `true` |
| `traefik/http/routers/Router1/priority` | `42` |
| `traefik/http/routers/Router1/rule` | `foobar` |

View File

@ -0,0 +1,114 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.1
name: tlsoptions.traefik.containo.us
spec:
group: traefik.containo.us
names:
kind: TLSOption
listKind: TLSOptionList
plural: tlsoptions
singular: tlsoption
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: |-
TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection.
More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: TLSOptionSpec defines the desired state of a TLSOption.
properties:
alpnProtocols:
description: |-
ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference.
More info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols
items:
type: string
type: array
cipherSuites:
description: |-
CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2.
More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites
items:
type: string
type: array
clientAuth:
description: ClientAuth defines the server's policy for TLS Client
Authentication.
properties:
clientAuthType:
description: ClientAuthType defines the client authentication
type to apply.
enum:
- NoClientCert
- RequestClientCert
- RequireAnyClientCert
- VerifyClientCertIfGiven
- RequireAndVerifyClientCert
type: string
secretNames:
description: SecretNames defines the names of the referenced Kubernetes
Secret storing certificate details.
items:
type: string
type: array
type: object
curvePreferences:
description: |-
CurvePreferences defines the preferred elliptic curves.
More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences
items:
type: string
type: array
maxVersion:
description: |-
MaxVersion defines the maximum TLS version that Traefik will accept.
Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13.
Default: None.
type: string
minVersion:
description: |-
MinVersion defines the minimum TLS version that Traefik will accept.
Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13.
Default: VersionTLS10.
type: string
preferServerCipherSuites:
description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
description: SniStrict defines whether Traefik allows connections
from clients connections that do not specify a server_name extension.
type: boolean
type: object
required:
- metadata
- spec
type: object
served: true
storage: true

View File

@ -92,10 +92,21 @@ spec:
More info: https://doc.traefik.io/traefik/v3.5/routing/routers/#observability
properties:
accessLogs:
description: AccessLogs enables access logs for this router.
type: boolean
metrics:
description: Metrics enables metrics for this router.
type: boolean
traceVerbosity:
default: minimal
description: TraceVerbosity defines the verbosity level
of the tracing for this router.
enum:
- minimal
- detailed
type: string
tracing:
description: Tracing enables tracing for this router.
type: boolean
type: object
priority:

View File

@ -78,7 +78,7 @@ spec:
type: object
curvePreferences:
description: |-
CurvePreferences defines the preferred elliptic curves in a specific order.
CurvePreferences defines the preferred elliptic curves.
More info: https://doc.traefik.io/traefik/v3.5/https/tls/#curve-preferences
items:
type: string

View File

@ -83,39 +83,40 @@ additionalArguments:
## Configuration Options
| Field | Description | Default | Required |
|:-----------------|:--------|:--------|:---------|
| `address` | Define the port, and optionally the hostname, on which to listen for incoming connections and packets.<br /> It also defines the protocol to use (TCP or UDP).<br /> If no protocol is specified, the default is TCP. The format is:`[host]:port[/tcp\|/udp] | - | Yes |
| `asDefault` | Mark the `entryPoint` to be in the list of default `entryPoints`.<br /> `entryPoints`in this list are used (by default) on HTTP and TCP routers that do not define their own `entryPoints` option.<br /> More information [here](#asdefault). | false | No |
| `forwardedHeaders.trustedIPs` | Set the IPs or CIDR from where Traefik trusts the forwarded headers information (`X-Forwarded-*`). | - | No |
| `forwardedHeaders.insecure` | Set the insecure mode to always trust the forwarded headers information (`X-Forwarded-*`).<br />We recommend to use this option only for tests purposes, not in production. | false | No |
| `http.redirections.`<br />`entryPoint.to` | The target element to enable (permanent) redirecting of all incoming requests on an entry point to another one. <br /> The target element can be an entry point name (ex: `websecure`), or a port (`:443`). | - | Yes |
| `http.redirections.`<br />`entryPoint.scheme` | The target scheme to use for (permanent) redirection of all incoming requests. | https | No |
| `http.redirections.`<br />`entryPoint.permanent` | Enable permanent redirecting of all incoming requests on an entry point to another one changing the scheme. <br /> The target element, it can be an entry point name (ex: `websecure`), or a port (`:443`). | false | No |
| `http.redirections.`<br />`entryPoint.priority` | Default priority applied to the routers attached to the `entryPoint`.| MaxInt32-1 (2147483646) | No |
| `http.encodeQuerySemicolons` | Enable query semicolons encoding. <br /> Use this option to avoid non-encoded semicolons to be interpreted as query parameter separators by Traefik. <br /> When using this option, the non-encoded semicolons characters in query will be transmitted encoded to the backend.<br /> More information [here](#encodequerysemicolons). | false | No |
| `http.sanitizePath` | Defines whether to enable the request path sanitization.<br /> More information [here](#sanitizepath). | false | No |
| `http.middlewares` | Set the list of middlewares that are prepended by default to the list of middlewares of each router associated to the named entry point. <br />More information [here](#httpmiddlewares). | - | No |
| `http.tls` | Enable TLS on every router attached to the `entryPoint`. <br /> If no certificate are set, a default self-signed certificate is generates by Traefik. <br /> We recommend to not use self signed certificates in production.| - | No |
| `http.tls.options` | Apply TLS options on every router attached to the `entryPoint`. <br /> The TLS options can be overidden per router. <br /> More information in the [dedicated section](../../routing/providers/kubernetes-crd.md#kind-tlsoption). | - | No |
| `http.tls.certResolver` | Apply a certificate resolver on every router attached to the `entryPoint`. <br /> The TLS options can be overidden per router. <br /> More information in the [dedicated section](../install-configuration/tls/certificate-resolvers/overview.md). | - | No |
| `http2.maxConcurrentStreams` | Set the number of concurrent streams per connection that each client is allowed to initiate. <br /> The value must be greater than zero. | 250 | No |
| `http3` | Enable HTTP/3 protocol on the `entryPoint`. <br /> HTTP/3 requires a TCP `entryPoint`. as HTTP/3 always starts as a TCP connection that then gets upgraded to UDP. In most scenarios, this `entryPoint` is the same as the one used for TLS traffic.<br /> More information [here](#http3. | - | No |
| `http3.advertisedPort` | Set the UDP port to advertise as the HTTP/3 authority. <br /> It defaults to the entryPoint's address port. <br /> It can be used to override the authority in the `alt-svc` header, for example if the public facing port is different from where Traefik is listening. | - | No |
| `observability.accessLogs` | Defines whether a router attached to this EntryPoint produces access-logs by default. Nonetheless, a router defining its own observability configuration will opt-out from this default. | true | No |
| `observability.metrics` | Defines whether a router attached to this EntryPoint produces metrics by default. Nonetheless, a router defining its own observability configuration will opt-out from this default. | true | No |
| `observability.tracing` | Defines whether a router attached to this EntryPoint produces traces by default. Nonetheless, a router defining its own observability configuration will opt-out from this default. | true | No |
| `proxyProtocol.trustedIPs` | Enable PROXY protocol with Trusted IPs. <br /> Traefik supports [PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2. <br /> If PROXY protocol header parsing is enabled for the entry point, this entry point can accept connections with or without PROXY protocol headers. <br /> If the PROXY protocol header is passed, then the version is determined automatically.<br /> More information [here](#proxyprotocol-and-load-balancers). | - | No |
| `proxyProtocol.insecure` | Enable PROXY protocol trusting every incoming connection. <br /> Every remote client address will be replaced (`trustedIPs`) won't have any effect). <br /> Traefik supports [PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2. <br /> If PROXY protocol header parsing is enabled for the entry point, this entry point can accept connections with or without PROXY protocol headers. <br /> If the PROXY protocol header is passed, then the version is determined automatically.<br />We recommend to use this option only for tests purposes, not in production.<br /> More information [here](#proxyprotocol-and-load-balancers). | - | No |
| `reusePort` | Enable `entryPoints` from the same or different processes listening on the same TCP/UDP port by utilizing the `SO_REUSEPORT` socket option. <br /> It also allows the kernel to act like a load balancer to distribute incoming connections between entry points..<br /> More information [here](#reuseport). | false | No |
| `transport.`<br />`respondingTimeouts.`<br />`readTimeout` | Set the timeouts for incoming requests to the Traefik instance. This is the maximum duration for reading the entire request, including the body. Setting them has no effect for UDP `entryPoints`.<br /> If zero, no timeout exists. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds. | 60s (seconds) | No |
| `transport.`<br />`respondingTimeouts.`<br />`writeTimeout` | Maximum duration before timing out writes of the response. <br /> It covers the time from the end of the request header read to the end of the response write. <br /> If zero, no timeout exists. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds. | 0s (seconds) | No |
| `transport.`<br />`respondingTimeouts.`<br />`idleTimeout` | Maximum duration an idle (keep-alive) connection will remain idle before closing itself. <br /> If zero, no timeout exists <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds | 180s (seconds) | No |
| `transport.`<br />`lifeCycle.`<br />`graceTimeOut` | Set the duration to give active requests a chance to finish before Traefik stops. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds <br /> In this time frame no new requests are accepted. | 10s (seconds) | No |
| `transport.`<br />`lifeCycle.`<br />`requestAcceptGraceTimeout` | Set the duration to keep accepting requests prior to initiating the graceful termination period (as defined by the `transportlifeCycle.graceTimeOut` option). <br /> This option is meant to give downstream load-balancers sufficient time to take Traefik out of rotation. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds | 0s (seconds) | No |
| `transport.`<br />`keepAliveMaxRequests` | Set the maximum number of requests Traefik can handle before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY). <br /> Zero means no limit. | 0 | No |
| `transport.`<br />`keepAliveMaxTime` | Set the maximum duration Traefik can handle requests before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY). Zero means no limit. | 0s (seconds) | No |
| `udp.timeout` | Define how long to wait on an idle session before releasing the related resources. <br />The Timeout value must be greater than zero. | 3s (seconds)| No |
| Field | Description | Default | Required |
|:----------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------|:---------|
| `address` | Define the port, and optionally the hostname, on which to listen for incoming connections and packets.<br /> It also defines the protocol to use (TCP or UDP).<br /> If no protocol is specified, the default is TCP. The format is:`[host]:port[/tcp\|/udp] | - | Yes |
| `asDefault` | Mark the `entryPoint` to be in the list of default `entryPoints`.<br /> `entryPoints`in this list are used (by default) on HTTP and TCP routers that do not define their own `entryPoints` option.<br /> More information [here](#asdefault). | false | No |
| `forwardedHeaders.trustedIPs` | Set the IPs or CIDR from where Traefik trusts the forwarded headers information (`X-Forwarded-*`). | - | No |
| `forwardedHeaders.insecure` | Set the insecure mode to always trust the forwarded headers information (`X-Forwarded-*`).<br />We recommend to use this option only for tests purposes, not in production. | false | No |
| `http.redirections.`<br />`entryPoint.to` | The target element to enable (permanent) redirecting of all incoming requests on an entry point to another one. <br /> The target element can be an entry point name (ex: `websecure`), or a port (`:443`). | - | Yes |
| `http.redirections.`<br />`entryPoint.scheme` | The target scheme to use for (permanent) redirection of all incoming requests. | https | No |
| `http.redirections.`<br />`entryPoint.permanent` | Enable permanent redirecting of all incoming requests on an entry point to another one changing the scheme. <br /> The target element, it can be an entry point name (ex: `websecure`), or a port (`:443`). | false | No |
| `http.redirections.`<br />`entryPoint.priority` | Default priority applied to the routers attached to the `entryPoint`. | MaxInt32-1 (2147483646) | No |
| `http.encodeQuerySemicolons` | Enable query semicolons encoding. <br /> Use this option to avoid non-encoded semicolons to be interpreted as query parameter separators by Traefik. <br /> When using this option, the non-encoded semicolons characters in query will be transmitted encoded to the backend.<br /> More information [here](#encodequerysemicolons). | false | No |
| `http.sanitizePath` | Defines whether to enable the request path sanitization.<br /> More information [here](#sanitizepath). | false | No |
| `http.middlewares` | Set the list of middlewares that are prepended by default to the list of middlewares of each router associated to the named entry point. <br />More information [here](#httpmiddlewares). | - | No |
| `http.tls` | Enable TLS on every router attached to the `entryPoint`. <br /> If no certificate are set, a default self-signed certificate is generates by Traefik. <br /> We recommend to not use self signed certificates in production. | - | No |
| `http.tls.options` | Apply TLS options on every router attached to the `entryPoint`. <br /> The TLS options can be overidden per router. <br /> More information in the [dedicated section](../../routing/providers/kubernetes-crd.md#kind-tlsoption). | - | No |
| `http.tls.certResolver` | Apply a certificate resolver on every router attached to the `entryPoint`. <br /> The TLS options can be overidden per router. <br /> More information in the [dedicated section](../install-configuration/tls/certificate-resolvers/overview.md). | - | No |
| `http2.maxConcurrentStreams` | Set the number of concurrent streams per connection that each client is allowed to initiate. <br /> The value must be greater than zero. | 250 | No |
| `http3` | Enable HTTP/3 protocol on the `entryPoint`. <br /> HTTP/3 requires a TCP `entryPoint`. as HTTP/3 always starts as a TCP connection that then gets upgraded to UDP. In most scenarios, this `entryPoint` is the same as the one used for TLS traffic.<br /> More information [here](#http3. | - | No |
| `http3.advertisedPort` | Set the UDP port to advertise as the HTTP/3 authority. <br /> It defaults to the entryPoint's address port. <br /> It can be used to override the authority in the `alt-svc` header, for example if the public facing port is different from where Traefik is listening. | - | No |
| `observability.accessLogs` | Defines whether a router attached to this EntryPoint produces access-logs by default. Nonetheless, a router defining its own observability configuration will opt-out from this default. | true | No |
| `observability.metrics` | Defines whether a router attached to this EntryPoint produces metrics by default. Nonetheless, a router defining its own observability configuration will opt-out from this default. | true | No |
| `observability.tracing` | Defines whether a router attached to this EntryPoint produces traces by default. Nonetheless, a router defining its own observability configuration will opt-out from this default. | true | No |
| `observability.traceVerbosity` | Defines the tracing verbosity level for routers attached to this EntryPoint. Possible values: `minimal` (default), `detailed`. Routers can override this value in their own observability configuration. <br /> More information [here](#traceverbosity). | minimal | No |
| `proxyProtocol.trustedIPs` | Enable PROXY protocol with Trusted IPs. <br /> Traefik supports [PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2. <br /> If PROXY protocol header parsing is enabled for the entry point, this entry point can accept connections with or without PROXY protocol headers. <br /> If the PROXY protocol header is passed, then the version is determined automatically.<br /> More information [here](#proxyprotocol-and-load-balancers). | - | No |
| `proxyProtocol.insecure` | Enable PROXY protocol trusting every incoming connection. <br /> Every remote client address will be replaced (`trustedIPs`) won't have any effect). <br /> Traefik supports [PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2. <br /> If PROXY protocol header parsing is enabled for the entry point, this entry point can accept connections with or without PROXY protocol headers. <br /> If the PROXY protocol header is passed, then the version is determined automatically.<br />We recommend to use this option only for tests purposes, not in production.<br /> More information [here](#proxyprotocol-and-load-balancers). | - | No |
| `reusePort` | Enable `entryPoints` from the same or different processes listening on the same TCP/UDP port by utilizing the `SO_REUSEPORT` socket option. <br /> It also allows the kernel to act like a load balancer to distribute incoming connections between entry points.<br /> More information [here](#reuseport). | false | No |
| `transport.`<br />`respondingTimeouts.`<br />`readTimeout` | Set the timeouts for incoming requests to the Traefik instance. This is the maximum duration for reading the entire request, including the body. Setting them has no effect for UDP `entryPoints`.<br /> If zero, no timeout exists. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds. | 60s (seconds) | No |
| `transport.`<br />`respondingTimeouts.`<br />`writeTimeout` | Maximum duration before timing out writes of the response. <br /> It covers the time from the end of the request header read to the end of the response write. <br /> If zero, no timeout exists. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds. | 0s (seconds) | No |
| `transport.`<br />`respondingTimeouts.`<br />`idleTimeout` | Maximum duration an idle (keep-alive) connection will remain idle before closing itself. <br /> If zero, no timeout exists <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds | 180s (seconds) | No |
| `transport.`<br />`lifeCycle.`<br />`graceTimeOut` | Set the duration to give active requests a chance to finish before Traefik stops. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds <br /> In this time frame no new requests are accepted. | 10s (seconds) | No |
| `transport.`<br />`lifeCycle.`<br />`requestAcceptGraceTimeout` | Set the duration to keep accepting requests prior to initiating the graceful termination period (as defined by the `transportlifeCycle.graceTimeOut` option). <br /> This option is meant to give downstream load-balancers sufficient time to take Traefik out of rotation. <br />Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).<br />If no units are provided, the value is parsed assuming seconds | 0s (seconds) | No |
| `transport.`<br />`keepAliveMaxRequests` | Set the maximum number of requests Traefik can handle before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY). <br /> Zero means no limit. | 0 | No |
| `transport.`<br />`keepAliveMaxTime` | Set the maximum duration Traefik can handle requests before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY). Zero means no limit. | 0s (seconds) | No |
| `udp.timeout` | Define how long to wait on an idle session before releasing the related resources. <br />The Timeout value must be greater than zero. | 3s (seconds) | No |
### asDefault
@ -213,7 +214,7 @@ only routers with TLS enabled will be usable with HTTP/3.
### ProxyProtocol and Load-Balancers
The replacement of the remote client address will occur only for IP addresses listed in `trustedIPs`. This is where yoåu specify your load balancer IPs or CIDR ranges.
The replacement of the remote client address will occur only for IP addresses listed in `trustedIPs`. This is where you specify your load balancer IPs or CIDR ranges.
When queuing Traefik behind another load-balancer, make sure to configure
PROXY protocol on both sides.
@ -271,3 +272,13 @@ Use the `reusePort` option with the other option `transport.lifeCycle.gracetimeo
to do
canary deployments against Traefik itself. Like upgrading Traefik version
or reloading the static configuration without any service downtime.
#### Trace Verbosity
`observability.traceVerbosity` defines the tracing verbosity level for routers attached to this EntryPoint.
Routers can override this value in their own observability configuration.
Possible values are:
- `minimal`: produces a single server span and one client span for each request processed by a router.
- `detailed`: enables the creation of additional spans for each middleware executed for each request processed by a router.

View File

@ -27,16 +27,6 @@ $ traefik healthcheck
OK: http://:8082/ping
```
### URL Option
The URL to check can be specified with the `--url` flag, which defaults to `http://localhost:8080/ping`.
Example:
```sh
traefik healthcheck --url=http://localhost:8080/ping
```
## Ping
The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`.

View File

@ -96,25 +96,27 @@ log:
#### Configuration Options
| Field | Description | Default | Required |
|:-----------|:-----------------------------------------------------------------------------|:--------|:---------|
| `log.otlp.http` | This instructs the exporter to send logs to the OpenTelemetry Collector using HTTP.| | No |
| `log.otlp.http.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<scheme>://<host>:<port><path>`) | `https://localhost:4318/v1/logs` | No |
| `log.otlp.http.headers` | Additional headers sent with logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `log.otlp.http.tls` | Defines the Client TLS configuration used by the exporter to send logs to the OpenTelemetry Collector. | | No |
| `log.otlp.http.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `log.otlp.http.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `log.otlp.http.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `log.otlp.http.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
| `log.otlp.grpc` | This instructs the exporter to send logs to the OpenTelemetry Collector using gRPC.| | No |
| `log.otlp.grpc.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<host>:<port>`) | `localhost:4317` | No |
| `log.otlp.grpc.headers` | Additional headers sent with logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `log.otlp.grpc.insecure` | Instructs the exporter to send logs to the OpenTelemetry Collector using an insecure protocol. | false | No |
| `log.otlp.grpc.tls` | Defines the Client TLS configuration used by the exporter to send logs to the OpenTelemetry Collector. | | No |
| `log.otlp.grpc.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `log.otlp.grpc.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `log.otlp.grpc.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `log.otlp.grpc.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
| Field | Description | Default | Required |
|:---------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------|:---------|
| `log.otlp.serviceName` | Service name used in selected backend. | "traefik" | No |
| `log.otlp.resourceAttributes` | Defines additional resource attributes to be sent to the collector. | [] | No |
| `log.otlp.http` | This instructs the exporter to send logs to the OpenTelemetry Collector using HTTP. | | No |
| `log.otlp.http.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<scheme>://<host>:<port><path>`) | `https://localhost:4318/v1/logs` | No |
| `log.otlp.http.headers` | Additional headers sent with logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `log.otlp.http.tls` | Defines the Client TLS configuration used by the exporter to send logs to the OpenTelemetry Collector. | | No |
| `log.otlp.http.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `log.otlp.http.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `log.otlp.http.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `log.otlp.http.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
| `log.otlp.grpc` | This instructs the exporter to send logs to the OpenTelemetry Collector using gRPC. | | No |
| `log.otlp.grpc.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<host>:<port>`) | `localhost:4317` | No |
| `log.otlp.grpc.headers` | Additional headers sent with logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `log.otlp.grpc.insecure` | Instructs the exporter to send logs to the OpenTelemetry Collector using an insecure protocol. | false | No |
| `log.otlp.grpc.tls` | Defines the Client TLS configuration used by the exporter to send logs to the OpenTelemetry Collector. | | No |
| `log.otlp.grpc.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `log.otlp.grpc.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `log.otlp.grpc.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `log.otlp.grpc.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
## AccessLogs
@ -256,25 +258,27 @@ accesslog:
#### Configuration Options
| Field | Description | Default | Required |
|:-----------|:--------------------------|:--------|:---------|
| `accesslog.otlp.http` | This instructs the exporter to send access logs to the OpenTelemetry Collector using HTTP.| | No |
| `accesslog.otlp.http.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<scheme>://<host>:<port><path>`) | `https://localhost:4318/v1/logs` | No |
| `accesslog.otlp.http.headers` | Additional headers sent with access logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `accesslog.otlp.http.tls` | Defines the Client TLS configuration used by the exporter to send access logs to the OpenTelemetry Collector. | | No |
| `accesslog.otlp.http.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `accesslog.otlp.http.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.http.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.http.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
| `accesslog.otlp.grpc` | This instructs the exporter to send access logs to the OpenTelemetry Collector using gRPC.| | No |
| `accesslog.otlp.grpc.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<host>:<port>`) | `localhost:4317` | No |
| `accesslog.otlp.grpc.headers` | Additional headers sent with access logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `accesslog.otlp.grpc.insecure` | Instructs the exporter to send access logs to the OpenTelemetry Collector using an insecure protocol. | false | No |
| `accesslog.otlp.grpc.tls` | Defines the Client TLS configuration used by the exporter to send access logs to the OpenTelemetry Collector. | | No |
| `accesslog.otlp.grpc.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `accesslog.otlp.grpc.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.grpc.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.grpc.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
| Field | Description | Default | Required |
|:---------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------|:---------|
| `accesslog.otlp.serviceName` | Defines the service name resource attribute. | "traefik" | No |
| `accesslog.otlp.resourceAttributes` | Defines additional resource attributes to be sent to the collector. | [] | No |
| `accesslog.otlp.http` | This instructs the exporter to send access logs to the OpenTelemetry Collector using HTTP. | | No |
| `accesslog.otlp.http.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<scheme>://<host>:<port><path>`) | `https://localhost:4318/v1/logs` | No |
| `accesslog.otlp.http.headers` | Additional headers sent with access logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `accesslog.otlp.http.tls` | Defines the Client TLS configuration used by the exporter to send access logs to the OpenTelemetry Collector. | | No |
| `accesslog.otlp.http.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `accesslog.otlp.http.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.http.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.http.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
| `accesslog.otlp.grpc` | This instructs the exporter to send access logs to the OpenTelemetry Collector using gRPC. | | No |
| `accesslog.otlp.grpc.endpoint` | The endpoint of the OpenTelemetry Collector. (format=`<host>:<port>`) | `localhost:4317` | No |
| `accesslog.otlp.grpc.headers` | Additional headers sent with access logs by the exporter to the OpenTelemetry Collector. | [ ] | No |
| `accesslog.otlp.grpc.insecure` | Instructs the exporter to send access logs to the OpenTelemetry Collector using an insecure protocol. | false | No |
| `accesslog.otlp.grpc.tls` | Defines the Client TLS configuration used by the exporter to send access logs to the OpenTelemetry Collector. | | No |
| `accesslog.otlp.grpc.tls.ca` | The path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | | No |
| `accesslog.otlp.grpc.tls.cert` | The path to the certificate to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.grpc.tls.key` | The path to the key to use for the OpenTelemetry Collector. | | No |
| `accesslog.otlp.grpc.tls.insecureSkipVerify` | Instructs the OpenTelemetry Collector to accept any certificate presented by the server regardless of the hostname in the certificate. | false | No |
### CLF format fields

View File

@ -60,29 +60,31 @@ metrics:
### Configuration Options
| Field | Description | Default | Required |
|:-----------|---------------|:--------|:---------|
| `metrics.addInternals` | Enables metrics for internal resources (e.g.: `ping@internal`). | false | No |
| `metrics.otlp.addEntryPointsLabels` | Enable metrics on entry points. | true | No |
| `metrics.otlp.addRoutersLabels` | Enable metrics on routers. | false | No |
| `metrics.otlp.addServicesLabels` | Enable metrics on services.| true | No |
| `metrics.otlp.explicitBoundaries` | Explicit boundaries for Histogram data points. | ".005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10" | No |
| `metrics.otlp.pushInterval` | Interval at which metrics are sent to the OpenTelemetry Collector. | 10s | No |
| `metrics.otlp.http` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `metrics.otlp.http.endpoint` | URL of the OpenTelemetry Collector to send metrics to.<br /> Format="`<scheme>://<host>:<port><path>`" | "http://localhost:4318/v1/metrics" | Yes |
| `metrics.otlp.http.headers` | Additional headers sent with metrics by the exporter to the OpenTelemetry Collector. | - | No |
| `metrics.otlp.http.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector,<br />it defaults to the system bundle. | "" | No |
| `metrics.otlp.http.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector.<br />When using this option, setting the `key` option is required. | "" | No |
| `metrics.otlp.http.tls.key` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `metrics.otlp.http.tls.insecureskipverify` | Allow the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |
| `metrics.otlp.grpc` | This instructs the exporter to send metrics to the OpenTelemetry Collector using gRPC. | null/false | No |
| `metrics.otlp.grpc.endpoint` | Address of the OpenTelemetry Collector to send metrics to.<br /> Format="`<host>:<port>`" | "localhost:4317" | Yes |
| `metrics.otlp.grpc.headers` | Additional headers sent with metrics by the exporter to the OpenTelemetry Collector. | - | No |
| `metrics.otlp.http.grpc.insecure` |Allows exporter to send metrics to the OpenTelemetry Collector without using a secured protocol. | false | Yes |
| `metrics.otlp.grpc.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector,<br />it defaults to the system bundle. | - | No |
| `metrics.otlp.grpc.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector.<br />When using this option, setting the `key` option is required. | - | No |
| `metrics.otlp.grpc.tls.key` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `metrics.otlp.grpc.tls.insecureskipverify` | Allow the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |
| Field | Description | Default | Required |
|:-------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------|:---------|
| `metrics.addInternals` | Enables metrics for internal resources (e.g.: `ping@internal`). | false | No |
| `metrics.otlp.serviceName` | Defines the service name resource attribute. | "traefik" | No |
| `metrics.otlp.resourceAttributes` | Defines additional resource attributes to be sent to the collector. | [] | No |
| `metrics.otlp.addEntryPointsLabels` | Enable metrics on entry points. | true | No |
| `metrics.otlp.addRoutersLabels` | Enable metrics on routers. | false | No |
| `metrics.otlp.addServicesLabels` | Enable metrics on services. | true | No |
| `metrics.otlp.explicitBoundaries` | Explicit boundaries for Histogram data points. | ".005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10" | No |
| `metrics.otlp.pushInterval` | Interval at which metrics are sent to the OpenTelemetry Collector. | 10s | No |
| `metrics.otlp.http` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `metrics.otlp.http.endpoint` | URL of the OpenTelemetry Collector to send metrics to.<br /> Format="`<scheme>://<host>:<port><path>`" | "http://localhost:4318/v1/metrics" | Yes |
| `metrics.otlp.http.headers` | Additional headers sent with metrics by the exporter to the OpenTelemetry Collector. | - | No |
| `metrics.otlp.http.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector,<br />it defaults to the system bundle. | "" | No |
| `metrics.otlp.http.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector.<br />When using this option, setting the `key` option is required. | "" | No |
| `metrics.otlp.http.tls.key` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `metrics.otlp.http.tls.insecureskipverify` | Allow the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |
| `metrics.otlp.grpc` | This instructs the exporter to send metrics to the OpenTelemetry Collector using gRPC. | null/false | No |
| `metrics.otlp.grpc.endpoint` | Address of the OpenTelemetry Collector to send metrics to.<br /> Format="`<host>:<port>`" | "localhost:4317" | Yes |
| `metrics.otlp.grpc.headers` | Additional headers sent with metrics by the exporter to the OpenTelemetry Collector. | - | No |
| `metrics.otlp.http.grpc.insecure` | Allows exporter to send metrics to the OpenTelemetry Collector without using a secured protocol. | false | Yes |
| `metrics.otlp.grpc.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector,<br />it defaults to the system bundle. | - | No |
| `metrics.otlp.grpc.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector.<br />When using this option, setting the `key` option is required. | - | No |
| `metrics.otlp.grpc.tls.key` | This instructs the exporter to send the metrics to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `metrics.otlp.grpc.tls.insecureskipverify` | Allow the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |
## Vendors

View File

@ -36,27 +36,27 @@ tracing: {}
## Configuration Options
| Field | Description | Default | Required |
|:-------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------|:---------|
| `tracing.addInternals` | Enables tracing for internal resources (e.g.: `ping@internal`). | false | No |
| `tracing.serviceName` | Service name used in selected backend. | "traefik" | No |
| `tracing.sampleRate` | The proportion of requests to trace, specified between 0.0 and 1.0. | 1.0 | No |
| `tracing.resourceAttributes` | Defines additional resource attributes to be sent to the collector. | [] | No |
| `tracing.capturedRequestHeaders` | Defines the list of request headers to add as attributes.<br />It applies to client and server kind spans.| [] | No |
| `tracing.capturedResponseHeaders` | Defines the list of response headers to add as attributes.<br />It applies to client and server kind spans.| [] |False |
| `tracing.safeQueryParams` | By default, all query parameters are redacted.<br />Defines the list of query parameters to not redact. | [] | No |
| `tracing.otlp.http` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `tracing.otlp.http.endpoint` | URL of the OpenTelemetry Collector to send tracing to.<br /> Format="`<scheme>://<host>:<port><path>`" | "http://localhost:4318/v1/tracing" | Yes |
| `tracing.otlp.http.headers` | Additional headers sent with tracing by the exporter to the OpenTelemetry Collector. | | No |
| `tracing.otlp.http.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | "" | No |
| `tracing.otlp.http.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector. When using this option, setting the `key` option is required. | "" | No |
| `tracing.otlp.http.tls.key` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | ""null/false "" | No |
| `tracing.otlp.http.tls.insecureskipverify` |If `insecureSkipVerify` is `true`, the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |
| `tracing.otlp.grpc` | This instructs the exporter to send tracing to the OpenTelemetry Collector using gRPC. | false | No |
| `tracing.otlp.grpc.endpoint` | Address of the OpenTelemetry Collector to send tracing to.<br /> Format="`<host>:<port>`" | "localhost:4317" | Yes |
| `tracing.otlp.grpc.headers` | Additional headers sent with tracing by the exporter to the OpenTelemetry Collector. | [] | No |
| `tracing.otlp.grpc.insecure` |Allows exporter to send tracing to the OpenTelemetry Collector without using a secured protocol. | false | Yes |
| `tracing.otlp.grpc.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | "" | No |
| `tracing.otlp.grpc.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector. When using this option, setting the `key` option is required. | "" | No |
| `tracing.otlp.grpc.tls.key` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | ""null/false "" | No |
| `tracing.otlp.grpc.tls.insecureskipverify` |If `insecureSkipVerify` is `true`, the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |
| Field | Description | Default | Required |
|:-------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------|:---------|
| `tracing.addInternals` | Enables tracing for internal resources (e.g.: `ping@internal`). | false | No |
| `tracing.serviceName` | Defines the service name resource attribute. | "traefik" | No |
| `tracing.resourceAttributes` | Defines additional resource attributes to be sent to the collector. | [] | No |
| `tracing.sampleRate` | The proportion of requests to trace, specified between 0.0 and 1.0. | 1.0 | No |
| `tracing.capturedRequestHeaders` | Defines the list of request headers to add as attributes.<br />It applies to client and server kind spans. | [] | No |
| `tracing.capturedResponseHeaders` | Defines the list of response headers to add as attributes.<br />It applies to client and server kind spans. | [] | False |
| `tracing.safeQueryParams` | By default, all query parameters are redacted.<br />Defines the list of query parameters to not redact. | [] | No |
| `tracing.otlp.http` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | null/false | No |
| `tracing.otlp.http.endpoint` | URL of the OpenTelemetry Collector to send tracing to.<br /> Format="`<scheme>://<host>:<port><path>`" | "http://localhost:4318/v1/tracing" | Yes |
| `tracing.otlp.http.headers` | Additional headers sent with tracing by the exporter to the OpenTelemetry Collector. | | No |
| `tracing.otlp.http.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | "" | No |
| `tracing.otlp.http.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector. When using this option, setting the `key` option is required. | "" | No |
| `tracing.otlp.http.tls.key` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | ""null/false "" | No |
| `tracing.otlp.http.tls.insecureskipverify` | If `insecureSkipVerify` is `true`, the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |
| `tracing.otlp.grpc` | This instructs the exporter to send tracing to the OpenTelemetry Collector using gRPC. | false | No |
| `tracing.otlp.grpc.endpoint` | Address of the OpenTelemetry Collector to send tracing to.<br /> Format="`<host>:<port>`" | "localhost:4317" | Yes |
| `tracing.otlp.grpc.headers` | Additional headers sent with tracing by the exporter to the OpenTelemetry Collector. | [] | No |
| `tracing.otlp.grpc.insecure` | Allows exporter to send tracing to the OpenTelemetry Collector without using a secured protocol. | false | Yes |
| `tracing.otlp.grpc.tls.ca` | Path to the certificate authority used for the secure connection to the OpenTelemetry Collector, it defaults to the system bundle. | "" | No |
| `tracing.otlp.grpc.tls.cert` | Path to the public certificate used for the secure connection to the OpenTelemetry Collector. When using this option, setting the `key` option is required. | "" | No |
| `tracing.otlp.grpc.tls.key` | This instructs the exporter to send the tracing to the OpenTelemetry Collector using HTTP.<br /> Setting the sub-options with their default values. | ""null/false "" | No |
| `tracing.otlp.grpc.tls.insecureskipverify` | If `insecureSkipVerify` is `true`, the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. | false | Yes |

View File

@ -270,6 +270,10 @@ created. If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions,
as well as the usual boolean logic, as shown in examples below.
!!! tip "Constraints key limitations"
Note that `traefik.*` is a reserved label namespace for configuration and can not be used as a key for custom constraints.
??? example "Constraints Expression Examples"
```toml

View File

@ -112,6 +112,10 @@ created. If the expression is empty, all detected services are included.
The expression syntax is based on the ```Tag(`tag`)```, and ```TagRegex(`tag`)``` functions,
as well as the usual boolean logic, as shown in examples below.
!!! tip "Constraints key limitations"
Note that `traefik.*` is a reserved label namespace for configuration and can not be used as a key for custom constraints.
??? example "Constraints Expression Examples"
```toml

View File

@ -191,6 +191,10 @@ created. If the expression is empty, all detected services are included.
The expression syntax is based on the ```Tag(`tag`)```, and ```TagRegex(`tag`)``` functions,
as well as the usual boolean logic, as shown in examples below.
!!! tip "Constraints key limitations"
Note that `traefik.*` is a reserved label namespace for configuration and can not be used as a key for custom constraints.
??? example "Constraints Expression Examples"
```toml

View File

@ -49,6 +49,10 @@ If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions,
as well as the usual boolean logic, as shown in examples below.
!!! tip "Constraints key limitations"
Note that `traefik.*` is a reserved label namespace for configuration and can not be used as a key for custom constraints.
??? example "Constraints Expression Examples"
```toml

View File

@ -276,6 +276,10 @@ created. If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions,
as well as the usual boolean logic, as shown in examples below.
!!! tip "Constraints key limitations"
Note that `traefik.*` is a reserved label namespace for configuration and can not be used as a key for custom constraints.
??? example "Constraints Expression Examples"
```toml

View File

@ -36,6 +36,7 @@ http:
metrics: false
accessLogs: false
tracing: false
traceVerbosity: detailed
```
```yaml tab="Structured (TOML)"
@ -47,6 +48,7 @@ http:
metrics = false
accessLogs = false
tracing = false
traceVerbosity = "detailed"
```
```yaml tab="Labels"
@ -56,6 +58,7 @@ labels:
- "traefik.http.routers.my-router.observability.metrics=false"
- "traefik.http.routers.my-router.observability.accessLogs=false"
- "traefik.http.routers.my-router.observability.tracing=false"
- "traefik.http.routers.my-router.observability.traceVerbosity=detailed"
```
```json tab="Tags"
@ -66,15 +69,26 @@ labels:
"traefik.http.routers.my-router.service=service-foo",
"traefik.http.routers.my-router.observability.metrics=false",
"traefik.http.routers.my-router.observability.accessLogs=false",
"traefik.http.routers.my-router.observability.tracing=false"
"traefik.http.routers.my-router.observability.tracing=false",
"traefik.http.routers.my-router.observability.traceVerbosity=detailed"
]
}
```
## Configuration Options
| Field | Description | Default | Required |
|:------|:------------|:--------|:---------|
| `accessLogs` | The `accessLogs` option controls whether the router will produce access-logs. | `true` | No |
| `metrics` | The `metrics` option controls whether the router will produce metrics. | `true` | No |
| `tracing` | The `tracing` option controls whether the router will produce traces. | `true` | No |
| Field | Description | Default | Required |
|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------|:---------|
| `accessLogs` | The `accessLogs` option controls whether the router will produce access-logs. | `true` | No |
| `metrics` | The `metrics` option controls whether the router will produce metrics. | `true` | No |
| `tracing` | The `tracing` option controls whether the router will produce traces. | `true` | No |
| `traceVerbosity` | The `traceVerbosity` option controls the tracing verbosity level for the router. Possible values: `minimal` (default), `detailed`. If not set, the value is inherited from the entryPoint. | `minimal` | No |
#### traceVerbosity
`observability.traceVerbosity` defines the tracing verbosity level for the router.
Possible values are:
- `minimal`: produces a single server span and one client span for each request processed by a router.
- `detailed`: enables the creation of additional spans for each middleware executed for each request processed by a router.

View File

@ -106,7 +106,7 @@ tls:
### Curve Preferences
This option allows to set the preferred elliptic curves in a specific order.
This option allows to set the preferred elliptic curves.
The names of the curves defined by [`crypto`](https://godoc.org/crypto/tls#CurveID) (e.g. `CurveP521`) and the [RFC defined names](https://tools.ietf.org/html/rfc8446#section-4.2.7) (e. g. `secp521r1`) can be used.

View File

@ -51,7 +51,7 @@ spec:
| `minVersion` | Minimum TLS version that is acceptable. | "VersionTLS12" | No |
| `maxVersion` | Maximum TLS version that is acceptable.<br />We do not recommend setting this option to disable TLS 1.3. | | No |
| `cipherSuites` | List of supported [cipher suites](https://godoc.org/crypto/tls#pkg-constants) for TLS versions up to TLS 1.2.<br />[Cipher suites defined for TLS 1.2 and below cannot be used in TLS 1.3, and vice versa.](https://tools.ietf.org/html/rfc8446)<br />With TLS 1.3, [the cipher suites are not configurable](https://golang.org/doc/go1.12#tls_1_3) (all supported cipher suites are safe in this case). | | No |
| `curvePreferences` | List of the elliptic curves references that will be used in an ECDHE handshake, in preference order.<br />Use curves names from [`crypto`](https://godoc.org/crypto/tls#CurveID) or the [RFC](https://tools.ietf.org/html/rfc8446#section-4.2.7).<br />See [CurveID](https://godoc.org/crypto/tls#CurveID) for more information. | | No |
| `curvePreferences` | List of the elliptic curves references that will be used in an ECDHE handshake.<br />Use curves names from [`crypto`](https://godoc.org/crypto/tls#CurveID) or the [RFC](https://tools.ietf.org/html/rfc8446#section-4.2.7).<br />See [CurveID](https://godoc.org/crypto/tls#CurveID) for more information. | | No |
| `clientAuth.secretNames` | Client Authentication (mTLS) option.<br />List of names of the referenced Kubernetes [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) (in TLSOption namespace).<br /> The secret must contain a certificate under either a `tls.ca` or a `ca.crt` key. | | No |
| `clientAuth.clientAuthType` | Client Authentication (mTLS) option.<br />Client authentication type to apply. Available values [here](#client-authentication-mtls). | | No |
| `sniStrict` | Allow rejecting connections from clients connections that do not specify a server_name extension.<br />The [default certificate](../../../http/tls/tls-certificates.md#default-certificate) is never served is the option is enabled. | false | No |
@ -60,7 +60,7 @@ spec:
### Client Authentication (mTLS)
The `clientAuth.clientAuthType` option governs the behaviour as follows:
The `clientAuth.clientAuthType` option governs the behavior as follows:
- `NoClientCert`: disregards any client certificate.
- `RequestClientCert`: asks for a certificate but proceeds anyway if none is provided.

View File

@ -296,99 +296,107 @@ Limitations or behavioral differences are indicated where relevant.
### Unsupported NGINX Annotations
All other NGINX annotations not listed above, including but not limited to:
!!! question "Want to Add Support for More Annotations?"
You can help extend support in two ways:
- [**Open a PR**](../../../contributing/submitting-pull-requests.md) with the new annotation support.
- **Reach out** to the [Traefik Labs support team](https://info.traefik.io/request-commercial-support?cta=doc).
All contributions and suggestions are welcome — let's build this together!
| Annotation | Notes |
|-----------------------------------------------------------------------------|------------------------------------------------------|
| `nginx.ingress.kubernetes.io/app-root` | Not supported. |
| `nginx.ingress.kubernetes.io/affinity-canary-behavior` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-tls-secret` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-tls-verify-depth` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-tls-verify-client` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-tls-error-page` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-tls-match-cn` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-cache-key` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-cache-duration` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-keepalive` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-keepalive-share-vars` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-keepalive-requests` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-keepalive-timeout` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-proxy-set-headers` | Not supported. |
| `nginx.ingress.kubernetes.io/auth-snippet` | Not supported. |
| `nginx.ingress.kubernetes.io/enable-global-auth` | Not supported. |
| `nginx.ingress.kubernetes.io/canary` | Not supported. |
| `nginx.ingress.kubernetes.io/canary-by-header` | Not supported. |
| `nginx.ingress.kubernetes.io/canary-by-header-value` | Not supported. |
| `nginx.ingress.kubernetes.io/canary-by-header-pattern` | Not supported. |
| `nginx.ingress.kubernetes.io/canary-by-cookie` | Not supported. |
| `nginx.ingress.kubernetes.io/canary-weight` | Not supported. |
| `nginx.ingress.kubernetes.io/canary-weight-total` | Not supported. |
| `nginx.ingress.kubernetes.io/client-body-buffer-size` | Not supported. |
| `nginx.ingress.kubernetes.io/configuration-snippet` | Not supported. |
| `nginx.ingress.kubernetes.io/custom-http-errors` | Not supported. |
| `nginx.ingress.kubernetes.io/disable-proxy-intercept-errors` | Not supported. |
| `nginx.ingress.kubernetes.io/default-backend` | Not supported; use `defaultBackend` in Ingress spec. |
| `nginx.ingress.kubernetes.io/limit-rate-after` | Not supported. |
| `nginx.ingress.kubernetes.io/limit-rate` | Not supported. |
| `nginx.ingress.kubernetes.io/limit-whitelist` | Not supported. |
| `nginx.ingress.kubernetes.io/limit-rps` | Not supported. |
| `nginx.ingress.kubernetes.io/limit-rpm` | Not supported. |
| `nginx.ingress.kubernetes.io/limit-burst-multiplier` | Not supported. |
| `nginx.ingress.kubernetes.io/limit-connections` | Not supported. |
| `nginx.ingress.kubernetes.io/global-rate-limit` | Not supported. |
| `nginx.ingress.kubernetes.io/global-rate-limit-window` | Not supported. |
| `nginx.ingress.kubernetes.io/global-rate-limit-key` | Not supported. |
| `nginx.ingress.kubernetes.io/global-rate-limit-ignored-cidrs` | Not supported. |
| `nginx.ingress.kubernetes.io/permanent-redirect` | Not supported. |
| `nginx.ingress.kubernetes.io/permanent-redirect-code` | Not supported. |
| `nginx.ingress.kubernetes.io/temporal-redirect` | Not supported. |
| `nginx.ingress.kubernetes.io/preserve-trailing-slash` | Not supported; Traefik preserves by default. |
| `nginx.ingress.kubernetes.io/proxy-cookie-domain` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-cookie-path` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-connect-timeout` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-send-timeout` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-read-timeout` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-next-upstream` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-next-upstream-timeout` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-next-upstream-tries` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-request-buffering` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-redirect-from` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-redirect-to` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-http-version` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-ssl-ciphers` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-ssl-verify-depth` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-ssl-protocols` | Not supported. |
| `nginx.ingress.kubernetes.io/enable-rewrite-log` | Not supported. |
| `nginx.ingress.kubernetes.io/rewrite-target` | Not supported. |
| `nginx.ingress.kubernetes.io/satisfy` | Not supported. |
| `nginx.ingress.kubernetes.io/server-alias` | Not supported. |
| `nginx.ingress.kubernetes.io/server-snippet` | Not supported. |
| `nginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none` | Not supported. |
| `nginx.ingress.kubernetes.io/session-cookie-expires` | Not supported. |
| `nginx.ingress.kubernetes.io/session-cookie-change-on-failure` | Not supported. |
| `nginx.ingress.kubernetes.io/ssl-ciphers` | Not supported. |
| `nginx.ingress.kubernetes.io/ssl-prefer-server-ciphers` | Not supported. |
| `nginx.ingress.kubernetes.io/connection-proxy-header` | Not supported. |
| `nginx.ingress.kubernetes.io/enable-access-log` | Not supported. |
| `nginx.ingress.kubernetes.io/enable-opentracing` | Not supported. |
| `nginx.ingress.kubernetes.io/opentracing-trust-incoming-span` | Not supported. |
| `nginx.ingress.kubernetes.io/enable-opentelemetry` | Not supported. |
| `nginx.ingress.kubernetes.io/opentelemetry-trust-incoming-span` | Not supported. |
| `nginx.ingress.kubernetes.io/enable-modsecurity` | Not supported. |
| `nginx.ingress.kubernetes.io/enable-owasp-core-rules` | Not supported. |
| `nginx.ingress.kubernetes.io/modsecurity-transaction-id` | Not supported. |
| `nginx.ingress.kubernetes.io/modsecurity-snippet` | Not supported. |
| `nginx.ingress.kubernetes.io/mirror-request-body` | Not supported. |
| `nginx.ingress.kubernetes.io/mirror-target` | Not supported. |
| `nginx.ingress.kubernetes.io/mirror-host` | Not supported. |
| `nginx.ingress.kubernetes.io/x-forwarded-prefix` | Not supported. |
| `nginx.ingress.kubernetes.io/upstream-hash-by` | Not supported. |
| `nginx.ingress.kubernetes.io/upstream-vhost` | Not supported. |
| `nginx.ingress.kubernetes.io/denylist-source-range` | Not supported. |
| `nginx.ingress.kubernetes.io/whitelist-source-range` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-buffering` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-buffers-number` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-buffer-size` | Not supported. |
| `nginx.ingress.kubernetes.io/proxy-max-temp-file-size` | Not supported. |
| `nginx.ingress.kubernetes.io/stream-snippet` | Not supported. |
| `nginx.ingress.kubernetes.io/app-root` | Not supported yet. |
| `nginx.ingress.kubernetes.io/affinity-canary-behavior` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-tls-secret` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-tls-verify-depth` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-tls-verify-client` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-tls-error-page` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-tls-match-cn` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-cache-key` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-cache-duration` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-keepalive` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-keepalive-share-vars` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-keepalive-requests` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-keepalive-timeout` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-proxy-set-headers` | Not supported yet. |
| `nginx.ingress.kubernetes.io/auth-snippet` | Not supported yet. |
| `nginx.ingress.kubernetes.io/enable-global-auth` | Not supported yet. |
| `nginx.ingress.kubernetes.io/canary` | Not supported yet. |
| `nginx.ingress.kubernetes.io/canary-by-header` | Not supported yet. |
| `nginx.ingress.kubernetes.io/canary-by-header-value` | Not supported yet. |
| `nginx.ingress.kubernetes.io/canary-by-header-pattern` | Not supported yet. |
| `nginx.ingress.kubernetes.io/canary-by-cookie` | Not supported yet. |
| `nginx.ingress.kubernetes.io/canary-weight` | Not supported yet. |
| `nginx.ingress.kubernetes.io/canary-weight-total` | Not supported yet. |
| `nginx.ingress.kubernetes.io/client-body-buffer-size` | Not supported yet. |
| `nginx.ingress.kubernetes.io/configuration-snippet` | Not supported yet. |
| `nginx.ingress.kubernetes.io/custom-http-errors` | Not supported yet. |
| `nginx.ingress.kubernetes.io/disable-proxy-intercept-errors` | Not supported yet. |
| `nginx.ingress.kubernetes.io/default-backend` | Not supported yet; use `defaultBackend` in Ingress spec. |
| `nginx.ingress.kubernetes.io/limit-rate-after` | Not supported yet. |
| `nginx.ingress.kubernetes.io/limit-rate` | Not supported yet. |
| `nginx.ingress.kubernetes.io/limit-whitelist` | Not supported yet. |
| `nginx.ingress.kubernetes.io/limit-rps` | Not supported yet. |
| `nginx.ingress.kubernetes.io/limit-rpm` | Not supported yet. |
| `nginx.ingress.kubernetes.io/limit-burst-multiplier` | Not supported yet. |
| `nginx.ingress.kubernetes.io/limit-connections` | Not supported yet. |
| `nginx.ingress.kubernetes.io/global-rate-limit` | Not supported yet. |
| `nginx.ingress.kubernetes.io/global-rate-limit-window` | Not supported yet. |
| `nginx.ingress.kubernetes.io/global-rate-limit-key` | Not supported yet. |
| `nginx.ingress.kubernetes.io/global-rate-limit-ignored-cidrs` | Not supported yet. |
| `nginx.ingress.kubernetes.io/permanent-redirect` | Not supported yet. |
| `nginx.ingress.kubernetes.io/permanent-redirect-code` | Not supported yet. |
| `nginx.ingress.kubernetes.io/temporal-redirect` | Not supported yet. |
| `nginx.ingress.kubernetes.io/preserve-trailing-slash` | Not supported yet; Traefik preserves by default. |
| `nginx.ingress.kubernetes.io/proxy-cookie-domain` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-cookie-path` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-connect-timeout` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-send-timeout` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-read-timeout` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-next-upstream` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-next-upstream-timeout` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-next-upstream-tries` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-request-buffering` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-redirect-from` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-redirect-to` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-http-version` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-ssl-ciphers` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-ssl-verify-depth` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-ssl-protocols` | Not supported yet. |
| `nginx.ingress.kubernetes.io/enable-rewrite-log` | Not supported yet. |
| `nginx.ingress.kubernetes.io/rewrite-target` | Not supported yet. |
| `nginx.ingress.kubernetes.io/satisfy` | Not supported yet. |
| `nginx.ingress.kubernetes.io/server-alias` | Not supported yet. |
| `nginx.ingress.kubernetes.io/server-snippet` | Not supported yet. |
| `nginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none` | Not supported yet. |
| `nginx.ingress.kubernetes.io/session-cookie-expires` | Not supported yet. |
| `nginx.ingress.kubernetes.io/session-cookie-change-on-failure` | Not supported yet. |
| `nginx.ingress.kubernetes.io/ssl-ciphers` | Not supported yet. |
| `nginx.ingress.kubernetes.io/ssl-prefer-server-ciphers` | Not supported yet. |
| `nginx.ingress.kubernetes.io/connection-proxy-header` | Not supported yet. |
| `nginx.ingress.kubernetes.io/enable-access-log` | Not supported yet. |
| `nginx.ingress.kubernetes.io/enable-opentracing` | Not supported yet. |
| `nginx.ingress.kubernetes.io/opentracing-trust-incoming-span` | Not supported yet. |
| `nginx.ingress.kubernetes.io/enable-opentelemetry` | Not supported yet. |
| `nginx.ingress.kubernetes.io/opentelemetry-trust-incoming-span` | Not supported yet. |
| `nginx.ingress.kubernetes.io/enable-modsecurity` | Not supported yet. |
| `nginx.ingress.kubernetes.io/enable-owasp-core-rules` | Not supported yet. |
| `nginx.ingress.kubernetes.io/modsecurity-transaction-id` | Not supported yet. |
| `nginx.ingress.kubernetes.io/modsecurity-snippet` | Not supported yet. |
| `nginx.ingress.kubernetes.io/mirror-request-body` | Not supported yet. |
| `nginx.ingress.kubernetes.io/mirror-target` | Not supported yet. |
| `nginx.ingress.kubernetes.io/mirror-host` | Not supported yet. |
| `nginx.ingress.kubernetes.io/x-forwarded-prefix` | Not supported yet. |
| `nginx.ingress.kubernetes.io/upstream-hash-by` | Not supported yet. |
| `nginx.ingress.kubernetes.io/upstream-vhost` | Not supported yet. |
| `nginx.ingress.kubernetes.io/denylist-source-range` | Not supported yet. |
| `nginx.ingress.kubernetes.io/whitelist-source-range` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-buffering` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-buffers-number` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-buffer-size` | Not supported yet. |
| `nginx.ingress.kubernetes.io/proxy-max-temp-file-size` | Not supported yet. |
| `nginx.ingress.kubernetes.io/stream-snippet` | Not supported yet. |

View File

@ -91,7 +91,7 @@ TLS key
Defines additional resource attributes (key:value).
`--accesslog.otlp.servicename`:
Set the name for this service. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)
`--api`:
Enable api/dashboard. (Default: ```false```)
@ -283,13 +283,16 @@ HTTP/3 configuration. (Default: ```false```)
UDP port to advertise, on which HTTP/3 is available. (Default: ```0```)
`--entrypoints.<name>.observability.accesslogs`:
(Default: ```true```)
Enables access-logs for this entryPoint. (Default: ```true```)
`--entrypoints.<name>.observability.metrics`:
(Default: ```true```)
Enables metrics for this entryPoint. (Default: ```true```)
`--entrypoints.<name>.observability.traceverbosity`:
Defines the tracing verbosity level for this entryPoint. (Default: ```minimal```)
`--entrypoints.<name>.observability.tracing`:
(Default: ```true```)
Enables tracing for this entryPoint. (Default: ```true```)
`--entrypoints.<name>.proxyprotocol`:
Proxy-Protocol configuration. (Default: ```false```)
@ -478,7 +481,7 @@ TLS key
Defines additional resource attributes (key:value).
`--log.otlp.servicename`:
Set the name for this service. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)
`--metrics.addinternals`:
Enables metrics for internal services (ping, dashboard, etc...). (Default: ```false```)
@ -597,8 +600,11 @@ TLS key
`--metrics.otlp.pushinterval`:
Period between calls to collect a checkpoint. (Default: ```10```)
`--metrics.otlp.resourceattributes.<name>`:
Defines additional resource attributes (key:value).
`--metrics.otlp.servicename`:
OTEL service name to use. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)
`--metrics.prometheus`:
Prometheus metrics exporter type. (Default: ```false```)
@ -1411,4 +1417,4 @@ Query params to not redact.
Sets the rate between 0.0 and 1.0 of requests to trace. (Default: ```1.000000```)
`--tracing.servicename`:
Sets the name for this service. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)

View File

@ -91,7 +91,7 @@ TLS key
Defines additional resource attributes (key:value).
`TRAEFIK_ACCESSLOG_OTLP_SERVICENAME`:
Set the name for this service. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)
`TRAEFIK_API`:
Enable api/dashboard. (Default: ```false```)
@ -283,13 +283,16 @@ Subject alternative names.
Default TLS options for the routers linked to the entry point.
`TRAEFIK_ENTRYPOINTS_<NAME>_OBSERVABILITY_ACCESSLOGS`:
(Default: ```true```)
Enables access-logs for this entryPoint. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_OBSERVABILITY_METRICS`:
(Default: ```true```)
Enables metrics for this entryPoint. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_OBSERVABILITY_TRACEVERBOSITY`:
Defines the tracing verbosity level for this entryPoint. (Default: ```minimal```)
`TRAEFIK_ENTRYPOINTS_<NAME>_OBSERVABILITY_TRACING`:
(Default: ```true```)
Enables tracing for this entryPoint. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_PROXYPROTOCOL`:
Proxy-Protocol configuration. (Default: ```false```)
@ -478,7 +481,7 @@ TLS key
Defines additional resource attributes (key:value).
`TRAEFIK_LOG_OTLP_SERVICENAME`:
Set the name for this service. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)
`TRAEFIK_METRICS_ADDINTERNALS`:
Enables metrics for internal services (ping, dashboard, etc...). (Default: ```false```)
@ -597,8 +600,11 @@ TLS key
`TRAEFIK_METRICS_OTLP_PUSHINTERVAL`:
Period between calls to collect a checkpoint. (Default: ```10```)
`TRAEFIK_METRICS_OTLP_RESOURCEATTRIBUTES_<NAME>`:
Defines additional resource attributes (key:value).
`TRAEFIK_METRICS_OTLP_SERVICENAME`:
OTEL service name to use. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)
`TRAEFIK_METRICS_PROMETHEUS`:
Prometheus metrics exporter type. (Default: ```false```)
@ -1411,4 +1417,4 @@ Query params to not redact.
Sets the rate between 0.0 and 1.0 of requests to trace. (Default: ```1.000000```)
`TRAEFIK_TRACING_SERVICENAME`:
Sets the name for this service. (Default: ```traefik```)
Defines the service name resource attribute. (Default: ```traefik```)

View File

@ -80,8 +80,9 @@
timeout = "42s"
[entryPoints.EntryPoint0.observability]
accessLogs = true
tracing = true
metrics = true
tracing = true
traceVerbosity = "foobar"
[providers]
providersThrottleDuration = "42s"
@ -387,6 +388,9 @@
[metrics.otlp.http.headers]
name0 = "foobar"
name1 = "foobar"
[metrics.otlp.resourceAttributes]
name0 = "foobar"
name1 = "foobar"
[ping]
entryPoint = "foobar"

View File

@ -94,8 +94,9 @@ entryPoints:
timeout: 42s
observability:
accessLogs: true
tracing: true
metrics: true
tracing: true
traceVerbosity: foobar
providers:
providersThrottleDuration: 42s
docker:
@ -428,6 +429,9 @@ metrics:
- 42
pushInterval: 42s
serviceName: foobar
resourceAttributes:
name0: foobar
name1: foobar
ping:
entryPoint: foobar
manualRouting: true

View File

@ -1671,7 +1671,7 @@ or referencing TLS options in the [`IngressRoute`](#kind-ingressroute) / [`Ingre
| [2] | `minVersion` | Defines the [minimum TLS version](../../https/tls.md#minimum-tls-version) that is acceptable. |
| [3] | `maxVersion` | Defines the [maximum TLS version](../../https/tls.md#maximum-tls-version) that is acceptable. |
| [4] | `cipherSuites` | list of supported [cipher suites](../../https/tls.md#cipher-suites) for TLS versions up to TLS 1.2. |
| [5] | `curvePreferences` | List of the [elliptic curves references](../../https/tls.md#curve-preferences) that will be used in an ECDHE handshake, in preference order. |
| [5] | `curvePreferences` | List of the [elliptic curves references](../../https/tls.md#curve-preferences) that will be used in an ECDHE handshake. |
| [6] | `clientAuth` | determines the server's policy for TLS [Client Authentication](../../https/tls.md#client-authentication-mtls). |
| [7] | `clientAuth.secretNames` | list of names of the referenced Kubernetes [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) (in TLSOption namespace). The secret must contain a certificate under either a `tls.ca` or a `ca.crt` key. |
| [8] | `clientAuth.clientAuthType` | defines the client authentication type to apply. The available values are: `NoClientCert`, `RequestClientCert`, `VerifyClientCertIfGiven` and `RequireAndVerifyClientCert`. |

5
go.mod
View File

@ -55,7 +55,7 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // No tag on the repo.
github.com/prometheus/client_golang v1.19.1
github.com/prometheus/client_model v0.6.1
github.com/quic-go/quic-go v0.49.0
github.com/quic-go/quic-go v0.54.0
github.com/redis/go-redis/v9 v9.7.3
github.com/rs/zerolog v1.33.0
github.com/sirupsen/logrus v1.9.3
@ -206,7 +206,6 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.16.0 // indirect
github.com/go-resty/resty/v2 v2.16.5 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/go-zookeeper/zk v1.0.3 // indirect
github.com/goccy/go-json v0.10.5 // indirect
@ -218,7 +217,6 @@ require (
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
@ -293,7 +291,6 @@ require (
github.com/nrdcg/porkbun v0.4.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/ginkgo/v2 v2.22.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect

5
go.sum
View File

@ -421,6 +421,7 @@ github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptd
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
@ -1033,8 +1034,8 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=

View File

@ -648,25 +648,6 @@ func (s *AccessLogSuite) TestAccessLogDisabledForInternals() {
require.Equal(s.T(), 0, count)
// Make some requests on the custom ping router in error.
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8010/ping-error", nil)
require.NoError(s.T(), err)
req.Host = "ping-error.docker.local"
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.BodyContains("X-Forwarded-Host: ping-error.docker.local"))
require.NoError(s.T(), err)
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.BodyContains("X-Forwarded-Host: ping-error.docker.local"))
require.NoError(s.T(), err)
// Here we verify that the remove of observability doesn't break the metrics for the error page service.
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil)
require.NoError(s.T(), err)
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("service3"))
require.NoError(s.T(), err)
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyNotContains("service=\"ping"))
require.NoError(s.T(), err)
// Verify no other Traefik problems.
s.checkNoOtherTraefikProblems()
}

View File

@ -92,10 +92,21 @@ spec:
More info: https://doc.traefik.io/traefik/v3.5/routing/routers/#observability
properties:
accessLogs:
description: AccessLogs enables access logs for this router.
type: boolean
metrics:
description: Metrics enables metrics for this router.
type: boolean
traceVerbosity:
default: minimal
description: TraceVerbosity defines the verbosity level
of the tracing for this router.
enum:
- minimal
- detailed
type: string
tracing:
description: Tracing enables tracing for this router.
type: boolean
type: object
priority:
@ -2551,7 +2562,7 @@ spec:
type: object
curvePreferences:
description: |-
CurvePreferences defines the preferred elliptic curves in a specific order.
CurvePreferences defines the preferred elliptic curves.
More info: https://doc.traefik.io/traefik/v3.5/https/tls/#curve-preferences
items:
type: string

View File

@ -14,6 +14,10 @@
[entryPoints]
[entryPoints.web]
address = ":8000"
[entryPoints.web.observability]
traceVerbosity = "detailed"
[entryPoints.web-minimal]
address = ":8001"
# Adding metrics to confirm that there is no wrong interaction with tracing.
[metrics]
@ -44,9 +48,13 @@
## dynamic configuration ##
[http.routers]
[http.routers.routerBasicMinimal]
Service = "service0"
Rule = "Path(`/basic-minimal`)"
[http.routers.routerBasicMinimal.observability]
traceVerbosity = "minimal"
[http.routers.router0]
Service = "service0"
Middlewares = []
Rule = "Path(`/basic`)"
[http.routers.router1]
Service = "service1"

View File

@ -101,13 +101,3 @@ services:
traefik.http.routers.ping.entryPoints: ping
traefik.http.routers.ping.rule: PathPrefix(`/ping`)
traefik.http.routers.ping.service: ping@internal
traefik.http.routers.ping-error.entryPoints: ping
traefik.http.routers.ping-error.rule: PathPrefix(`/ping-error`)
traefik.http.routers.ping-error.middlewares: errors, basicauth
traefik.http.routers.ping-error.service: ping@internal
traefik.http.middlewares.basicauth.basicauth.users: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
traefik.http.middlewares.errors.errors.status: 401
traefik.http.middlewares.errors.errors.service: service3
traefik.http.middlewares.errors.errors.query: /
traefik.http.services.service3.loadbalancer.server.port: 80

View File

@ -14,8 +14,9 @@
"tls": {},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +50,9 @@
},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -67,8 +69,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -89,8 +92,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -100,7 +104,13 @@
},
"middlewares": {
"compressor@consul": {
"compress": {},
"compress": {
"encodings": [
"gzip",
"br",
"zstd"
]
},
"status": "enabled",
"usedBy": [
"Router0@consul"
@ -173,6 +183,7 @@
"mirror@consul": {
"mirroring": {
"service": "simplesvc",
"mirrorBody": true,
"maxBodySize": -1,
"mirrors": [
{

View File

@ -9,8 +9,9 @@
"priority": 18,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -29,8 +30,9 @@
},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [

View File

@ -9,8 +9,9 @@
"priority": 18,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -29,8 +30,9 @@
},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +51,9 @@
"priority": 46,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -66,8 +69,9 @@
"priority": 38,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -83,8 +87,9 @@
"priority": 50,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -100,8 +105,9 @@
"priority": 35,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"error": [
"the service \"other-ns-wrr3@kubernetescrd\" does not exist"

View File

@ -14,8 +14,9 @@
"tls": {},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +50,9 @@
},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -67,8 +69,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -89,8 +92,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -100,7 +104,13 @@
},
"middlewares": {
"compressor@etcd": {
"compress": {},
"compress": {
"encodings": [
"gzip",
"br",
"zstd"
]
},
"status": "enabled",
"usedBy": [
"Router0@etcd"
@ -173,6 +183,7 @@
"mirror@etcd": {
"mirroring": {
"service": "simplesvc",
"mirrorBody": true,
"maxBodySize": -1,
"mirrors": [
{

View File

@ -10,8 +10,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -32,8 +33,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -50,8 +52,9 @@
"priority": 100008,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -69,8 +72,9 @@
"tls": {},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [

View File

@ -10,8 +10,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -32,8 +33,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +51,9 @@
"priority": 44,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [

View File

@ -10,8 +10,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -32,8 +33,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +51,9 @@
"priority": 50,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -66,8 +69,9 @@
"priority": 44,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -83,8 +87,9 @@
"priority": 47,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -100,8 +105,9 @@
"priority": 47,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [

View File

@ -10,8 +10,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -32,8 +33,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [

View File

@ -10,8 +10,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -32,8 +33,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +51,9 @@
"priority": 47,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [

View File

@ -14,8 +14,9 @@
"tls": {},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +50,9 @@
},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -67,8 +69,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -89,8 +92,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -100,7 +104,13 @@
},
"middlewares": {
"compressor@redis": {
"compress": {},
"compress": {
"encodings": [
"gzip",
"br",
"zstd"
]
},
"status": "enabled",
"usedBy": [
"Router0@redis"
@ -173,6 +183,7 @@
"mirror@redis": {
"mirroring": {
"service": "simplesvc",
"mirrorBody": true,
"maxBodySize": -1,
"mirrors": [
{
@ -244,6 +255,7 @@
"url": "http://10.0.1.3:8889"
}
],
"strategy": "wrr",
"passHostHeader": true,
"responseForwarding": {
"flushInterval": "100ms"

View File

@ -14,8 +14,9 @@
"tls": {},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -49,8 +50,9 @@
},
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -67,8 +69,9 @@
"priority": 9223372036854775806,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -89,8 +92,9 @@
"priority": 9223372036854775805,
"observability": {
"accessLogs": true,
"metrics": true,
"tracing": true,
"metrics": true
"traceVerbosity": "minimal"
},
"status": "enabled",
"using": [
@ -100,7 +104,13 @@
},
"middlewares": {
"compressor@zookeeper": {
"compress": {},
"compress": {
"encodings": [
"gzip",
"br",
"zstd"
]
},
"status": "enabled",
"usedBy": [
"Router0@zookeeper"
@ -173,6 +183,7 @@
"mirror@zookeeper": {
"mirroring": {
"service": "simplesvc",
"mirrorBody": true,
"maxBodySize": -1,
"mirrors": [
{

View File

@ -77,6 +77,104 @@ func (s *TracingSuite) TearDownTest() {
s.composeStop("tempo")
}
func (s *TracingSuite) TestOpenTelemetryBasic_HTTP_router_minimalVerbosity() {
file := s.adaptFile("fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.otelCollectorIP,
IsHTTP: true,
})
s.traefikCmd(withConfigFile(file))
// wait for traefik
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
require.NoError(s.T(), err)
err = try.GetRequest("http://127.0.0.1:8000/basic-minimal", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
contains := []map[string]string{
{
"batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik",
"batches.0.scopeSpans.0.spans.0.name": "ReverseProxy",
"batches.0.scopeSpans.0.spans.0.kind": "SPAN_KIND_CLIENT",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"network.protocol.version\").value.stringValue": "1.1",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.full\").value.stringValue": fmt.Sprintf("http://%s/basic-minimal", net.JoinHostPort(s.whoamiIP, "80")),
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"network.peer.address\").value.stringValue": s.whoamiIP,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"network.peer.port\").value.intValue": "80",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"server.address\").value.stringValue": s.whoamiIP,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"server.port\").value.intValue": "80",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "200",
"batches.0.scopeSpans.0.spans.1.name": "EntryPoint",
"batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_SERVER",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"entry_point\").value.stringValue": "web",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"http.request.method\").value.stringValue": "GET",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"url.path\").value.stringValue": "/basic-minimal",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"url.query\").value.stringValue": "",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"server.address\").value.stringValue": "127.0.0.1:8000",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"network.peer.address\").value.stringValue": "127.0.0.1",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"http.response.status_code\").value.intValue": "200",
},
}
s.checkTraceContent(contains)
}
func (s *TracingSuite) TestOpenTelemetryBasic_HTTP_entrypoint_minimalVerbosity() {
file := s.adaptFile("fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.otelCollectorIP,
IsHTTP: true,
})
s.traefikCmd(withConfigFile(file))
// wait for traefik
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
require.NoError(s.T(), err)
err = try.GetRequest("http://127.0.0.1:8001/basic", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
contains := []map[string]string{
{
"batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik",
"batches.0.scopeSpans.0.spans.0.name": "ReverseProxy",
"batches.0.scopeSpans.0.spans.0.kind": "SPAN_KIND_CLIENT",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"network.protocol.version\").value.stringValue": "1.1",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.full\").value.stringValue": fmt.Sprintf("http://%s/basic", net.JoinHostPort(s.whoamiIP, "80")),
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"network.peer.address\").value.stringValue": s.whoamiIP,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"network.peer.port\").value.intValue": "80",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"server.address\").value.stringValue": s.whoamiIP,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"server.port\").value.intValue": "80",
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "200",
"batches.0.scopeSpans.0.spans.1.name": "EntryPoint",
"batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_SERVER",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"entry_point\").value.stringValue": "web-minimal",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"http.request.method\").value.stringValue": "GET",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"url.path\").value.stringValue": "/basic",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"url.query\").value.stringValue": "",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"server.address\").value.stringValue": "127.0.0.1:8001",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"network.peer.address\").value.stringValue": "127.0.0.1",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"http.response.status_code\").value.intValue": "200",
},
}
s.checkTraceContent(contains)
}
func (s *TracingSuite) TestOpenTelemetryBasic_HTTP() {
file := s.adaptFile("fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{
WhoamiIP: s.whoamiIP,
@ -121,7 +219,7 @@ func (s *TracingSuite) TestOpenTelemetryBasic_HTTP() {
"batches.0.scopeSpans.0.spans.3.name": "Router",
"batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.service.name\").value.stringValue": "service0@file",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.router.name\").value.stringValue": "router0@file",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router0@file",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"http.route\").value.stringValue": "Path(`/basic`)",
"batches.0.scopeSpans.0.spans.4.name": "Metrics",
@ -189,7 +287,7 @@ func (s *TracingSuite) TestOpenTelemetryBasic_gRPC() {
"batches.0.scopeSpans.0.spans.3.name": "Router",
"batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.service.name\").value.stringValue": "service0@file",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.router.name\").value.stringValue": "router0@file",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router0@file",
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"http.route\").value.stringValue": "Path(`/basic`)",
"batches.0.scopeSpans.0.spans.4.name": "Metrics",
@ -251,7 +349,7 @@ func (s *TracingSuite) TestOpenTelemetryRateLimit() {
"batches.0.scopeSpans.0.spans.1.name": "Router",
"batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service1@file",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router1@file",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router1@file",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"http.route\").value.stringValue": "Path(`/ratelimit`)",
"batches.0.scopeSpans.0.spans.2.name": "Metrics",
@ -299,7 +397,7 @@ func (s *TracingSuite) TestOpenTelemetryRateLimit() {
"batches.0.scopeSpans.0.spans.4.name": "Router",
"batches.0.scopeSpans.0.spans.4.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.service.name\").value.stringValue": "service1@file",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.router.name\").value.stringValue": "router1@file",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router1@file",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"http.route\").value.stringValue": "Path(`/ratelimit`)",
"batches.0.scopeSpans.0.spans.5.name": "Metrics",
@ -423,7 +521,7 @@ func (s *TracingSuite) TestOpenTelemetryRetry() {
"batches.0.scopeSpans.0.spans.12.name": "Router",
"batches.0.scopeSpans.0.spans.12.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.12.attributes.#(key=\"traefik.service.name\").value.stringValue": "service2@file",
"batches.0.scopeSpans.0.spans.12.attributes.#(key=\"traefik.router.name\").value.stringValue": "router2@file",
"batches.0.scopeSpans.0.spans.12.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router2@file",
"batches.0.scopeSpans.0.spans.13.name": "Metrics",
"batches.0.scopeSpans.0.spans.13.kind": "SPAN_KIND_INTERNAL",
@ -475,7 +573,7 @@ func (s *TracingSuite) TestOpenTelemetryAuth() {
"batches.0.scopeSpans.0.spans.1.name": "Router",
"batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service3@file",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router3@file",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router3@file",
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"http.route\").value.stringValue": "Path(`/auth`)",
"batches.0.scopeSpans.0.spans.2.name": "Metrics",
@ -532,7 +630,7 @@ func (s *TracingSuite) TestOpenTelemetryAuthWithRetry() {
"batches.0.scopeSpans.0.spans.2.name": "Router",
"batches.0.scopeSpans.0.spans.2.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.service.name\").value.stringValue": "service4@file",
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.router.name\").value.stringValue": "router4@file",
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router4@file",
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"http.route\").value.stringValue": "Path(`/retry-auth`)",
"batches.0.scopeSpans.0.spans.3.name": "Metrics",
@ -601,7 +699,7 @@ func (s *TracingSuite) TestOpenTelemetrySafeURL() {
"batches.0.scopeSpans.0.spans.4.name": "Router",
"batches.0.scopeSpans.0.spans.4.kind": "SPAN_KIND_INTERNAL",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.service.name\").value.stringValue": "service3@file",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.router.name\").value.stringValue": "router3@file",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.router.name\").value.stringValue": "web-router3@file",
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"http.route\").value.stringValue": "Path(`/auth`)",
"batches.0.scopeSpans.0.spans.5.name": "Metrics",

View File

@ -88,9 +88,21 @@ type RouterTLSConfig struct {
// RouterObservabilityConfig holds the observability configuration for a router.
type RouterObservabilityConfig struct {
// AccessLogs enables access logs for this router.
AccessLogs *bool `json:"accessLogs,omitempty" toml:"accessLogs,omitempty" yaml:"accessLogs,omitempty" export:"true"`
Tracing *bool `json:"tracing,omitempty" toml:"tracing,omitempty" yaml:"tracing,omitempty" export:"true"`
Metrics *bool `json:"metrics,omitempty" toml:"metrics,omitempty" yaml:"metrics,omitempty" export:"true"`
// Metrics enables metrics for this router.
Metrics *bool `json:"metrics,omitempty" toml:"metrics,omitempty" yaml:"metrics,omitempty" export:"true"`
// Tracing enables tracing for this router.
Tracing *bool `json:"tracing,omitempty" toml:"tracing,omitempty" yaml:"tracing,omitempty" export:"true"`
// TraceVerbosity defines the verbosity level of the tracing for this router.
// +kubebuilder:validation:Enum=minimal;detailed
// +kubebuilder:default=minimal
TraceVerbosity types.TracingVerbosity `json:"traceVerbosity,omitempty" toml:"traceVerbosity,omitempty" yaml:"traceVerbosity,omitempty" export:"true"`
}
// SetDefaults Default values for a RouterObservabilityConfig.
func (r *RouterObservabilityConfig) SetDefaults() {
r.TraceVerbosity = types.MinimalVerbosity
}
// +k8s:deepcopy-gen=true

View File

@ -1335,13 +1335,13 @@ func (in *RouterObservabilityConfig) DeepCopyInto(out *RouterObservabilityConfig
*out = new(bool)
**out = **in
}
if in.Tracing != nil {
in, out := &in.Tracing, &out.Tracing
if in.Metrics != nil {
in, out := &in.Metrics, &out.Metrics
*out = new(bool)
**out = **in
}
if in.Metrics != nil {
in, out := &in.Metrics, &out.Metrics
if in.Tracing != nil {
in, out := &in.Tracing, &out.Tracing
*out = new(bool)
**out = **in
}

View File

@ -26,9 +26,10 @@ const (
type Configuration struct {
Routers map[string]*RouterInfo `json:"routers,omitempty"`
Middlewares map[string]*MiddlewareInfo `json:"middlewares,omitempty"`
TCPMiddlewares map[string]*TCPMiddlewareInfo `json:"tcpMiddlewares,omitempty"`
Services map[string]*ServiceInfo `json:"services,omitempty"`
Models map[string]*dynamic.Model `json:"-"`
TCPRouters map[string]*TCPRouterInfo `json:"tcpRouters,omitempty"`
TCPMiddlewares map[string]*TCPMiddlewareInfo `json:"tcpMiddlewares,omitempty"`
TCPServices map[string]*TCPServiceInfo `json:"tcpServices,omitempty"`
UDPRouters map[string]*UDPRouterInfo `json:"udpRouters,omitempty"`
UDPServices map[string]*UDPServiceInfo `json:"udpServices,omitempty"`
@ -66,6 +67,8 @@ func NewConfig(conf dynamic.Configuration) *Configuration {
runtimeConfig.Middlewares[k] = &MiddlewareInfo{Middleware: v, Status: StatusEnabled}
}
}
runtimeConfig.Models = conf.HTTP.Models
}
if conf.TCP != nil {

View File

@ -165,15 +165,17 @@ func (u *UDPConfig) SetDefaults() {
// ObservabilityConfig holds the observability configuration for an entry point.
type ObservabilityConfig struct {
AccessLogs *bool `json:"accessLogs,omitempty" toml:"accessLogs,omitempty" yaml:"accessLogs,omitempty" export:"true"`
Tracing *bool `json:"tracing,omitempty" toml:"tracing,omitempty" yaml:"tracing,omitempty" export:"true"`
Metrics *bool `json:"metrics,omitempty" toml:"metrics,omitempty" yaml:"metrics,omitempty" export:"true"`
AccessLogs *bool `description:"Enables access-logs for this entryPoint." json:"accessLogs,omitempty" toml:"accessLogs,omitempty" yaml:"accessLogs,omitempty" export:"true"`
Metrics *bool `description:"Enables metrics for this entryPoint." json:"metrics,omitempty" toml:"metrics,omitempty" yaml:"metrics,omitempty" export:"true"`
Tracing *bool `description:"Enables tracing for this entryPoint." json:"tracing,omitempty" toml:"tracing,omitempty" yaml:"tracing,omitempty" export:"true"`
TraceVerbosity types.TracingVerbosity `description:"Defines the tracing verbosity level for this entryPoint." json:"traceVerbosity,omitempty" toml:"traceVerbosity,omitempty" yaml:"traceVerbosity,omitempty" export:"true"`
}
// SetDefaults sets the default values.
func (o *ObservabilityConfig) SetDefaults() {
defaultValue := true
o.AccessLogs = &defaultValue
o.Tracing = &defaultValue
o.Metrics = &defaultValue
o.Tracing = &defaultValue
o.TraceVerbosity = types.MinimalVerbosity
}

View File

@ -205,7 +205,7 @@ func (a *LifeCycle) SetDefaults() {
// Tracing holds the tracing configuration.
type Tracing struct {
ServiceName string `description:"Sets the name for this service." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
ServiceName string `description:"Defines the service name resource attribute." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
ResourceAttributes map[string]string `description:"Defines additional resource attributes (key:value)." json:"resourceAttributes,omitempty" toml:"resourceAttributes,omitempty" yaml:"resourceAttributes,omitempty" export:"true"`
CapturedRequestHeaders []string `description:"Request headers to add as attributes for server and client spans." json:"capturedRequestHeaders,omitempty" toml:"capturedRequestHeaders,omitempty" yaml:"capturedRequestHeaders,omitempty" export:"true"`
CapturedResponseHeaders []string `description:"Response headers to add as attributes for server and client spans." json:"capturedResponseHeaders,omitempty" toml:"capturedResponseHeaders,omitempty" yaml:"capturedResponseHeaders,omitempty" export:"true"`

View File

@ -1,6 +1,7 @@
package logs
import (
"context"
"encoding/json"
"fmt"
"reflect"
@ -12,12 +13,12 @@ import (
)
// SetupOTelLogger sets up the OpenTelemetry logger.
func SetupOTelLogger(logger zerolog.Logger, config *types.OTelLog) (zerolog.Logger, error) {
func SetupOTelLogger(ctx context.Context, logger zerolog.Logger, config *types.OTelLog) (zerolog.Logger, error) {
if config == nil {
return logger, nil
}
provider, err := config.NewLoggerProvider()
provider, err := config.NewLoggerProvider(ctx)
if err != nil {
return zerolog.Logger{}, fmt.Errorf("setting up OpenTelemetry logger provider: %w", err)
}

View File

@ -171,7 +171,7 @@ func TestLog(t *testing.T) {
out := zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339})
logger := zerolog.New(out).With().Caller().Logger()
logger, err := SetupOTelLogger(logger, config)
logger, err := SetupOTelLogger(t.Context(), logger, config)
require.NoError(t, err)
ctx := trace.ContextWithSpanContext(t.Context(), trace.NewSpanContext(trace.SpanContextConfig{

View File

@ -206,15 +206,27 @@ func newOpenTelemetryMeterProvider(ctx context.Context, config *types.OTLP) (*sd
return nil, fmt.Errorf("creating exporter: %w", err)
}
var resAttrs []attribute.KeyValue
for k, v := range config.ResourceAttributes {
resAttrs = append(resAttrs, attribute.String(k, v))
}
res, err := resource.New(ctx,
resource.WithAttributes(semconv.ServiceNameKey.String(config.ServiceName)),
resource.WithAttributes(semconv.ServiceVersionKey.String(version.Version)),
resource.WithContainer(),
resource.WithFromEnv(),
resource.WithHost(),
resource.WithOS(),
resource.WithProcess(),
resource.WithTelemetrySDK(),
resource.WithDetectors(types.K8sAttributesDetector{}),
// The following order allows the user to override the service name and version,
// as well as any other attributes set by the above detectors.
resource.WithAttributes(
semconv.ServiceName(config.ServiceName),
semconv.ServiceVersion(version.Version),
),
resource.WithAttributes(resAttrs...),
// Use the environment variables to allow overriding above resource attributes.
resource.WithFromEnv(),
)
if err != nil {
return nil, fmt.Errorf("building resource: %w", err)

View File

@ -21,6 +21,7 @@ import (
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/middlewares/capture"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
traefiktls "github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types"
"go.opentelemetry.io/contrib/bridges/otellogrus"
@ -69,17 +70,22 @@ type Handler struct {
wg sync.WaitGroup
}
// WrapHandler Wraps access log handler into an Alice Constructor.
func WrapHandler(handler *Handler) alice.Constructor {
// AliceConstructor returns an alice.Constructor that wraps the Handler (conditionally) in a middleware chain.
func (h *Handler) AliceConstructor() alice.Constructor {
return func(next http.Handler) (http.Handler, error) {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
handler.ServeHTTP(rw, req, next)
if h == nil {
next.ServeHTTP(rw, req)
return
}
h.ServeHTTP(rw, req, next)
}), nil
}
}
// NewHandler creates a new Handler.
func NewHandler(config *types.AccessLog) (*Handler, error) {
func NewHandler(ctx context.Context, config *types.AccessLog) (*Handler, error) {
var file io.WriteCloser = noopCloser{os.Stdout}
if len(config.FilePath) > 0 {
f, err := openAccessLogFile(config.FilePath)
@ -110,7 +116,7 @@ func NewHandler(config *types.AccessLog) (*Handler, error) {
}
if config.OTLP != nil {
otelLoggerProvider, err := config.OTLP.NewLoggerProvider()
otelLoggerProvider, err := config.OTLP.NewLoggerProvider(ctx)
if err != nil {
return nil, fmt.Errorf("setting up OpenTelemetry logger provider: %w", err)
}
@ -196,6 +202,12 @@ func GetLogData(req *http.Request) *LogData {
}
func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http.Handler) {
if !observability.AccessLogsEnabled(req.Context()) {
next.ServeHTTP(rw, req)
return
}
now := time.Now().UTC()
core := CoreLogData{

View File

@ -7,6 +7,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCommonLogFormatter_Format(t *testing.T) {
@ -82,8 +83,9 @@ func TestCommonLogFormatter_Format(t *testing.T) {
},
}
// Set timezone to Etc/GMT+9 to have a constant behavior
t.Setenv("TZ", "Etc/GMT+9")
var err error
time.Local, err = time.LoadLocation("Etc/GMT+9")
require.NoError(t, err)
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {

View File

@ -25,6 +25,7 @@ import (
"github.com/stretchr/testify/require"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/middlewares/capture"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"github.com/traefik/traefik/v3/pkg/types"
"go.opentelemetry.io/collector/pdata/plog/plogotlp"
"go.opentelemetry.io/otel/attribute"
@ -84,7 +85,7 @@ func TestOTelAccessLog(t *testing.T) {
},
},
}
logHandler, err := NewHandler(config)
logHandler, err := NewHandler(t.Context(), config)
require.NoError(t, err)
t.Cleanup(func() {
err := logHandler.Close()
@ -105,7 +106,15 @@ func TestOTelAccessLog(t *testing.T) {
chain := alice.New()
chain = chain.Append(capture.Wrap)
chain = chain.Append(WrapHandler(logHandler))
// Injection of the observability variables in the request context.
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
return observability.WithObservabilityHandler(next, observability.Observability{
AccessLogsEnabled: true,
}), nil
})
chain = chain.Append(logHandler.AliceConstructor())
handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusOK)
}))
@ -129,7 +138,7 @@ func TestLogRotation(t *testing.T) {
rotatedFileName := fileName + ".rotated"
config := &types.AccessLog{FilePath: fileName, Format: CommonFormat}
logHandler, err := NewHandler(config)
logHandler, err := NewHandler(t.Context(), config)
require.NoError(t, err)
t.Cleanup(func() {
err := logHandler.Close()
@ -138,7 +147,15 @@ func TestLogRotation(t *testing.T) {
chain := alice.New()
chain = chain.Append(capture.Wrap)
chain = chain.Append(WrapHandler(logHandler))
// Injection of the observability variables in the request context.
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
return observability.WithObservabilityHandler(next, observability.Observability{
AccessLogsEnabled: true,
}), nil
})
chain = chain.Append(logHandler.AliceConstructor())
handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusOK)
}))
@ -265,7 +282,7 @@ func TestLoggerHeaderFields(t *testing.T) {
Fields: &test.accessLogFields,
}
logger, err := NewHandler(config)
logger, err := NewHandler(t.Context(), config)
require.NoError(t, err)
t.Cleanup(func() {
err := logger.Close()
@ -290,7 +307,15 @@ func TestLoggerHeaderFields(t *testing.T) {
chain := alice.New()
chain = chain.Append(capture.Wrap)
chain = chain.Append(WrapHandler(logger))
// Injection of the observability variables in the request context.
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
return observability.WithObservabilityHandler(next, observability.Observability{
AccessLogsEnabled: true,
}), nil
})
chain = chain.Append(logger.AliceConstructor())
handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusOK)
}))
@ -954,7 +979,7 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS, tracing bool) {
t.Helper()
logger, err := NewHandler(config)
logger, err := NewHandler(t.Context(), config)
require.NoError(t, err)
t.Cleanup(func() {
err := logger.Close()
@ -998,7 +1023,15 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS, tracing b
chain := alice.New()
chain = chain.Append(capture.Wrap)
chain = chain.Append(WrapHandler(logger))
// Injection of the observability variables in the request context.
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
return observability.WithObservabilityHandler(next, observability.Observability{
AccessLogsEnabled: true,
}), nil
})
chain = chain.Append(logger.AliceConstructor())
handler, err := chain.Then(http.HandlerFunc(logWriterTestHandlerFunc))
require.NoError(t, err)
@ -1043,7 +1076,7 @@ func logWriterTestHandlerFunc(rw http.ResponseWriter, r *http.Request) {
func doLoggingWithAbortedStream(t *testing.T, config *types.AccessLog) {
t.Helper()
logger, err := NewHandler(config)
logger, err := NewHandler(t.Context(), config)
require.NoError(t, err)
t.Cleanup(func() {
err := logger.Close()
@ -1085,7 +1118,15 @@ func doLoggingWithAbortedStream(t *testing.T, config *types.AccessLog) {
}), nil
})
chain = chain.Append(capture.Wrap)
chain = chain.Append(WrapHandler(logger))
// Injection of the observability variables in the request context.
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
return observability.WithObservabilityHandler(next, observability.Observability{
AccessLogsEnabled: true,
}), nil
})
chain = chain.Append(logger.AliceConstructor())
service := NewFieldHandler(http.HandlerFunc(streamBackend), ServiceURL, "http://stream", nil)
service = NewFieldHandler(service, ServiceAddr, "127.0.0.1", nil)

View File

@ -7,7 +7,6 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const (
@ -39,8 +38,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.AddPrefix, name
return result, nil
}
func (a *addPrefix) GetTracingInformation() (string, string, trace.SpanKind) {
return a.name, typeName, trace.SpanKindInternal
func (a *addPrefix) GetTracingInformation() (string, string) {
return a.name, typeName
}
func (a *addPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -12,7 +12,6 @@ import (
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/traefik/traefik/v3/pkg/middlewares/accesslog"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"go.opentelemetry.io/otel/trace"
"golang.org/x/sync/singleflight"
)
@ -61,8 +60,8 @@ func NewBasic(ctx context.Context, next http.Handler, authConfig dynamic.BasicAu
return ba, nil
}
func (b *basicAuth) GetTracingInformation() (string, string, trace.SpanKind) {
return b.name, typeNameBasic, trace.SpanKindInternal
func (b *basicAuth) GetTracingInformation() (string, string) {
return b.name, typeNameBasic
}
func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -12,7 +12,6 @@ import (
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/traefik/traefik/v3/pkg/middlewares/accesslog"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"go.opentelemetry.io/otel/trace"
)
const (
@ -54,8 +53,8 @@ func NewDigest(ctx context.Context, next http.Handler, authConfig dynamic.Digest
return da, nil
}
func (d *digestAuth) GetTracingInformation() (string, string, trace.SpanKind) {
return d.name, typeNameDigest, trace.SpanKindInternal
func (d *digestAuth) GetTracingInformation() (string, string) {
return d.name, typeNameDigest
}
func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -131,8 +131,8 @@ func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAu
return fa, nil
}
func (fa *forwardAuth) GetTracingInformation() (string, string, trace.SpanKind) {
return fa.name, typeNameForward, trace.SpanKindInternal
func (fa *forwardAuth) GetTracingInformation() (string, string) {
return fa.name, typeNameForward
}
func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
@ -180,7 +180,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
var forwardSpan trace.Span
var tracer *tracing.Tracer
if tracer = tracing.TracerFromContext(req.Context()); tracer != nil {
if tracer = tracing.TracerFromContext(req.Context()); tracer != nil && observability.TracingEnabled(req.Context()) {
var tracingCtx context.Context
tracingCtx, forwardSpan = tracer.Start(req.Context(), "AuthRequest", trace.WithSpanKind(trace.SpanKindClient))
defer forwardSpan.End()

View File

@ -16,6 +16,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"github.com/traefik/traefik/v3/pkg/proxy/httputil"
"github.com/traefik/traefik/v3/pkg/testhelpers"
"github.com/traefik/traefik/v3/pkg/tracing"
@ -756,6 +757,10 @@ func TestForwardAuthTracing(t *testing.T) {
next, err := NewForward(t.Context(), next, auth, "authTest")
require.NoError(t, err)
next = observability.WithObservabilityHandler(next, observability.Observability{
TracingEnabled: true,
})
req := httptest.NewRequest(http.MethodGet, "http://www.test.com/search?q=Opentelemetry", nil)
req.RemoteAddr = "10.0.0.1:1234"
req.Header.Set("User-Agent", "forward-test")

View File

@ -9,7 +9,6 @@ import (
"github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/middlewares"
oxybuffer "github.com/vulcand/oxy/v2/buffer"
"go.opentelemetry.io/otel/trace"
)
const (
@ -48,8 +47,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name
}, nil
}
func (b *buffer) GetTracingInformation() (string, string, trace.SpanKind) {
return b.name, typeName, trace.SpanKindInternal
func (b *buffer) GetTracingInformation() (string, string) {
return b.name, typeName
}
func (b *buffer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -12,7 +12,6 @@ import (
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"github.com/vulcand/oxy/v2/cbreaker"
"go.opentelemetry.io/otel/trace"
)
const typeName = "CircuitBreaker"
@ -68,8 +67,8 @@ func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.Circ
}, nil
}
func (c *circuitBreaker) GetTracingInformation() (string, string, trace.SpanKind) {
return c.name, typeName, trace.SpanKindInternal
func (c *circuitBreaker) GetTracingInformation() (string, string) {
return c.name, typeName
}
func (c *circuitBreaker) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -13,7 +13,6 @@ import (
"github.com/klauspost/compress/zstd"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const typeName = "Compress"
@ -181,8 +180,8 @@ func (c *compress) chooseHandler(typ string, rw http.ResponseWriter, req *http.R
}
}
func (c *compress) GetTracingInformation() (string, string, trace.SpanKind) {
return c.name, typeName, trace.SpanKindInternal
func (c *compress) GetTracingInformation() (string, string) {
return c.name, typeName
}
func (c *compress) newGzipHandler() (http.Handler, error) {

View File

@ -15,7 +15,6 @@ import (
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"github.com/traefik/traefik/v3/pkg/types"
"github.com/vulcand/oxy/v2/utils"
"go.opentelemetry.io/otel/trace"
)
// Compile time validation that the response recorder implements http interfaces correctly.
@ -83,8 +82,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, servi
}, nil
}
func (c *customErrors) GetTracingInformation() (string, string, trace.SpanKind) {
return c.name, typeName, trace.SpanKindInternal
func (c *customErrors) GetTracingInformation() (string, string) {
return c.name, typeName
}
func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -6,7 +6,6 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const requestHeaderModifierTypeName = "RequestHeaderModifier"
@ -35,8 +34,8 @@ func NewRequestHeaderModifier(ctx context.Context, next http.Handler, config dyn
}
}
func (r *requestHeaderModifier) GetTracingInformation() (string, string, trace.SpanKind) {
return r.name, requestHeaderModifierTypeName, trace.SpanKindUnspecified
func (r *requestHeaderModifier) GetTracingInformation() (string, string) {
return r.name, requestHeaderModifierTypeName
}
func (r *requestHeaderModifier) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -6,7 +6,6 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const responseHeaderModifierTypeName = "ResponseHeaderModifier"
@ -35,8 +34,8 @@ func NewResponseHeaderModifier(ctx context.Context, next http.Handler, config dy
}
}
func (r *responseHeaderModifier) GetTracingInformation() (string, string, trace.SpanKind) {
return r.name, responseHeaderModifierTypeName, trace.SpanKindUnspecified
func (r *responseHeaderModifier) GetTracingInformation() (string, string) {
return r.name, responseHeaderModifierTypeName
}
func (r *responseHeaderModifier) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -10,7 +10,6 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const typeName = "RequestRedirect"
@ -52,8 +51,8 @@ func NewRequestRedirect(ctx context.Context, next http.Handler, conf dynamic.Req
}, nil
}
func (r redirect) GetTracingInformation() (string, string, trace.SpanKind) {
return r.name, typeName, trace.SpanKindInternal
func (r redirect) GetTracingInformation() (string, string) {
return r.name, typeName
}
func (r redirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -8,7 +8,6 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const (
@ -38,8 +37,8 @@ func NewURLRewrite(ctx context.Context, next http.Handler, conf dynamic.URLRewri
}
}
func (u urlRewrite) GetTracingInformation() (string, string, trace.SpanKind) {
return u.name, typeName, trace.SpanKindInternal
func (u urlRewrite) GetTracingInformation() (string, string) {
return u.name, typeName
}
func (u urlRewrite) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -8,7 +8,6 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const (
@ -58,8 +57,8 @@ func New(ctx context.Context, next http.Handler, cfg dynamic.Headers, name strin
}, nil
}
func (h *headers) GetTracingInformation() (string, string, trace.SpanKind) {
return h.name, typeName, trace.SpanKindInternal
func (h *headers) GetTracingInformation() (string, string) {
return h.name, typeName
}
func (h *headers) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -13,7 +13,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"go.opentelemetry.io/otel/trace"
)
func TestNew_withoutOptions(t *testing.T) {
@ -107,11 +106,10 @@ func Test_headers_getTracingInformation(t *testing.T) {
name: "testing",
}
name, typeName, spanKind := mid.GetTracingInformation()
name, typeName := mid.GetTracingInformation()
assert.Equal(t, "testing", name)
assert.Equal(t, "Headers", typeName)
assert.Equal(t, trace.SpanKindInternal, spanKind)
}
// This test is an adapted version of net/http/httputil.Test1xxResponses test.

View File

@ -10,7 +10,6 @@ import (
"github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/vulcand/oxy/v2/connlimit"
"go.opentelemetry.io/otel/trace"
)
const (
@ -53,8 +52,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.InFlightReq, nam
return &inFlightReq{handler: handler, name: name}, nil
}
func (i *inFlightReq) GetTracingInformation() (string, string, trace.SpanKind) {
return i.name, typeName, trace.SpanKindInternal
func (i *inFlightReq) GetTracingInformation() (string, string) {
return i.name, typeName
}
func (i *inFlightReq) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -11,7 +11,6 @@ import (
"github.com/traefik/traefik/v3/pkg/ip"
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"go.opentelemetry.io/otel/trace"
)
const (
@ -65,8 +64,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, nam
}, nil
}
func (al *ipAllowLister) GetTracingInformation() (string, string, trace.SpanKind) {
return al.name, typeName, trace.SpanKindInternal
func (al *ipAllowLister) GetTracingInformation() (string, string) {
return al.name, typeName
}
func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -11,7 +11,6 @@ import (
"github.com/traefik/traefik/v3/pkg/ip"
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"go.opentelemetry.io/otel/trace"
)
const (
@ -55,8 +54,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPWhiteList, nam
}, nil
}
func (wl *ipWhiteLister) GetTracingInformation() (string, string, trace.SpanKind) {
return wl.name, typeName, trace.SpanKindInternal
func (wl *ipWhiteLister) GetTracingInformation() (string, string) {
return wl.name, typeName
}
func (wl *ipWhiteLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -18,7 +18,6 @@ import (
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"github.com/traefik/traefik/v3/pkg/middlewares/retry"
traefiktls "github.com/traefik/traefik/v3/pkg/tls"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc/codes"
)
@ -93,33 +92,45 @@ func NewServiceMiddleware(ctx context.Context, next http.Handler, registry metri
}
}
// WrapEntryPointHandler Wraps metrics entrypoint to alice.Constructor.
func WrapEntryPointHandler(ctx context.Context, registry metrics.Registry, entryPointName string) alice.Constructor {
// EntryPointMetricsHandler returns the metrics entrypoint handler.
func EntryPointMetricsHandler(ctx context.Context, registry metrics.Registry, entryPointName string) alice.Constructor {
return func(next http.Handler) (http.Handler, error) {
if registry == nil || !registry.IsEpEnabled() {
return next, nil
}
return NewEntryPointMiddleware(ctx, next, registry, entryPointName), nil
}
}
// WrapRouterHandler Wraps metrics router to alice.Constructor.
func WrapRouterHandler(ctx context.Context, registry metrics.Registry, routerName string, serviceName string) alice.Constructor {
// RouterMetricsHandler returns the metrics router handler.
func RouterMetricsHandler(ctx context.Context, registry metrics.Registry, routerName string, serviceName string) alice.Constructor {
return func(next http.Handler) (http.Handler, error) {
if registry == nil || !registry.IsRouterEnabled() {
return next, nil
}
return NewRouterMiddleware(ctx, next, registry, routerName, serviceName), nil
}
}
// WrapServiceHandler Wraps metrics service to alice.Constructor.
func WrapServiceHandler(ctx context.Context, registry metrics.Registry, serviceName string) alice.Constructor {
// ServiceMetricsHandler returns the metrics service handler.
func ServiceMetricsHandler(ctx context.Context, registry metrics.Registry, serviceName string) alice.Constructor {
return func(next http.Handler) (http.Handler, error) {
if registry == nil || !registry.IsSvcEnabled() {
return next, nil
}
return NewServiceMiddleware(ctx, next, registry, serviceName), nil
}
}
func (m *metricsMiddleware) GetTracingInformation() (string, string, trace.SpanKind) {
return m.name, typeName, trace.SpanKindInternal
func (m *metricsMiddleware) GetTracingInformation() (string, string) {
return m.name, typeName
}
func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if val := req.Context().Value(observability.DisableMetricsKey); val != nil {
if !observability.MetricsEnabled(req.Context()) {
m.next.ServeHTTP(rw, req)
return
}

View File

@ -48,11 +48,17 @@ func newEntryPoint(ctx context.Context, tracer *tracing.Tracer, entryPointName s
}
func (e *entryPointTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if e.tracer == nil || !TracingEnabled(req.Context()) {
e.next.ServeHTTP(rw, req)
return
}
tracingCtx := tracing.ExtractCarrierIntoContext(req.Context(), req.Header)
start := time.Now()
tracingCtx, span := e.tracer.Start(tracingCtx, "EntryPoint", trace.WithSpanKind(trace.SpanKindServer), trace.WithTimestamp(start))
// Associate the request context with the logger.
// This allows the logger to be aware of the tracing context and log accordingly (TraceID, SpanID, etc.).
logger := log.Ctx(tracingCtx).With().Ctx(tracingCtx).Logger()
loggerCtx := logger.WithContext(tracingCtx)

View File

@ -14,7 +14,7 @@ import (
// Traceable embeds tracing information.
type Traceable interface {
GetTracingInformation() (name string, typeName string, spanKind trace.SpanKind)
GetTracingInformation() (name string, typeName string)
}
// WrapMiddleware adds traceability to an alice.Constructor.
@ -29,21 +29,20 @@ func WrapMiddleware(ctx context.Context, constructor alice.Constructor) alice.Co
}
if traceableHandler, ok := handler.(Traceable); ok {
name, typeName, spanKind := traceableHandler.GetTracingInformation()
name, typeName := traceableHandler.GetTracingInformation()
log.Ctx(ctx).Debug().Str(logs.MiddlewareName, name).Msg("Adding tracing to middleware")
return NewMiddleware(handler, name, typeName, spanKind), nil
return NewMiddleware(handler, name, typeName), nil
}
return handler, nil
}
}
// NewMiddleware returns a http.Handler struct.
func NewMiddleware(next http.Handler, name string, typeName string, spanKind trace.SpanKind) http.Handler {
func NewMiddleware(next http.Handler, name string, typeName string) http.Handler {
return &middlewareTracing{
next: next,
name: name,
typeName: typeName,
spanKind: spanKind,
}
}
@ -52,12 +51,11 @@ type middlewareTracing struct {
next http.Handler
name string
typeName string
spanKind trace.SpanKind
}
func (w *middlewareTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if tracer := tracing.TracerFromContext(req.Context()); tracer != nil {
tracingCtx, span := tracer.Start(req.Context(), w.typeName, trace.WithSpanKind(w.spanKind))
if tracer := tracing.TracerFromContext(req.Context()); tracer != nil && DetailedTracingEnabled(req.Context()) {
tracingCtx, span := tracer.Start(req.Context(), w.typeName, trace.WithSpanKind(trace.SpanKindInternal))
defer span.End()
req = req.WithContext(tracingCtx)

View File

@ -3,6 +3,7 @@ package observability
import (
"context"
"fmt"
"net/http"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
@ -10,8 +11,58 @@ import (
type contextKey int
// DisableMetricsKey is a context key used to disable the metrics.
const DisableMetricsKey contextKey = iota
const observabilityKey contextKey = iota
type Observability struct {
AccessLogsEnabled bool
MetricsEnabled bool
SemConvMetricsEnabled bool
TracingEnabled bool
DetailedTracingEnabled bool
}
// WithObservabilityHandler sets the observability state in the context for the next handler.
// This is also used for testing purposes to control whether access logs are enabled or not.
func WithObservabilityHandler(next http.Handler, obs Observability) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
next.ServeHTTP(rw, req.WithContext(WithObservability(req.Context(), obs)))
})
}
// WithObservability injects the observability state into the context.
func WithObservability(ctx context.Context, obs Observability) context.Context {
return context.WithValue(ctx, observabilityKey, obs)
}
// AccessLogsEnabled returns whether access-logs are enabled.
func AccessLogsEnabled(ctx context.Context) bool {
obs, ok := ctx.Value(observabilityKey).(Observability)
return ok && obs.AccessLogsEnabled
}
// MetricsEnabled returns whether metrics are enabled.
func MetricsEnabled(ctx context.Context) bool {
obs, ok := ctx.Value(observabilityKey).(Observability)
return ok && obs.MetricsEnabled
}
// SemConvMetricsEnabled returns whether metrics are enabled.
func SemConvMetricsEnabled(ctx context.Context) bool {
obs, ok := ctx.Value(observabilityKey).(Observability)
return ok && obs.SemConvMetricsEnabled
}
// TracingEnabled returns whether tracing is enabled.
func TracingEnabled(ctx context.Context) bool {
obs, ok := ctx.Value(observabilityKey).(Observability)
return ok && obs.TracingEnabled
}
// DetailedTracingEnabled returns whether detailed tracing is enabled.
func DetailedTracingEnabled(ctx context.Context) bool {
obs, ok := ctx.Value(observabilityKey).(Observability)
return ok && obs.DetailedTracingEnabled
}
// SetStatusErrorf flags the span as in error and log an event.
func SetStatusErrorf(ctx context.Context, format string, args ...interface{}) {

View File

@ -45,7 +45,7 @@ func newRouter(ctx context.Context, router, routerRule, service string, next htt
}
func (f *routerTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if tracer := tracing.TracerFromContext(req.Context()); tracer != nil {
if tracer := tracing.TracerFromContext(req.Context()); tracer != nil && DetailedTracingEnabled(req.Context()) {
tracingCtx, span := tracer.Start(req.Context(), "Router", trace.WithSpanKind(trace.SpanKindInternal))
defer span.End()

View File

@ -46,7 +46,7 @@ func newServerMetricsSemConv(ctx context.Context, semConvMetricRegistry *metrics
}
func (e *semConvServerMetrics) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if e.semConvMetricRegistry == nil || e.semConvMetricRegistry.HTTPServerRequestDuration() == nil {
if e.semConvMetricRegistry == nil || e.semConvMetricRegistry.HTTPServerRequestDuration() == nil || !SemConvMetricsEnabled(req.Context()) {
e.next.ServeHTTP(rw, req)
return
}

View File

@ -83,6 +83,11 @@ func TestSemConvServerMetrics(t *testing.T) {
handler, err = capture.Wrap(handler)
require.NoError(t, err)
// Injection of the observability variables in the request context.
handler = WithObservabilityHandler(handler, Observability{
SemConvMetricsEnabled: true,
})
handler.ServeHTTP(rw, req)
got := metricdata.ResourceMetrics{}

View File

@ -32,7 +32,7 @@ func NewService(ctx context.Context, service string, next http.Handler) http.Han
}
func (t *serviceTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if tracer := tracing.TracerFromContext(req.Context()); tracer != nil {
if tracer := tracing.TracerFromContext(req.Context()); tracer != nil && DetailedTracingEnabled(req.Context()) {
tracingCtx, span := tracer.Start(req.Context(), "Service", trace.WithSpanKind(trace.SpanKindInternal))
defer span.End()

View File

@ -14,7 +14,6 @@ import (
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"go.opentelemetry.io/otel/trace"
)
const typeName = "PassClientTLSCert"
@ -139,8 +138,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.PassTLSClientCer
}, nil
}
func (p *passTLSClientCert) GetTracingInformation() (string, string, trace.SpanKind) {
return p.name, typeName, trace.SpanKindInternal
func (p *passTLSClientCert) GetTracingInformation() (string, string) {
return p.name, typeName
}
func (p *passTLSClientCert) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

View File

@ -14,7 +14,6 @@ import (
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/traefik/traefik/v3/pkg/middlewares/observability"
"github.com/vulcand/oxy/v2/utils"
"go.opentelemetry.io/otel/trace"
"golang.org/x/time/rate"
)
@ -127,8 +126,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.RateLimit, name
}, nil
}
func (rl *rateLimiter) GetTracingInformation() (string, string, trace.SpanKind) {
return rl.name, typeName, trace.SpanKindInternal
func (rl *rateLimiter) GetTracingInformation() (string, string) {
return rl.name, typeName
}
func (rl *rateLimiter) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

Some files were not shown because too many files have changed in this diff Show More