124 lines
3.7 KiB
Go
124 lines
3.7 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/containous/alice"
|
|
"github.com/containous/traefik/v2/pkg/config/static"
|
|
"github.com/containous/traefik/v2/pkg/log"
|
|
"github.com/containous/traefik/v2/pkg/metrics"
|
|
"github.com/containous/traefik/v2/pkg/middlewares/accesslog"
|
|
metricsmiddleware "github.com/containous/traefik/v2/pkg/middlewares/metrics"
|
|
"github.com/containous/traefik/v2/pkg/middlewares/requestdecorator"
|
|
mTracing "github.com/containous/traefik/v2/pkg/middlewares/tracing"
|
|
"github.com/containous/traefik/v2/pkg/tracing"
|
|
"github.com/containous/traefik/v2/pkg/tracing/jaeger"
|
|
)
|
|
|
|
// ChainBuilder Creates a middleware chain by entry point. It is used for middlewares that are created almost systematically and that need to be created before all others.
|
|
type ChainBuilder struct {
|
|
metricsRegistry metrics.Registry
|
|
accessLoggerMiddleware *accesslog.Handler
|
|
tracer *tracing.Tracing
|
|
requestDecorator *requestdecorator.RequestDecorator
|
|
}
|
|
|
|
// NewChainBuilder Creates a new ChainBuilder.
|
|
func NewChainBuilder(staticConfiguration static.Configuration, metricsRegistry metrics.Registry, accessLoggerMiddleware *accesslog.Handler) *ChainBuilder {
|
|
return &ChainBuilder{
|
|
metricsRegistry: metricsRegistry,
|
|
accessLoggerMiddleware: accessLoggerMiddleware,
|
|
tracer: setupTracing(staticConfiguration.Tracing),
|
|
requestDecorator: requestdecorator.New(staticConfiguration.HostResolver),
|
|
}
|
|
}
|
|
|
|
// Build a middleware chain by entry point.
|
|
func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.Chain {
|
|
chain := alice.New()
|
|
|
|
if c.accessLoggerMiddleware != nil {
|
|
chain = chain.Append(accesslog.WrapHandler(c.accessLoggerMiddleware))
|
|
}
|
|
|
|
if c.tracer != nil {
|
|
chain = chain.Append(mTracing.WrapEntryPointHandler(ctx, c.tracer, entryPointName))
|
|
}
|
|
|
|
if c.metricsRegistry != nil && c.metricsRegistry.IsEpEnabled() {
|
|
chain = chain.Append(metricsmiddleware.WrapEntryPointHandler(ctx, c.metricsRegistry, entryPointName))
|
|
}
|
|
|
|
return chain.Append(requestdecorator.WrapHandler(c.requestDecorator))
|
|
}
|
|
|
|
// Close accessLogger and tracer.
|
|
func (c *ChainBuilder) Close() {
|
|
if c.accessLoggerMiddleware != nil {
|
|
if err := c.accessLoggerMiddleware.Close(); err != nil {
|
|
log.WithoutContext().Errorf("Could not close the access log file: %s", err)
|
|
}
|
|
}
|
|
|
|
if c.tracer != nil {
|
|
c.tracer.Close()
|
|
}
|
|
}
|
|
|
|
func setupTracing(conf *static.Tracing) *tracing.Tracing {
|
|
if conf == nil {
|
|
return nil
|
|
}
|
|
|
|
var backend tracing.Backend
|
|
|
|
if conf.Jaeger != nil {
|
|
backend = conf.Jaeger
|
|
}
|
|
|
|
if conf.Zipkin != nil {
|
|
if backend != nil {
|
|
log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Zipkin backend.")
|
|
} else {
|
|
backend = conf.Zipkin
|
|
}
|
|
}
|
|
|
|
if conf.Datadog != nil {
|
|
if backend != nil {
|
|
log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Datadog backend.")
|
|
} else {
|
|
backend = conf.Datadog
|
|
}
|
|
}
|
|
|
|
if conf.Instana != nil {
|
|
if backend != nil {
|
|
log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Instana backend.")
|
|
} else {
|
|
backend = conf.Instana
|
|
}
|
|
}
|
|
|
|
if conf.Haystack != nil {
|
|
if backend != nil {
|
|
log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Haystack backend.")
|
|
} else {
|
|
backend = conf.Haystack
|
|
}
|
|
}
|
|
|
|
if backend == nil {
|
|
log.WithoutContext().Debug("Could not initialize tracing, using Jaeger by default")
|
|
defaultBackend := &jaeger.Config{}
|
|
defaultBackend.SetDefaults()
|
|
backend = defaultBackend
|
|
}
|
|
|
|
tracer, err := tracing.NewTracing(conf.ServiceName, conf.SpanNameLimit, backend)
|
|
if err != nil {
|
|
log.WithoutContext().Warnf("Unable to create tracer: %v", err)
|
|
return nil
|
|
}
|
|
return tracer
|
|
}
|