Add traffic size metrics
Co-authored-by: OmarElawady <omarelawady1998@gmail.com> Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com> Co-authored-by: Romain <rtribotte@users.noreply.github.com>
This commit is contained in:
parent
10528c973a
commit
d578ed7327
26 changed files with 1125 additions and 339 deletions
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
"github.com/traefik/traefik/v2/pkg/metrics"
|
"github.com/traefik/traefik/v2/pkg/metrics"
|
||||||
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
|
||||||
"github.com/traefik/traefik/v2/pkg/pilot"
|
"github.com/traefik/traefik/v2/pkg/pilot"
|
||||||
"github.com/traefik/traefik/v2/pkg/provider/acme"
|
"github.com/traefik/traefik/v2/pkg/provider/acme"
|
||||||
"github.com/traefik/traefik/v2/pkg/provider/aggregator"
|
"github.com/traefik/traefik/v2/pkg/provider/aggregator"
|
||||||
|
@ -41,6 +42,8 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/server/middleware"
|
"github.com/traefik/traefik/v2/pkg/server/middleware"
|
||||||
"github.com/traefik/traefik/v2/pkg/server/service"
|
"github.com/traefik/traefik/v2/pkg/server/service"
|
||||||
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/tracing"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/tracing/jaeger"
|
||||||
"github.com/traefik/traefik/v2/pkg/types"
|
"github.com/traefik/traefik/v2/pkg/types"
|
||||||
"github.com/traefik/traefik/v2/pkg/version"
|
"github.com/traefik/traefik/v2/pkg/version"
|
||||||
"github.com/vulcand/oxy/roundrobin"
|
"github.com/vulcand/oxy/roundrobin"
|
||||||
|
@ -270,7 +273,10 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
|
||||||
// Router factory
|
// Router factory
|
||||||
|
|
||||||
accessLog := setupAccessLog(staticConfiguration.AccessLog)
|
accessLog := setupAccessLog(staticConfiguration.AccessLog)
|
||||||
chainBuilder := middleware.NewChainBuilder(*staticConfiguration, metricsRegistry, accessLog)
|
tracer := setupTracing(staticConfiguration.Tracing)
|
||||||
|
captureMiddleware := setupCapture(staticConfiguration)
|
||||||
|
|
||||||
|
chainBuilder := middleware.NewChainBuilder(metricsRegistry, accessLog, tracer, captureMiddleware)
|
||||||
routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry)
|
routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry)
|
||||||
|
|
||||||
// Watcher
|
// Watcher
|
||||||
|
@ -504,13 +510,86 @@ func setupAccessLog(conf *types.AccessLog) *accesslog.Handler {
|
||||||
|
|
||||||
accessLoggerMiddleware, err := accesslog.NewHandler(conf)
|
accessLoggerMiddleware, err := accesslog.NewHandler(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithoutContext().Warnf("Unable to create access logger : %v", err)
|
log.WithoutContext().Warnf("Unable to create access logger: %v", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return accessLoggerMiddleware
|
return accessLoggerMiddleware
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 conf.Elastic != nil {
|
||||||
|
if backend != nil {
|
||||||
|
log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Elastic backend.")
|
||||||
|
} else {
|
||||||
|
backend = conf.Elastic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupCapture(staticConfiguration *static.Configuration) *capture.Handler {
|
||||||
|
if staticConfiguration.AccessLog == nil && staticConfiguration.Metrics == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &capture.Handler{}
|
||||||
|
}
|
||||||
|
|
||||||
func configureLogging(staticConfiguration *static.Configuration) {
|
func configureLogging(staticConfiguration *static.Configuration) {
|
||||||
// configure default log flags
|
// configure default log flags
|
||||||
stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags)
|
stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags)
|
||||||
|
|
|
@ -94,6 +94,8 @@ traefik_tls_certs_not_after
|
||||||
| [HTTPS Requests Count](#https-requests-count) | ✓ | ✓ | ✓ | ✓ |
|
| [HTTPS Requests Count](#https-requests-count) | ✓ | ✓ | ✓ | ✓ |
|
||||||
| [Request Duration Histogram](#request-duration-histogram) | ✓ | ✓ | ✓ | ✓ |
|
| [Request Duration Histogram](#request-duration-histogram) | ✓ | ✓ | ✓ | ✓ |
|
||||||
| [Open Connections Count](#open-connections-count) | ✓ | ✓ | ✓ | ✓ |
|
| [Open Connections Count](#open-connections-count) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| [Requests Bytes Count](#requests-bytes-count) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| [Responses Bytes Count](#responses-bytes-count) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
|
||||||
### HTTP Requests Count
|
### HTTP Requests Count
|
||||||
|
|
||||||
|
@ -187,6 +189,52 @@ traefik_entrypoint_open_connections
|
||||||
{prefix}.entrypoint.connections.open
|
{prefix}.entrypoint.connections.open
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Requests Bytes Count
|
||||||
|
|
||||||
|
The total size of HTTP requests in bytes handled by an entrypoint.
|
||||||
|
|
||||||
|
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||||
|
|
||||||
|
```dd tab="Datadog"
|
||||||
|
entrypoint.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```influxdb tab="InfluxDB / InfluxDB2"
|
||||||
|
traefik.entrypoint.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```prom tab="Prometheus"
|
||||||
|
traefik_entrypoint_requests_bytes_total
|
||||||
|
```
|
||||||
|
|
||||||
|
```statsd tab="StatsD"
|
||||||
|
# Default prefix: "traefik"
|
||||||
|
{prefix}.entrypoint.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
### Responses Bytes Count
|
||||||
|
|
||||||
|
The total size of HTTP responses in bytes handled by an entrypoint.
|
||||||
|
|
||||||
|
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||||
|
|
||||||
|
```dd tab="Datadog"
|
||||||
|
entrypoint.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```influxdb tab="InfluxDB / InfluxDB2"
|
||||||
|
traefik.entrypoint.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```prom tab="Prometheus"
|
||||||
|
traefik_entrypoint_responses_bytes_total
|
||||||
|
```
|
||||||
|
|
||||||
|
```statsd tab="StatsD"
|
||||||
|
# Default prefix: "traefik"
|
||||||
|
{prefix}.entrypoint.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
## Router Metrics
|
## Router Metrics
|
||||||
|
|
||||||
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
||||||
|
@ -195,6 +243,8 @@ traefik_entrypoint_open_connections
|
||||||
| [HTTPS Requests Count](#https-requests-count_1) | ✓ | ✓ | ✓ | ✓ |
|
| [HTTPS Requests Count](#https-requests-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||||
| [Request Duration Histogram](#request-duration-histogram_1) | ✓ | ✓ | ✓ | ✓ |
|
| [Request Duration Histogram](#request-duration-histogram_1) | ✓ | ✓ | ✓ | ✓ |
|
||||||
| [Open Connections Count](#open-connections-count_1) | ✓ | ✓ | ✓ | ✓ |
|
| [Open Connections Count](#open-connections-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| [Requests Bytes Count](#requests-bytes-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| [Responses Bytes Count](#responses-bytes-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
|
||||||
### HTTP Requests Count
|
### HTTP Requests Count
|
||||||
|
|
||||||
|
@ -288,6 +338,52 @@ traefik_router_open_connections
|
||||||
{prefix}.router.connections.open
|
{prefix}.router.connections.open
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Requests Bytes Count
|
||||||
|
|
||||||
|
The total size of HTTP requests in bytes handled by a router.
|
||||||
|
|
||||||
|
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||||
|
|
||||||
|
```dd tab="Datadog"
|
||||||
|
router.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```influxdb tab="InfluxDB / InfluxDB2"
|
||||||
|
traefik.router.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```prom tab="Prometheus"
|
||||||
|
traefik_router_requests_bytes_total
|
||||||
|
```
|
||||||
|
|
||||||
|
```statsd tab="StatsD"
|
||||||
|
# Default prefix: "traefik"
|
||||||
|
{prefix}.router.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
### Responses Bytes Count
|
||||||
|
|
||||||
|
The total size of HTTP responses in bytes handled by a router.
|
||||||
|
|
||||||
|
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||||
|
|
||||||
|
```dd tab="Datadog"
|
||||||
|
router.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```influxdb tab="InfluxDB / InfluxDB2"
|
||||||
|
traefik.router.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```prom tab="Prometheus"
|
||||||
|
traefik_router_responses_bytes_total
|
||||||
|
```
|
||||||
|
|
||||||
|
```statsd tab="StatsD"
|
||||||
|
# Default prefix: "traefik"
|
||||||
|
{prefix}.router.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
## Service Metrics
|
## Service Metrics
|
||||||
|
|
||||||
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
||||||
|
@ -298,6 +394,8 @@ traefik_router_open_connections
|
||||||
| [Open Connections Count](#open-connections-count_2) | ✓ | ✓ | ✓ | ✓ |
|
| [Open Connections Count](#open-connections-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||||
| [Requests Retries Count](#requests-retries-count) | ✓ | ✓ | ✓ | ✓ |
|
| [Requests Retries Count](#requests-retries-count) | ✓ | ✓ | ✓ | ✓ |
|
||||||
| [Service Server UP](#service-server-up) | ✓ | ✓ | ✓ | ✓ |
|
| [Service Server UP](#service-server-up) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| [Requests Bytes Count](#requests-bytes-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| [Responses outgoing traffic](#responses-bytes-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
|
||||||
### HTTP Requests Count
|
### HTTP Requests Count
|
||||||
|
|
||||||
|
@ -437,6 +535,52 @@ traefik_service_server_up
|
||||||
{prefix}.service.server.up
|
{prefix}.service.server.up
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Requests Bytes Count
|
||||||
|
|
||||||
|
The total size of requests in bytes received by a service.
|
||||||
|
|
||||||
|
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||||
|
|
||||||
|
```dd tab="Datadog"
|
||||||
|
service.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```influxdb tab="InfluxDB / InfluxDB2"
|
||||||
|
traefik.service.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```prom tab="Prometheus"
|
||||||
|
traefik_service_requests_bytes_total
|
||||||
|
```
|
||||||
|
|
||||||
|
```statsd tab="StatsD"
|
||||||
|
# Default prefix: "traefik"
|
||||||
|
{prefix}.service.requests.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
### Responses Bytes Count
|
||||||
|
|
||||||
|
The total size of responses in bytes returned by a service.
|
||||||
|
|
||||||
|
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||||
|
|
||||||
|
```dd tab="Datadog"
|
||||||
|
service.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```influxdb tab="InfluxDB / InfluxDB2"
|
||||||
|
traefik.service.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
|
```prom tab="Prometheus"
|
||||||
|
traefik_service_responses_bytes_total
|
||||||
|
```
|
||||||
|
|
||||||
|
```statsd tab="StatsD"
|
||||||
|
# Default prefix: "traefik"
|
||||||
|
{prefix}.service.responses.bytes.total
|
||||||
|
```
|
||||||
|
|
||||||
## Labels
|
## Labels
|
||||||
|
|
||||||
Here is a comprehensive list of labels that are provided by the metrics:
|
Here is a comprehensive list of labels that are provided by the metrics:
|
||||||
|
|
|
@ -28,18 +28,24 @@ const (
|
||||||
ddEntryPointReqsTLSName = "entrypoint.request.tls.total"
|
ddEntryPointReqsTLSName = "entrypoint.request.tls.total"
|
||||||
ddEntryPointReqDurationName = "entrypoint.request.duration"
|
ddEntryPointReqDurationName = "entrypoint.request.duration"
|
||||||
ddEntryPointOpenConnsName = "entrypoint.connections.open"
|
ddEntryPointOpenConnsName = "entrypoint.connections.open"
|
||||||
|
ddEntryPointReqsBytesName = "entrypoint.requests.bytes.total"
|
||||||
|
ddEntryPointRespsBytesName = "entrypoint.responses.bytes.total"
|
||||||
|
|
||||||
ddMetricsRouterReqsName = "router.request.total"
|
ddRouterReqsName = "router.request.total"
|
||||||
ddMetricsRouterReqsTLSName = "router.request.tls.total"
|
ddRouterReqsTLSName = "router.request.tls.total"
|
||||||
ddMetricsRouterReqsDurationName = "router.request.duration"
|
ddRouterReqsDurationName = "router.request.duration"
|
||||||
ddRouterOpenConnsName = "router.connections.open"
|
ddRouterOpenConnsName = "router.connections.open"
|
||||||
|
ddRouterReqsBytesName = "router.requests.bytes.total"
|
||||||
|
ddRouterRespsBytesName = "router.responses.bytes.total"
|
||||||
|
|
||||||
ddMetricsServiceReqsName = "service.request.total"
|
ddServiceReqsName = "service.request.total"
|
||||||
ddMetricsServiceReqsTLSName = "service.request.tls.total"
|
ddServiceReqsTLSName = "service.request.tls.total"
|
||||||
ddMetricsServiceReqsDurationName = "service.request.duration"
|
ddServiceReqsDurationName = "service.request.duration"
|
||||||
ddRetriesTotalName = "service.retries.total"
|
ddServiceRetriesName = "service.retries.total"
|
||||||
ddOpenConnsName = "service.connections.open"
|
ddServiceOpenConnsName = "service.connections.open"
|
||||||
ddServerUpName = "service.server.up"
|
ddServiceServerUpName = "service.server.up"
|
||||||
|
ddServiceReqsBytesName = "service.requests.bytes.total"
|
||||||
|
ddServiceRespsBytesName = "service.responses.bytes.total"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterDatadog registers the metrics pusher if this didn't happen yet and creates a datadog Registry instance.
|
// RegisterDatadog registers the metrics pusher if this didn't happen yet and creates a datadog Registry instance.
|
||||||
|
@ -73,24 +79,30 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry {
|
||||||
registry.entryPointReqsTLSCounter = datadogClient.NewCounter(ddEntryPointReqsTLSName, 1.0)
|
registry.entryPointReqsTLSCounter = datadogClient.NewCounter(ddEntryPointReqsTLSName, 1.0)
|
||||||
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddEntryPointReqDurationName, 1.0), time.Second)
|
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddEntryPointReqDurationName, 1.0), time.Second)
|
||||||
registry.entryPointOpenConnsGauge = datadogClient.NewGauge(ddEntryPointOpenConnsName)
|
registry.entryPointOpenConnsGauge = datadogClient.NewGauge(ddEntryPointOpenConnsName)
|
||||||
|
registry.entryPointReqsBytesCounter = datadogClient.NewCounter(ddEntryPointReqsBytesName, 1.0)
|
||||||
|
registry.entryPointRespsBytesCounter = datadogClient.NewCounter(ddEntryPointRespsBytesName, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddRoutersLabels {
|
if config.AddRoutersLabels {
|
||||||
registry.routerEnabled = config.AddRoutersLabels
|
registry.routerEnabled = config.AddRoutersLabels
|
||||||
registry.routerReqsCounter = datadogClient.NewCounter(ddMetricsRouterReqsName, 1.0)
|
registry.routerReqsCounter = datadogClient.NewCounter(ddRouterReqsName, 1.0)
|
||||||
registry.routerReqsTLSCounter = datadogClient.NewCounter(ddMetricsRouterReqsTLSName, 1.0)
|
registry.routerReqsTLSCounter = datadogClient.NewCounter(ddRouterReqsTLSName, 1.0)
|
||||||
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddMetricsRouterReqsDurationName, 1.0), time.Second)
|
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddRouterReqsDurationName, 1.0), time.Second)
|
||||||
registry.routerOpenConnsGauge = datadogClient.NewGauge(ddRouterOpenConnsName)
|
registry.routerOpenConnsGauge = datadogClient.NewGauge(ddRouterOpenConnsName)
|
||||||
|
registry.routerReqsBytesCounter = datadogClient.NewCounter(ddRouterReqsBytesName, 1.0)
|
||||||
|
registry.routerRespsBytesCounter = datadogClient.NewCounter(ddRouterRespsBytesName, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddServicesLabels {
|
if config.AddServicesLabels {
|
||||||
registry.svcEnabled = config.AddServicesLabels
|
registry.svcEnabled = config.AddServicesLabels
|
||||||
registry.serviceReqsCounter = datadogClient.NewCounter(ddMetricsServiceReqsName, 1.0)
|
registry.serviceReqsCounter = datadogClient.NewCounter(ddServiceReqsName, 1.0)
|
||||||
registry.serviceReqsTLSCounter = datadogClient.NewCounter(ddMetricsServiceReqsTLSName, 1.0)
|
registry.serviceReqsTLSCounter = datadogClient.NewCounter(ddServiceReqsTLSName, 1.0)
|
||||||
registry.serviceReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddMetricsServiceReqsDurationName, 1.0), time.Second)
|
registry.serviceReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddServiceReqsDurationName, 1.0), time.Second)
|
||||||
registry.serviceRetriesCounter = datadogClient.NewCounter(ddRetriesTotalName, 1.0)
|
registry.serviceRetriesCounter = datadogClient.NewCounter(ddServiceRetriesName, 1.0)
|
||||||
registry.serviceOpenConnsGauge = datadogClient.NewGauge(ddOpenConnsName)
|
registry.serviceOpenConnsGauge = datadogClient.NewGauge(ddServiceOpenConnsName)
|
||||||
registry.serviceServerUpGauge = datadogClient.NewGauge(ddServerUpName)
|
registry.serviceServerUpGauge = datadogClient.NewGauge(ddServiceServerUpName)
|
||||||
|
registry.serviceReqsBytesCounter = datadogClient.NewCounter(ddServiceReqsBytesName, 1.0)
|
||||||
|
registry.serviceRespsBytesCounter = datadogClient.NewCounter(ddServiceRespsBytesName, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return registry
|
return registry
|
||||||
|
|
|
@ -55,12 +55,16 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg
|
||||||
metricsPrefix + ".entrypoint.request.tls.total:1.000000|c|#entrypoint:test,tls_version:foo,tls_cipher:bar\n",
|
metricsPrefix + ".entrypoint.request.tls.total:1.000000|c|#entrypoint:test,tls_version:foo,tls_cipher:bar\n",
|
||||||
metricsPrefix + ".entrypoint.request.duration:10000.000000|h|#entrypoint:test\n",
|
metricsPrefix + ".entrypoint.request.duration:10000.000000|h|#entrypoint:test\n",
|
||||||
metricsPrefix + ".entrypoint.connections.open:1.000000|g|#entrypoint:test\n",
|
metricsPrefix + ".entrypoint.connections.open:1.000000|g|#entrypoint:test\n",
|
||||||
|
metricsPrefix + ".entrypoint.requests.bytes.total:1.000000|c|#entrypoint:test\n",
|
||||||
|
metricsPrefix + ".entrypoint.responses.bytes.total:1.000000|c|#entrypoint:test\n",
|
||||||
|
|
||||||
metricsPrefix + ".router.request.total:1.000000|c|#router:demo,service:test,code:404,method:GET\n",
|
metricsPrefix + ".router.request.total:1.000000|c|#router:demo,service:test,code:404,method:GET\n",
|
||||||
metricsPrefix + ".router.request.total:1.000000|c|#router:demo,service:test,code:200,method:GET\n",
|
metricsPrefix + ".router.request.total:1.000000|c|#router:demo,service:test,code:200,method:GET\n",
|
||||||
metricsPrefix + ".router.request.tls.total:1.000000|c|#router:demo,service:test,tls_version:foo,tls_cipher:bar\n",
|
metricsPrefix + ".router.request.tls.total:1.000000|c|#router:demo,service:test,tls_version:foo,tls_cipher:bar\n",
|
||||||
metricsPrefix + ".router.request.duration:10000.000000|h|#router:demo,service:test,code:200\n",
|
metricsPrefix + ".router.request.duration:10000.000000|h|#router:demo,service:test,code:200\n",
|
||||||
metricsPrefix + ".router.connections.open:1.000000|g|#router:demo,service:test\n",
|
metricsPrefix + ".router.connections.open:1.000000|g|#router:demo,service:test\n",
|
||||||
|
metricsPrefix + ".router.requests.bytes.total:1.000000|c|#router:demo,service:test,code:200,method:GET\n",
|
||||||
|
metricsPrefix + ".router.responses.bytes.total:1.000000|c|#router:demo,service:test,code:200,method:GET\n",
|
||||||
|
|
||||||
metricsPrefix + ".service.request.total:1.000000|c|#service:test,code:404,method:GET\n",
|
metricsPrefix + ".service.request.total:1.000000|c|#service:test,code:404,method:GET\n",
|
||||||
metricsPrefix + ".service.request.total:1.000000|c|#service:test,code:200,method:GET\n",
|
metricsPrefix + ".service.request.total:1.000000|c|#service:test,code:200,method:GET\n",
|
||||||
|
@ -70,6 +74,8 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg
|
||||||
metricsPrefix + ".service.retries.total:2.000000|c|#service:test\n",
|
metricsPrefix + ".service.retries.total:2.000000|c|#service:test\n",
|
||||||
metricsPrefix + ".service.request.duration:10000.000000|h|#service:test,code:200\n",
|
metricsPrefix + ".service.request.duration:10000.000000|h|#service:test,code:200\n",
|
||||||
metricsPrefix + ".service.server.up:1.000000|g|#service:test,url:http://127.0.0.1,one:two\n",
|
metricsPrefix + ".service.server.up:1.000000|g|#service:test,url:http://127.0.0.1,one:two\n",
|
||||||
|
metricsPrefix + ".service.requests.bytes.total:1.000000|c|#service:test,code:200,method:GET\n",
|
||||||
|
metricsPrefix + ".service.responses.bytes.total:1.000000|c|#service:test,code:200,method:GET\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
udp.ShouldReceiveAll(t, expected, func() {
|
udp.ShouldReceiveAll(t, expected, func() {
|
||||||
|
@ -84,12 +90,16 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg
|
||||||
datadogRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
datadogRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
datadogRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
datadogRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
||||||
datadogRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
datadogRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
||||||
|
datadogRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test").Add(1)
|
||||||
|
datadogRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test").Add(1)
|
||||||
|
|
||||||
datadogRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
datadogRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
datadogRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
datadogRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
||||||
datadogRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
datadogRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
datadogRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
datadogRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
||||||
datadogRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
datadogRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
||||||
|
datadogRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
datadogRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
|
||||||
datadogRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
datadogRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
datadogRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
datadogRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
||||||
|
@ -99,5 +109,7 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg
|
||||||
datadogRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
datadogRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
datadogRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
datadogRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
datadogRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1", "one", "two").Set(1)
|
datadogRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1", "one", "two").Set(1)
|
||||||
|
datadogRegistry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
datadogRegistry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,15 @@ const (
|
||||||
influxDBEntryPointReqsTLSName = "traefik.entrypoint.requests.tls.total"
|
influxDBEntryPointReqsTLSName = "traefik.entrypoint.requests.tls.total"
|
||||||
influxDBEntryPointReqDurationName = "traefik.entrypoint.request.duration"
|
influxDBEntryPointReqDurationName = "traefik.entrypoint.request.duration"
|
||||||
influxDBEntryPointOpenConnsName = "traefik.entrypoint.connections.open"
|
influxDBEntryPointOpenConnsName = "traefik.entrypoint.connections.open"
|
||||||
|
influxDBEntryPointReqsBytesName = "traefik.entrypoint.requests.bytes.total"
|
||||||
|
influxDBEntryPointRespsBytesName = "traefik.entrypoint.responses.bytes.total"
|
||||||
|
|
||||||
influxDBRouterReqsName = "traefik.router.requests.total"
|
influxDBRouterReqsName = "traefik.router.requests.total"
|
||||||
influxDBRouterReqsTLSName = "traefik.router.requests.tls.total"
|
influxDBRouterReqsTLSName = "traefik.router.requests.tls.total"
|
||||||
influxDBRouterReqsDurationName = "traefik.router.request.duration"
|
influxDBRouterReqsDurationName = "traefik.router.request.duration"
|
||||||
influxDBORouterOpenConnsName = "traefik.router.connections.open"
|
influxDBORouterOpenConnsName = "traefik.router.connections.open"
|
||||||
|
influxDBRouterReqsBytesName = "traefik.router.requests.bytes.total"
|
||||||
|
influxDBRouterRespsBytesName = "traefik.router.responses.bytes.total"
|
||||||
|
|
||||||
influxDBServiceReqsName = "traefik.service.requests.total"
|
influxDBServiceReqsName = "traefik.service.requests.total"
|
||||||
influxDBServiceReqsTLSName = "traefik.service.requests.tls.total"
|
influxDBServiceReqsTLSName = "traefik.service.requests.tls.total"
|
||||||
|
@ -45,6 +49,8 @@ const (
|
||||||
influxDBServiceRetriesTotalName = "traefik.service.retries.total"
|
influxDBServiceRetriesTotalName = "traefik.service.retries.total"
|
||||||
influxDBServiceOpenConnsName = "traefik.service.connections.open"
|
influxDBServiceOpenConnsName = "traefik.service.connections.open"
|
||||||
influxDBServiceServerUpName = "traefik.service.server.up"
|
influxDBServiceServerUpName = "traefik.service.server.up"
|
||||||
|
influxDBServiceReqsBytesName = "traefik.service.requests.bytes.total"
|
||||||
|
influxDBServiceRespsBytesName = "traefik.service.responses.bytes.total"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -75,6 +81,8 @@ func RegisterInfluxDB(ctx context.Context, config *types.InfluxDB) Registry {
|
||||||
registry.entryPointReqsTLSCounter = influxDBClient.NewCounter(influxDBEntryPointReqsTLSName)
|
registry.entryPointReqsTLSCounter = influxDBClient.NewCounter(influxDBEntryPointReqsTLSName)
|
||||||
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBEntryPointReqDurationName), time.Second)
|
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBEntryPointReqDurationName), time.Second)
|
||||||
registry.entryPointOpenConnsGauge = influxDBClient.NewGauge(influxDBEntryPointOpenConnsName)
|
registry.entryPointOpenConnsGauge = influxDBClient.NewGauge(influxDBEntryPointOpenConnsName)
|
||||||
|
registry.entryPointReqsBytesCounter = influxDBClient.NewCounter(influxDBEntryPointReqsBytesName)
|
||||||
|
registry.entryPointRespsBytesCounter = influxDBClient.NewCounter(influxDBEntryPointRespsBytesName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddRoutersLabels {
|
if config.AddRoutersLabels {
|
||||||
|
@ -83,6 +91,8 @@ func RegisterInfluxDB(ctx context.Context, config *types.InfluxDB) Registry {
|
||||||
registry.routerReqsTLSCounter = influxDBClient.NewCounter(influxDBRouterReqsTLSName)
|
registry.routerReqsTLSCounter = influxDBClient.NewCounter(influxDBRouterReqsTLSName)
|
||||||
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBRouterReqsDurationName), time.Second)
|
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBRouterReqsDurationName), time.Second)
|
||||||
registry.routerOpenConnsGauge = influxDBClient.NewGauge(influxDBORouterOpenConnsName)
|
registry.routerOpenConnsGauge = influxDBClient.NewGauge(influxDBORouterOpenConnsName)
|
||||||
|
registry.routerReqsBytesCounter = influxDBClient.NewCounter(influxDBRouterReqsBytesName)
|
||||||
|
registry.routerRespsBytesCounter = influxDBClient.NewCounter(influxDBRouterRespsBytesName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddServicesLabels {
|
if config.AddServicesLabels {
|
||||||
|
@ -93,6 +103,8 @@ func RegisterInfluxDB(ctx context.Context, config *types.InfluxDB) Registry {
|
||||||
registry.serviceRetriesCounter = influxDBClient.NewCounter(influxDBServiceRetriesTotalName)
|
registry.serviceRetriesCounter = influxDBClient.NewCounter(influxDBServiceRetriesTotalName)
|
||||||
registry.serviceOpenConnsGauge = influxDBClient.NewGauge(influxDBServiceOpenConnsName)
|
registry.serviceOpenConnsGauge = influxDBClient.NewGauge(influxDBServiceOpenConnsName)
|
||||||
registry.serviceServerUpGauge = influxDBClient.NewGauge(influxDBServiceServerUpName)
|
registry.serviceServerUpGauge = influxDBClient.NewGauge(influxDBServiceServerUpName)
|
||||||
|
registry.serviceReqsBytesCounter = influxDBClient.NewCounter(influxDBServiceReqsBytesName)
|
||||||
|
registry.serviceRespsBytesCounter = influxDBClient.NewCounter(influxDBServiceRespsBytesName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return registry
|
return registry
|
||||||
|
|
|
@ -65,6 +65,8 @@ func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry {
|
||||||
registry.entryPointReqsTLSCounter = influxDB2Store.NewCounter(influxDBEntryPointReqsTLSName)
|
registry.entryPointReqsTLSCounter = influxDB2Store.NewCounter(influxDBEntryPointReqsTLSName)
|
||||||
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(influxDB2Store.NewHistogram(influxDBEntryPointReqDurationName), time.Second)
|
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(influxDB2Store.NewHistogram(influxDBEntryPointReqDurationName), time.Second)
|
||||||
registry.entryPointOpenConnsGauge = influxDB2Store.NewGauge(influxDBEntryPointOpenConnsName)
|
registry.entryPointOpenConnsGauge = influxDB2Store.NewGauge(influxDBEntryPointOpenConnsName)
|
||||||
|
registry.entryPointReqsBytesCounter = influxDB2Store.NewCounter(influxDBEntryPointReqsBytesName)
|
||||||
|
registry.entryPointRespsBytesCounter = influxDB2Store.NewCounter(influxDBEntryPointRespsBytesName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddRoutersLabels {
|
if config.AddRoutersLabels {
|
||||||
|
@ -73,6 +75,8 @@ func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry {
|
||||||
registry.routerReqsTLSCounter = influxDB2Store.NewCounter(influxDBRouterReqsTLSName)
|
registry.routerReqsTLSCounter = influxDB2Store.NewCounter(influxDBRouterReqsTLSName)
|
||||||
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(influxDB2Store.NewHistogram(influxDBRouterReqsDurationName), time.Second)
|
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(influxDB2Store.NewHistogram(influxDBRouterReqsDurationName), time.Second)
|
||||||
registry.routerOpenConnsGauge = influxDB2Store.NewGauge(influxDBORouterOpenConnsName)
|
registry.routerOpenConnsGauge = influxDB2Store.NewGauge(influxDBORouterOpenConnsName)
|
||||||
|
registry.routerReqsBytesCounter = influxDB2Store.NewCounter(influxDBRouterReqsBytesName)
|
||||||
|
registry.routerRespsBytesCounter = influxDB2Store.NewCounter(influxDBRouterRespsBytesName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddServicesLabels {
|
if config.AddServicesLabels {
|
||||||
|
@ -83,6 +87,8 @@ func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry {
|
||||||
registry.serviceRetriesCounter = influxDB2Store.NewCounter(influxDBServiceRetriesTotalName)
|
registry.serviceRetriesCounter = influxDB2Store.NewCounter(influxDBServiceRetriesTotalName)
|
||||||
registry.serviceOpenConnsGauge = influxDB2Store.NewGauge(influxDBServiceOpenConnsName)
|
registry.serviceOpenConnsGauge = influxDB2Store.NewGauge(influxDBServiceOpenConnsName)
|
||||||
registry.serviceServerUpGauge = influxDB2Store.NewGauge(influxDBServiceServerUpName)
|
registry.serviceServerUpGauge = influxDB2Store.NewGauge(influxDBServiceServerUpName)
|
||||||
|
registry.serviceReqsBytesCounter = influxDB2Store.NewCounter(influxDBServiceReqsBytesName)
|
||||||
|
registry.serviceRespsBytesCounter = influxDB2Store.NewCounter(influxDBServiceRespsBytesName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return registry
|
return registry
|
||||||
|
|
|
@ -73,12 +73,16 @@ func TestInfluxDB2(t *testing.T) {
|
||||||
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
||||||
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
||||||
`(traefik\.entrypoint\.connections\.open,entrypoint=test value=1) [\d]{19}`,
|
`(traefik\.entrypoint\.connections\.open,entrypoint=test value=1) [\d]{19}`,
|
||||||
|
`(traefik\.entrypoint\.requests\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`,
|
||||||
|
`(traefik\.entrypoint\.responses\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
influxDB2Registry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
influxDB2Registry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
influxDB2Registry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
influxDB2Registry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
influxDB2Registry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
influxDB2Registry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
||||||
influxDB2Registry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
influxDB2Registry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
||||||
|
influxDB2Registry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDB2Registry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
msgEntrypoint := <-c
|
msgEntrypoint := <-c
|
||||||
|
|
||||||
assertMessage(t, *msgEntrypoint, expectedEntrypoint)
|
assertMessage(t, *msgEntrypoint, expectedEntrypoint)
|
||||||
|
@ -89,6 +93,8 @@ func TestInfluxDB2(t *testing.T) {
|
||||||
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
||||||
`(traefik\.router\.request\.duration,code=200,router=demo,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
`(traefik\.router\.request\.duration,code=200,router=demo,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
||||||
`(traefik\.router\.connections\.open,router=demo,service=test value=1) [\d]{19}`,
|
`(traefik\.router\.connections\.open,router=demo,service=test value=1) [\d]{19}`,
|
||||||
|
`(traefik\.router\.requests\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`,
|
||||||
|
`(traefik\.router\.responses\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
influxDB2Registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
influxDB2Registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
||||||
|
@ -96,6 +102,8 @@ func TestInfluxDB2(t *testing.T) {
|
||||||
influxDB2Registry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
influxDB2Registry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
influxDB2Registry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
influxDB2Registry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
||||||
influxDB2Registry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
influxDB2Registry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
||||||
|
influxDB2Registry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDB2Registry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
msgRouter := <-c
|
msgRouter := <-c
|
||||||
|
|
||||||
assertMessage(t, *msgRouter, expectedRouter)
|
assertMessage(t, *msgRouter, expectedRouter)
|
||||||
|
@ -106,6 +114,8 @@ func TestInfluxDB2(t *testing.T) {
|
||||||
`(traefik\.service\.requests\.tls\.total,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
`(traefik\.service\.requests\.tls\.total,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
||||||
`(traefik\.service\.request\.duration,code=200,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
`(traefik\.service\.request\.duration,code=200,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
||||||
`(traefik\.service\.server\.up,service=test,url=http://127.0.0.1 value=1) [\d]{19}`,
|
`(traefik\.service\.server\.up,service=test,url=http://127.0.0.1 value=1) [\d]{19}`,
|
||||||
|
`(traefik\.service\.requests\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`,
|
||||||
|
`(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
influxDB2Registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
influxDB2Registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
@ -113,6 +123,8 @@ func TestInfluxDB2(t *testing.T) {
|
||||||
influxDB2Registry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
influxDB2Registry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
influxDB2Registry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
influxDB2Registry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
||||||
influxDB2Registry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
|
influxDB2Registry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
|
||||||
|
influxDB2Registry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDB2Registry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
msgService := <-c
|
msgService := <-c
|
||||||
|
|
||||||
assertMessage(t, *msgService, expectedService)
|
assertMessage(t, *msgService, expectedService)
|
||||||
|
|
|
@ -69,6 +69,8 @@ func TestInfluxDB(t *testing.T) {
|
||||||
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
||||||
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
||||||
`(traefik\.entrypoint\.connections\.open,entrypoint=test,tag1=val1 value=1) [\d]{19}`,
|
`(traefik\.entrypoint\.connections\.open,entrypoint=test,tag1=val1 value=1) [\d]{19}`,
|
||||||
|
`(traefik\.entrypoint\.requests\.bytes\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`,
|
||||||
|
`(traefik\.entrypoint\.responses\.bytes\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
msgEntrypoint := udp.ReceiveString(t, func() {
|
msgEntrypoint := udp.ReceiveString(t, func() {
|
||||||
|
@ -76,6 +78,8 @@ func TestInfluxDB(t *testing.T) {
|
||||||
influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
||||||
influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
||||||
|
influxDBRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDBRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
assertMessage(t, msgEntrypoint, expectedEntrypoint)
|
assertMessage(t, msgEntrypoint, expectedEntrypoint)
|
||||||
|
@ -86,6 +90,8 @@ func TestInfluxDB(t *testing.T) {
|
||||||
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
||||||
`(traefik\.router\.request\.duration,code=200,router=demo,service=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
`(traefik\.router\.request\.duration,code=200,router=demo,service=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
||||||
`(traefik\.router\.connections\.open,router=demo,service=test,tag1=val1 value=1) [\d]{19}`,
|
`(traefik\.router\.connections\.open,router=demo,service=test,tag1=val1 value=1) [\d]{19}`,
|
||||||
|
`(traefik\.router\.requests\.bytes\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`,
|
||||||
|
`(traefik\.router\.responses\.bytes\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
msgRouter := udp.ReceiveString(t, func() {
|
msgRouter := udp.ReceiveString(t, func() {
|
||||||
|
@ -94,6 +100,8 @@ func TestInfluxDB(t *testing.T) {
|
||||||
influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
||||||
influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
||||||
|
influxDBRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDBRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
assertMessage(t, msgRouter, expectedRouter)
|
assertMessage(t, msgRouter, expectedRouter)
|
||||||
|
@ -106,6 +114,8 @@ func TestInfluxDB(t *testing.T) {
|
||||||
`(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test,tag1=val1 count=2) [\d]{19}`,
|
`(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test,tag1=val1 count=2) [\d]{19}`,
|
||||||
`(traefik\.service\.server\.up,service=test,tag1=val1,url=http://127.0.0.1 value=1) [\d]{19}`,
|
`(traefik\.service\.server\.up,service=test,tag1=val1,url=http://127.0.0.1 value=1) [\d]{19}`,
|
||||||
`(traefik\.service\.connections\.open,service=test,tag1=val1 value=1) [\d]{19}`,
|
`(traefik\.service\.connections\.open,service=test,tag1=val1 value=1) [\d]{19}`,
|
||||||
|
`(traefik\.service\.requests\.bytes\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`,
|
||||||
|
`(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
msgService := udp.ReceiveString(t, func() {
|
msgService := udp.ReceiveString(t, func() {
|
||||||
|
@ -117,6 +127,8 @@ func TestInfluxDB(t *testing.T) {
|
||||||
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
|
influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
|
||||||
|
influxDBRegistry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDBRegistry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
assertMessage(t, msgService, expectedService)
|
assertMessage(t, msgService, expectedService)
|
||||||
|
@ -181,12 +193,16 @@ func TestInfluxDBHTTP(t *testing.T) {
|
||||||
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
||||||
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
||||||
`(traefik\.entrypoint\.connections\.open,entrypoint=test value=1) [\d]{19}`,
|
`(traefik\.entrypoint\.connections\.open,entrypoint=test value=1) [\d]{19}`,
|
||||||
|
`(traefik\.entrypoint\.requests\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`,
|
||||||
|
`(traefik\.entrypoint\.responses\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
influxDBRegistry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
influxDBRegistry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
||||||
influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
||||||
|
influxDBRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDBRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
msgEntrypoint := <-c
|
msgEntrypoint := <-c
|
||||||
|
|
||||||
assertMessage(t, *msgEntrypoint, expectedEntrypoint)
|
assertMessage(t, *msgEntrypoint, expectedEntrypoint)
|
||||||
|
@ -197,6 +213,8 @@ func TestInfluxDBHTTP(t *testing.T) {
|
||||||
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
|
||||||
`(traefik\.router\.request\.duration,code=200,router=demo,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
`(traefik\.router\.request\.duration,code=200,router=demo,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
|
||||||
`(traefik\.router\.connections\.open,router=demo,service=test value=1) [\d]{19}`,
|
`(traefik\.router\.connections\.open,router=demo,service=test value=1) [\d]{19}`,
|
||||||
|
`(traefik\.router\.requests\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`,
|
||||||
|
`(traefik\.router\.responses\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
||||||
|
@ -204,6 +222,8 @@ func TestInfluxDBHTTP(t *testing.T) {
|
||||||
influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
||||||
influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
||||||
|
influxDBRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDBRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
msgRouter := <-c
|
msgRouter := <-c
|
||||||
|
|
||||||
assertMessage(t, *msgRouter, expectedRouter)
|
assertMessage(t, *msgRouter, expectedRouter)
|
||||||
|
@ -216,6 +236,8 @@ func TestInfluxDBHTTP(t *testing.T) {
|
||||||
`(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test count=2) [\d]{19}`,
|
`(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test count=2) [\d]{19}`,
|
||||||
`(traefik\.service\.server\.up,service=test,url=http://127.0.0.1 value=1) [\d]{19}`,
|
`(traefik\.service\.server\.up,service=test,url=http://127.0.0.1 value=1) [\d]{19}`,
|
||||||
`(traefik\.service\.connections\.open,service=test value=1) [\d]{19}`,
|
`(traefik\.service\.connections\.open,service=test value=1) [\d]{19}`,
|
||||||
|
`(traefik\.service\.requests\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`,
|
||||||
|
`(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
@ -226,6 +248,8 @@ func TestInfluxDBHTTP(t *testing.T) {
|
||||||
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
|
influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
|
||||||
|
influxDBRegistry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
influxDBRegistry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
msgService := <-c
|
msgService := <-c
|
||||||
|
|
||||||
assertMessage(t, *msgService, expectedService)
|
assertMessage(t, *msgService, expectedService)
|
||||||
|
|
|
@ -36,6 +36,8 @@ type Registry interface {
|
||||||
EntryPointReqsTLSCounter() metrics.Counter
|
EntryPointReqsTLSCounter() metrics.Counter
|
||||||
EntryPointReqDurationHistogram() ScalableHistogram
|
EntryPointReqDurationHistogram() ScalableHistogram
|
||||||
EntryPointOpenConnsGauge() metrics.Gauge
|
EntryPointOpenConnsGauge() metrics.Gauge
|
||||||
|
EntryPointReqsBytesCounter() metrics.Counter
|
||||||
|
EntryPointRespsBytesCounter() metrics.Counter
|
||||||
|
|
||||||
// router metrics
|
// router metrics
|
||||||
|
|
||||||
|
@ -43,6 +45,8 @@ type Registry interface {
|
||||||
RouterReqsTLSCounter() metrics.Counter
|
RouterReqsTLSCounter() metrics.Counter
|
||||||
RouterReqDurationHistogram() ScalableHistogram
|
RouterReqDurationHistogram() ScalableHistogram
|
||||||
RouterOpenConnsGauge() metrics.Gauge
|
RouterOpenConnsGauge() metrics.Gauge
|
||||||
|
RouterReqsBytesCounter() metrics.Counter
|
||||||
|
RouterRespsBytesCounter() metrics.Counter
|
||||||
|
|
||||||
// service metrics
|
// service metrics
|
||||||
|
|
||||||
|
@ -52,6 +56,8 @@ type Registry interface {
|
||||||
ServiceOpenConnsGauge() metrics.Gauge
|
ServiceOpenConnsGauge() metrics.Gauge
|
||||||
ServiceRetriesCounter() metrics.Counter
|
ServiceRetriesCounter() metrics.Counter
|
||||||
ServiceServerUpGauge() metrics.Gauge
|
ServiceServerUpGauge() metrics.Gauge
|
||||||
|
ServiceReqsBytesCounter() metrics.Counter
|
||||||
|
ServiceRespsBytesCounter() metrics.Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVoidRegistry is a noop implementation of metrics.Registry.
|
// NewVoidRegistry is a noop implementation of metrics.Registry.
|
||||||
|
@ -62,7 +68,7 @@ func NewVoidRegistry() Registry {
|
||||||
|
|
||||||
// NewMultiRegistry is an implementation of metrics.Registry that wraps multiple registries.
|
// NewMultiRegistry is an implementation of metrics.Registry that wraps multiple registries.
|
||||||
// It handles the case when a registry hasn't registered some metric and returns nil.
|
// It handles the case when a registry hasn't registered some metric and returns nil.
|
||||||
// This allows for feature imparity between the different metric implementations.
|
// This allows for feature disparity between the different metric implementations.
|
||||||
func NewMultiRegistry(registries []Registry) Registry {
|
func NewMultiRegistry(registries []Registry) Registry {
|
||||||
var configReloadsCounter []metrics.Counter
|
var configReloadsCounter []metrics.Counter
|
||||||
var configReloadsFailureCounter []metrics.Counter
|
var configReloadsFailureCounter []metrics.Counter
|
||||||
|
@ -73,16 +79,22 @@ func NewMultiRegistry(registries []Registry) Registry {
|
||||||
var entryPointReqsTLSCounter []metrics.Counter
|
var entryPointReqsTLSCounter []metrics.Counter
|
||||||
var entryPointReqDurationHistogram []ScalableHistogram
|
var entryPointReqDurationHistogram []ScalableHistogram
|
||||||
var entryPointOpenConnsGauge []metrics.Gauge
|
var entryPointOpenConnsGauge []metrics.Gauge
|
||||||
|
var entryPointReqsBytesCounter []metrics.Counter
|
||||||
|
var entryPointRespsBytesCounter []metrics.Counter
|
||||||
var routerReqsCounter []metrics.Counter
|
var routerReqsCounter []metrics.Counter
|
||||||
var routerReqsTLSCounter []metrics.Counter
|
var routerReqsTLSCounter []metrics.Counter
|
||||||
var routerReqDurationHistogram []ScalableHistogram
|
var routerReqDurationHistogram []ScalableHistogram
|
||||||
var routerOpenConnsGauge []metrics.Gauge
|
var routerOpenConnsGauge []metrics.Gauge
|
||||||
|
var routerReqsBytesCounter []metrics.Counter
|
||||||
|
var routerRespsBytesCounter []metrics.Counter
|
||||||
var serviceReqsCounter []metrics.Counter
|
var serviceReqsCounter []metrics.Counter
|
||||||
var serviceReqsTLSCounter []metrics.Counter
|
var serviceReqsTLSCounter []metrics.Counter
|
||||||
var serviceReqDurationHistogram []ScalableHistogram
|
var serviceReqDurationHistogram []ScalableHistogram
|
||||||
var serviceOpenConnsGauge []metrics.Gauge
|
var serviceOpenConnsGauge []metrics.Gauge
|
||||||
var serviceRetriesCounter []metrics.Counter
|
var serviceRetriesCounter []metrics.Counter
|
||||||
var serviceServerUpGauge []metrics.Gauge
|
var serviceServerUpGauge []metrics.Gauge
|
||||||
|
var serviceReqsBytesCounter []metrics.Counter
|
||||||
|
var serviceRespsBytesCounter []metrics.Counter
|
||||||
|
|
||||||
for _, r := range registries {
|
for _, r := range registries {
|
||||||
if r.ConfigReloadsCounter() != nil {
|
if r.ConfigReloadsCounter() != nil {
|
||||||
|
@ -112,6 +124,12 @@ func NewMultiRegistry(registries []Registry) Registry {
|
||||||
if r.EntryPointOpenConnsGauge() != nil {
|
if r.EntryPointOpenConnsGauge() != nil {
|
||||||
entryPointOpenConnsGauge = append(entryPointOpenConnsGauge, r.EntryPointOpenConnsGauge())
|
entryPointOpenConnsGauge = append(entryPointOpenConnsGauge, r.EntryPointOpenConnsGauge())
|
||||||
}
|
}
|
||||||
|
if r.EntryPointReqsBytesCounter() != nil {
|
||||||
|
entryPointReqsBytesCounter = append(entryPointReqsBytesCounter, r.EntryPointReqsBytesCounter())
|
||||||
|
}
|
||||||
|
if r.EntryPointRespsBytesCounter() != nil {
|
||||||
|
entryPointRespsBytesCounter = append(entryPointRespsBytesCounter, r.EntryPointRespsBytesCounter())
|
||||||
|
}
|
||||||
if r.RouterReqsCounter() != nil {
|
if r.RouterReqsCounter() != nil {
|
||||||
routerReqsCounter = append(routerReqsCounter, r.RouterReqsCounter())
|
routerReqsCounter = append(routerReqsCounter, r.RouterReqsCounter())
|
||||||
}
|
}
|
||||||
|
@ -124,6 +142,12 @@ func NewMultiRegistry(registries []Registry) Registry {
|
||||||
if r.RouterOpenConnsGauge() != nil {
|
if r.RouterOpenConnsGauge() != nil {
|
||||||
routerOpenConnsGauge = append(routerOpenConnsGauge, r.RouterOpenConnsGauge())
|
routerOpenConnsGauge = append(routerOpenConnsGauge, r.RouterOpenConnsGauge())
|
||||||
}
|
}
|
||||||
|
if r.RouterReqsBytesCounter() != nil {
|
||||||
|
routerReqsBytesCounter = append(routerReqsBytesCounter, r.RouterReqsBytesCounter())
|
||||||
|
}
|
||||||
|
if r.RouterRespsBytesCounter() != nil {
|
||||||
|
routerRespsBytesCounter = append(routerRespsBytesCounter, r.RouterRespsBytesCounter())
|
||||||
|
}
|
||||||
if r.ServiceReqsCounter() != nil {
|
if r.ServiceReqsCounter() != nil {
|
||||||
serviceReqsCounter = append(serviceReqsCounter, r.ServiceReqsCounter())
|
serviceReqsCounter = append(serviceReqsCounter, r.ServiceReqsCounter())
|
||||||
}
|
}
|
||||||
|
@ -142,6 +166,12 @@ func NewMultiRegistry(registries []Registry) Registry {
|
||||||
if r.ServiceServerUpGauge() != nil {
|
if r.ServiceServerUpGauge() != nil {
|
||||||
serviceServerUpGauge = append(serviceServerUpGauge, r.ServiceServerUpGauge())
|
serviceServerUpGauge = append(serviceServerUpGauge, r.ServiceServerUpGauge())
|
||||||
}
|
}
|
||||||
|
if r.ServiceReqsBytesCounter() != nil {
|
||||||
|
serviceReqsBytesCounter = append(serviceReqsBytesCounter, r.ServiceReqsBytesCounter())
|
||||||
|
}
|
||||||
|
if r.ServiceRespsBytesCounter() != nil {
|
||||||
|
serviceRespsBytesCounter = append(serviceRespsBytesCounter, r.ServiceRespsBytesCounter())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &standardRegistry{
|
return &standardRegistry{
|
||||||
|
@ -155,18 +185,24 @@ func NewMultiRegistry(registries []Registry) Registry {
|
||||||
tlsCertsNotAfterTimestampGauge: multi.NewGauge(tlsCertsNotAfterTimestampGauge...),
|
tlsCertsNotAfterTimestampGauge: multi.NewGauge(tlsCertsNotAfterTimestampGauge...),
|
||||||
entryPointReqsCounter: multi.NewCounter(entryPointReqsCounter...),
|
entryPointReqsCounter: multi.NewCounter(entryPointReqsCounter...),
|
||||||
entryPointReqsTLSCounter: multi.NewCounter(entryPointReqsTLSCounter...),
|
entryPointReqsTLSCounter: multi.NewCounter(entryPointReqsTLSCounter...),
|
||||||
entryPointReqDurationHistogram: NewMultiHistogram(entryPointReqDurationHistogram...),
|
entryPointReqDurationHistogram: MultiHistogram(entryPointReqDurationHistogram),
|
||||||
entryPointOpenConnsGauge: multi.NewGauge(entryPointOpenConnsGauge...),
|
entryPointOpenConnsGauge: multi.NewGauge(entryPointOpenConnsGauge...),
|
||||||
|
entryPointReqsBytesCounter: multi.NewCounter(entryPointReqsBytesCounter...),
|
||||||
|
entryPointRespsBytesCounter: multi.NewCounter(entryPointRespsBytesCounter...),
|
||||||
routerReqsCounter: multi.NewCounter(routerReqsCounter...),
|
routerReqsCounter: multi.NewCounter(routerReqsCounter...),
|
||||||
routerReqsTLSCounter: multi.NewCounter(routerReqsTLSCounter...),
|
routerReqsTLSCounter: multi.NewCounter(routerReqsTLSCounter...),
|
||||||
routerReqDurationHistogram: NewMultiHistogram(routerReqDurationHistogram...),
|
routerReqDurationHistogram: MultiHistogram(routerReqDurationHistogram),
|
||||||
routerOpenConnsGauge: multi.NewGauge(routerOpenConnsGauge...),
|
routerOpenConnsGauge: multi.NewGauge(routerOpenConnsGauge...),
|
||||||
|
routerReqsBytesCounter: multi.NewCounter(routerReqsBytesCounter...),
|
||||||
|
routerRespsBytesCounter: multi.NewCounter(routerRespsBytesCounter...),
|
||||||
serviceReqsCounter: multi.NewCounter(serviceReqsCounter...),
|
serviceReqsCounter: multi.NewCounter(serviceReqsCounter...),
|
||||||
serviceReqsTLSCounter: multi.NewCounter(serviceReqsTLSCounter...),
|
serviceReqsTLSCounter: multi.NewCounter(serviceReqsTLSCounter...),
|
||||||
serviceReqDurationHistogram: NewMultiHistogram(serviceReqDurationHistogram...),
|
serviceReqDurationHistogram: MultiHistogram(serviceReqDurationHistogram),
|
||||||
serviceOpenConnsGauge: multi.NewGauge(serviceOpenConnsGauge...),
|
serviceOpenConnsGauge: multi.NewGauge(serviceOpenConnsGauge...),
|
||||||
serviceRetriesCounter: multi.NewCounter(serviceRetriesCounter...),
|
serviceRetriesCounter: multi.NewCounter(serviceRetriesCounter...),
|
||||||
serviceServerUpGauge: multi.NewGauge(serviceServerUpGauge...),
|
serviceServerUpGauge: multi.NewGauge(serviceServerUpGauge...),
|
||||||
|
serviceReqsBytesCounter: multi.NewCounter(serviceReqsBytesCounter...),
|
||||||
|
serviceRespsBytesCounter: multi.NewCounter(serviceRespsBytesCounter...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,16 +219,22 @@ type standardRegistry struct {
|
||||||
entryPointReqsTLSCounter metrics.Counter
|
entryPointReqsTLSCounter metrics.Counter
|
||||||
entryPointReqDurationHistogram ScalableHistogram
|
entryPointReqDurationHistogram ScalableHistogram
|
||||||
entryPointOpenConnsGauge metrics.Gauge
|
entryPointOpenConnsGauge metrics.Gauge
|
||||||
|
entryPointReqsBytesCounter metrics.Counter
|
||||||
|
entryPointRespsBytesCounter metrics.Counter
|
||||||
routerReqsCounter metrics.Counter
|
routerReqsCounter metrics.Counter
|
||||||
routerReqsTLSCounter metrics.Counter
|
routerReqsTLSCounter metrics.Counter
|
||||||
routerReqDurationHistogram ScalableHistogram
|
routerReqDurationHistogram ScalableHistogram
|
||||||
routerOpenConnsGauge metrics.Gauge
|
routerOpenConnsGauge metrics.Gauge
|
||||||
|
routerReqsBytesCounter metrics.Counter
|
||||||
|
routerRespsBytesCounter metrics.Counter
|
||||||
serviceReqsCounter metrics.Counter
|
serviceReqsCounter metrics.Counter
|
||||||
serviceReqsTLSCounter metrics.Counter
|
serviceReqsTLSCounter metrics.Counter
|
||||||
serviceReqDurationHistogram ScalableHistogram
|
serviceReqDurationHistogram ScalableHistogram
|
||||||
serviceOpenConnsGauge metrics.Gauge
|
serviceOpenConnsGauge metrics.Gauge
|
||||||
serviceRetriesCounter metrics.Counter
|
serviceRetriesCounter metrics.Counter
|
||||||
serviceServerUpGauge metrics.Gauge
|
serviceServerUpGauge metrics.Gauge
|
||||||
|
serviceReqsBytesCounter metrics.Counter
|
||||||
|
serviceRespsBytesCounter metrics.Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *standardRegistry) IsEpEnabled() bool {
|
func (r *standardRegistry) IsEpEnabled() bool {
|
||||||
|
@ -243,6 +285,14 @@ func (r *standardRegistry) EntryPointOpenConnsGauge() metrics.Gauge {
|
||||||
return r.entryPointOpenConnsGauge
|
return r.entryPointOpenConnsGauge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *standardRegistry) EntryPointReqsBytesCounter() metrics.Counter {
|
||||||
|
return r.entryPointReqsBytesCounter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *standardRegistry) EntryPointRespsBytesCounter() metrics.Counter {
|
||||||
|
return r.entryPointRespsBytesCounter
|
||||||
|
}
|
||||||
|
|
||||||
func (r *standardRegistry) RouterReqsCounter() metrics.Counter {
|
func (r *standardRegistry) RouterReqsCounter() metrics.Counter {
|
||||||
return r.routerReqsCounter
|
return r.routerReqsCounter
|
||||||
}
|
}
|
||||||
|
@ -259,6 +309,14 @@ func (r *standardRegistry) RouterOpenConnsGauge() metrics.Gauge {
|
||||||
return r.routerOpenConnsGauge
|
return r.routerOpenConnsGauge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *standardRegistry) RouterReqsBytesCounter() metrics.Counter {
|
||||||
|
return r.routerReqsBytesCounter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *standardRegistry) RouterRespsBytesCounter() metrics.Counter {
|
||||||
|
return r.routerRespsBytesCounter
|
||||||
|
}
|
||||||
|
|
||||||
func (r *standardRegistry) ServiceReqsCounter() metrics.Counter {
|
func (r *standardRegistry) ServiceReqsCounter() metrics.Counter {
|
||||||
return r.serviceReqsCounter
|
return r.serviceReqsCounter
|
||||||
}
|
}
|
||||||
|
@ -283,6 +341,14 @@ func (r *standardRegistry) ServiceServerUpGauge() metrics.Gauge {
|
||||||
return r.serviceServerUpGauge
|
return r.serviceServerUpGauge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *standardRegistry) ServiceReqsBytesCounter() metrics.Counter {
|
||||||
|
return r.serviceReqsBytesCounter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *standardRegistry) ServiceRespsBytesCounter() metrics.Counter {
|
||||||
|
return r.serviceRespsBytesCounter
|
||||||
|
}
|
||||||
|
|
||||||
// ScalableHistogram is a Histogram with a predefined time unit,
|
// ScalableHistogram is a Histogram with a predefined time unit,
|
||||||
// used when producing observations without explicitly setting the observed value.
|
// used when producing observations without explicitly setting the observed value.
|
||||||
type ScalableHistogram interface {
|
type ScalableHistogram interface {
|
||||||
|
@ -335,11 +401,6 @@ func NewHistogramWithScale(histogram metrics.Histogram, unit time.Duration) (Sca
|
||||||
// MultiHistogram collects multiple individual histograms and treats them as a unit.
|
// MultiHistogram collects multiple individual histograms and treats them as a unit.
|
||||||
type MultiHistogram []ScalableHistogram
|
type MultiHistogram []ScalableHistogram
|
||||||
|
|
||||||
// NewMultiHistogram returns a multi-histogram, wrapping the passed histograms.
|
|
||||||
func NewMultiHistogram(h ...ScalableHistogram) MultiHistogram {
|
|
||||||
return MultiHistogram(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObserveFromStart implements ScalableHistogram.
|
// ObserveFromStart implements ScalableHistogram.
|
||||||
func (h MultiHistogram) ObserveFromStart(start time.Time) {
|
func (h MultiHistogram) ObserveFromStart(start time.Time) {
|
||||||
for _, histogram := range h {
|
for _, histogram := range h {
|
||||||
|
|
|
@ -32,27 +32,33 @@ const (
|
||||||
tlsCertsNotAfterTimestamp = metricsTLSPrefix + "certs_not_after"
|
tlsCertsNotAfterTimestamp = metricsTLSPrefix + "certs_not_after"
|
||||||
|
|
||||||
// entry point.
|
// entry point.
|
||||||
metricEntryPointPrefix = MetricNamePrefix + "entrypoint_"
|
metricEntryPointPrefix = MetricNamePrefix + "entrypoint_"
|
||||||
entryPointReqsTotalName = metricEntryPointPrefix + "requests_total"
|
entryPointReqsTotalName = metricEntryPointPrefix + "requests_total"
|
||||||
entryPointReqsTLSTotalName = metricEntryPointPrefix + "requests_tls_total"
|
entryPointReqsTLSTotalName = metricEntryPointPrefix + "requests_tls_total"
|
||||||
entryPointReqDurationName = metricEntryPointPrefix + "request_duration_seconds"
|
entryPointReqDurationName = metricEntryPointPrefix + "request_duration_seconds"
|
||||||
entryPointOpenConnsName = metricEntryPointPrefix + "open_connections"
|
entryPointOpenConnsName = metricEntryPointPrefix + "open_connections"
|
||||||
|
entryPointReqsBytesTotalName = metricEntryPointPrefix + "requests_bytes_total"
|
||||||
|
entryPointRespsBytesTotalName = metricEntryPointPrefix + "responses_bytes_total"
|
||||||
|
|
||||||
// router level.
|
// router level.
|
||||||
metricRouterPrefix = MetricNamePrefix + "router_"
|
metricRouterPrefix = MetricNamePrefix + "router_"
|
||||||
routerReqsTotalName = metricRouterPrefix + "requests_total"
|
routerReqsTotalName = metricRouterPrefix + "requests_total"
|
||||||
routerReqsTLSTotalName = metricRouterPrefix + "requests_tls_total"
|
routerReqsTLSTotalName = metricRouterPrefix + "requests_tls_total"
|
||||||
routerReqDurationName = metricRouterPrefix + "request_duration_seconds"
|
routerReqDurationName = metricRouterPrefix + "request_duration_seconds"
|
||||||
routerOpenConnsName = metricRouterPrefix + "open_connections"
|
routerOpenConnsName = metricRouterPrefix + "open_connections"
|
||||||
|
routerReqsBytesTotalName = metricRouterPrefix + "requests_bytes_total"
|
||||||
|
routerRespsBytesTotalName = metricRouterPrefix + "responses_bytes_total"
|
||||||
|
|
||||||
// service level.
|
// service level.
|
||||||
metricServicePrefix = MetricNamePrefix + "service_"
|
metricServicePrefix = MetricNamePrefix + "service_"
|
||||||
serviceReqsTotalName = metricServicePrefix + "requests_total"
|
serviceReqsTotalName = metricServicePrefix + "requests_total"
|
||||||
serviceReqsTLSTotalName = metricServicePrefix + "requests_tls_total"
|
serviceReqsTLSTotalName = metricServicePrefix + "requests_tls_total"
|
||||||
serviceReqDurationName = metricServicePrefix + "request_duration_seconds"
|
serviceReqDurationName = metricServicePrefix + "request_duration_seconds"
|
||||||
serviceOpenConnsName = metricServicePrefix + "open_connections"
|
serviceOpenConnsName = metricServicePrefix + "open_connections"
|
||||||
serviceRetriesTotalName = metricServicePrefix + "retries_total"
|
serviceRetriesTotalName = metricServicePrefix + "retries_total"
|
||||||
serviceServerUpName = metricServicePrefix + "server_up"
|
serviceServerUpName = metricServicePrefix + "server_up"
|
||||||
|
serviceReqsBytesTotalName = metricServicePrefix + "requests_bytes_total"
|
||||||
|
serviceRespsBytesTotalName = metricServicePrefix + "responses_bytes_total"
|
||||||
)
|
)
|
||||||
|
|
||||||
// promState holds all metric state internally and acts as the only Collector we register for Prometheus.
|
// promState holds all metric state internally and acts as the only Collector we register for Prometheus.
|
||||||
|
@ -166,18 +172,30 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||||
Name: entryPointOpenConnsName,
|
Name: entryPointOpenConnsName,
|
||||||
Help: "How many open connections exist on an entrypoint, partitioned by method and protocol.",
|
Help: "How many open connections exist on an entrypoint, partitioned by method and protocol.",
|
||||||
}, []string{"method", "protocol", "entrypoint"})
|
}, []string{"method", "protocol", "entrypoint"})
|
||||||
|
entryPointReqsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{
|
||||||
|
Name: entryPointReqsBytesTotalName,
|
||||||
|
Help: "The total size of requests in bytes handled by an entrypoint, partitioned by status code, protocol, and method.",
|
||||||
|
}, []string{"code", "method", "protocol", "entrypoint"})
|
||||||
|
entryPointRespsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{
|
||||||
|
Name: entryPointRespsBytesTotalName,
|
||||||
|
Help: "The total size of responses in bytes handled by an entrypoint, partitioned by status code, protocol, and method.",
|
||||||
|
}, []string{"code", "method", "protocol", "entrypoint"})
|
||||||
|
|
||||||
promState.vectors = append(promState.vectors,
|
promState.vectors = append(promState.vectors,
|
||||||
entryPointReqs.cv,
|
entryPointReqs.cv,
|
||||||
entryPointReqsTLS.cv,
|
entryPointReqsTLS.cv,
|
||||||
entryPointReqDurations.hv,
|
entryPointReqDurations.hv,
|
||||||
entryPointOpenConns.gv,
|
entryPointOpenConns.gv,
|
||||||
|
entryPointReqsBytesTotal.cv,
|
||||||
|
entryPointRespsBytesTotal.cv,
|
||||||
)
|
)
|
||||||
|
|
||||||
reg.entryPointReqsCounter = entryPointReqs
|
reg.entryPointReqsCounter = entryPointReqs
|
||||||
reg.entryPointReqsTLSCounter = entryPointReqsTLS
|
reg.entryPointReqsTLSCounter = entryPointReqsTLS
|
||||||
reg.entryPointReqDurationHistogram, _ = NewHistogramWithScale(entryPointReqDurations, time.Second)
|
reg.entryPointReqDurationHistogram, _ = NewHistogramWithScale(entryPointReqDurations, time.Second)
|
||||||
reg.entryPointOpenConnsGauge = entryPointOpenConns
|
reg.entryPointOpenConnsGauge = entryPointOpenConns
|
||||||
|
reg.entryPointReqsBytesCounter = entryPointReqsBytesTotal
|
||||||
|
reg.entryPointRespsBytesCounter = entryPointRespsBytesTotal
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddRoutersLabels {
|
if config.AddRoutersLabels {
|
||||||
|
@ -198,17 +216,29 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||||
Name: routerOpenConnsName,
|
Name: routerOpenConnsName,
|
||||||
Help: "How many open connections exist on a router, partitioned by service, method, and protocol.",
|
Help: "How many open connections exist on a router, partitioned by service, method, and protocol.",
|
||||||
}, []string{"method", "protocol", "router", "service"})
|
}, []string{"method", "protocol", "router", "service"})
|
||||||
|
routerReqsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{
|
||||||
|
Name: routerReqsBytesTotalName,
|
||||||
|
Help: "The total size of requests in bytes handled by a router, partitioned by service, status code, protocol, and method.",
|
||||||
|
}, []string{"code", "method", "protocol", "router", "service"})
|
||||||
|
routerRespsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{
|
||||||
|
Name: routerRespsBytesTotalName,
|
||||||
|
Help: "The total size of responses in bytes handled by a router, partitioned by service, status code, protocol, and method.",
|
||||||
|
}, []string{"code", "method", "protocol", "router", "service"})
|
||||||
|
|
||||||
promState.vectors = append(promState.vectors,
|
promState.vectors = append(promState.vectors,
|
||||||
routerReqs.cv,
|
routerReqs.cv,
|
||||||
routerReqsTLS.cv,
|
routerReqsTLS.cv,
|
||||||
routerReqDurations.hv,
|
routerReqDurations.hv,
|
||||||
routerOpenConns.gv,
|
routerOpenConns.gv,
|
||||||
|
routerReqsBytesTotal.cv,
|
||||||
|
routerRespsBytesTotal.cv,
|
||||||
)
|
)
|
||||||
reg.routerReqsCounter = routerReqs
|
reg.routerReqsCounter = routerReqs
|
||||||
reg.routerReqsTLSCounter = routerReqsTLS
|
reg.routerReqsTLSCounter = routerReqsTLS
|
||||||
reg.routerReqDurationHistogram, _ = NewHistogramWithScale(routerReqDurations, time.Second)
|
reg.routerReqDurationHistogram, _ = NewHistogramWithScale(routerReqDurations, time.Second)
|
||||||
reg.routerOpenConnsGauge = routerOpenConns
|
reg.routerOpenConnsGauge = routerOpenConns
|
||||||
|
reg.routerReqsBytesCounter = routerReqsBytesTotal
|
||||||
|
reg.routerRespsBytesCounter = routerRespsBytesTotal
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddServicesLabels {
|
if config.AddServicesLabels {
|
||||||
|
@ -237,6 +267,14 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||||
Name: serviceServerUpName,
|
Name: serviceServerUpName,
|
||||||
Help: "service server is up, described by gauge value of 0 or 1.",
|
Help: "service server is up, described by gauge value of 0 or 1.",
|
||||||
}, []string{"service", "url"})
|
}, []string{"service", "url"})
|
||||||
|
serviceReqsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{
|
||||||
|
Name: serviceReqsBytesTotalName,
|
||||||
|
Help: "The total size of requests in bytes received by a service, partitioned by status code, protocol, and method.",
|
||||||
|
}, []string{"code", "method", "protocol", "service"})
|
||||||
|
serviceRespsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{
|
||||||
|
Name: serviceRespsBytesTotalName,
|
||||||
|
Help: "The total size of responses in bytes returned by a service, partitioned by status code, protocol, and method.",
|
||||||
|
}, []string{"code", "method", "protocol", "service"})
|
||||||
|
|
||||||
promState.vectors = append(promState.vectors,
|
promState.vectors = append(promState.vectors,
|
||||||
serviceReqs.cv,
|
serviceReqs.cv,
|
||||||
|
@ -245,6 +283,8 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||||
serviceOpenConns.gv,
|
serviceOpenConns.gv,
|
||||||
serviceRetries.cv,
|
serviceRetries.cv,
|
||||||
serviceServerUp.gv,
|
serviceServerUp.gv,
|
||||||
|
serviceReqsBytesTotal.cv,
|
||||||
|
serviceRespsBytesTotal.cv,
|
||||||
)
|
)
|
||||||
|
|
||||||
reg.serviceReqsCounter = serviceReqs
|
reg.serviceReqsCounter = serviceReqs
|
||||||
|
@ -253,6 +293,8 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||||
reg.serviceOpenConnsGauge = serviceOpenConns
|
reg.serviceOpenConnsGauge = serviceOpenConns
|
||||||
reg.serviceRetriesCounter = serviceRetries
|
reg.serviceRetriesCounter = serviceRetries
|
||||||
reg.serviceServerUpGauge = serviceServerUp
|
reg.serviceServerUpGauge = serviceServerUp
|
||||||
|
reg.serviceReqsBytesCounter = serviceReqsBytesTotal
|
||||||
|
reg.serviceRespsBytesCounter = serviceRespsBytesTotal
|
||||||
}
|
}
|
||||||
|
|
||||||
return reg
|
return reg
|
||||||
|
|
|
@ -121,6 +121,14 @@ func TestPrometheus(t *testing.T) {
|
||||||
EntryPointOpenConnsGauge().
|
EntryPointOpenConnsGauge().
|
||||||
With("method", http.MethodGet, "protocol", "http", "entrypoint", "http").
|
With("method", http.MethodGet, "protocol", "http", "entrypoint", "http").
|
||||||
Set(1)
|
Set(1)
|
||||||
|
prometheusRegistry.
|
||||||
|
EntryPointRespsBytesCounter().
|
||||||
|
With("code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http", "entrypoint", "http").
|
||||||
|
Add(1)
|
||||||
|
prometheusRegistry.
|
||||||
|
EntryPointReqsBytesCounter().
|
||||||
|
With("code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http", "entrypoint", "http").
|
||||||
|
Add(1)
|
||||||
|
|
||||||
prometheusRegistry.
|
prometheusRegistry.
|
||||||
RouterReqsCounter().
|
RouterReqsCounter().
|
||||||
|
@ -138,6 +146,14 @@ func TestPrometheus(t *testing.T) {
|
||||||
RouterOpenConnsGauge().
|
RouterOpenConnsGauge().
|
||||||
With("router", "demo", "service", "service1", "method", http.MethodGet, "protocol", "http").
|
With("router", "demo", "service", "service1", "method", http.MethodGet, "protocol", "http").
|
||||||
Set(1)
|
Set(1)
|
||||||
|
prometheusRegistry.
|
||||||
|
RouterRespsBytesCounter().
|
||||||
|
With("router", "demo", "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||||
|
Add(1)
|
||||||
|
prometheusRegistry.
|
||||||
|
RouterReqsBytesCounter().
|
||||||
|
With("router", "demo", "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||||
|
Add(1)
|
||||||
|
|
||||||
prometheusRegistry.
|
prometheusRegistry.
|
||||||
ServiceReqsCounter().
|
ServiceReqsCounter().
|
||||||
|
@ -163,6 +179,14 @@ func TestPrometheus(t *testing.T) {
|
||||||
ServiceServerUpGauge().
|
ServiceServerUpGauge().
|
||||||
With("service", "service1", "url", "http://127.0.0.10:80").
|
With("service", "service1", "url", "http://127.0.0.10:80").
|
||||||
Set(1)
|
Set(1)
|
||||||
|
prometheusRegistry.
|
||||||
|
ServiceRespsBytesCounter().
|
||||||
|
With("service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||||
|
Add(1)
|
||||||
|
prometheusRegistry.
|
||||||
|
ServiceReqsBytesCounter().
|
||||||
|
With("service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||||
|
Add(1)
|
||||||
|
|
||||||
delayForTrackingCompletion()
|
delayForTrackingCompletion()
|
||||||
|
|
||||||
|
@ -227,6 +251,26 @@ func TestPrometheus(t *testing.T) {
|
||||||
},
|
},
|
||||||
assert: buildGaugeAssert(t, entryPointOpenConnsName, 1),
|
assert: buildGaugeAssert(t, entryPointOpenConnsName, 1),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: entryPointReqsBytesTotalName,
|
||||||
|
labels: map[string]string{
|
||||||
|
"code": "200",
|
||||||
|
"method": http.MethodGet,
|
||||||
|
"protocol": "http",
|
||||||
|
"entrypoint": "http",
|
||||||
|
},
|
||||||
|
assert: buildCounterAssert(t, entryPointReqsBytesTotalName, 1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: entryPointRespsBytesTotalName,
|
||||||
|
labels: map[string]string{
|
||||||
|
"code": "200",
|
||||||
|
"method": http.MethodGet,
|
||||||
|
"protocol": "http",
|
||||||
|
"entrypoint": "http",
|
||||||
|
},
|
||||||
|
assert: buildCounterAssert(t, entryPointRespsBytesTotalName, 1),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: routerReqsTotalName,
|
name: routerReqsTotalName,
|
||||||
labels: map[string]string{
|
labels: map[string]string{
|
||||||
|
@ -269,6 +313,28 @@ func TestPrometheus(t *testing.T) {
|
||||||
},
|
},
|
||||||
assert: buildGaugeAssert(t, routerOpenConnsName, 1),
|
assert: buildGaugeAssert(t, routerOpenConnsName, 1),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: routerReqsBytesTotalName,
|
||||||
|
labels: map[string]string{
|
||||||
|
"code": "200",
|
||||||
|
"method": http.MethodGet,
|
||||||
|
"protocol": "http",
|
||||||
|
"service": "service1",
|
||||||
|
"router": "demo",
|
||||||
|
},
|
||||||
|
assert: buildCounterAssert(t, routerReqsBytesTotalName, 1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: routerRespsBytesTotalName,
|
||||||
|
labels: map[string]string{
|
||||||
|
"code": "200",
|
||||||
|
"method": http.MethodGet,
|
||||||
|
"protocol": "http",
|
||||||
|
"service": "service1",
|
||||||
|
"router": "demo",
|
||||||
|
},
|
||||||
|
assert: buildCounterAssert(t, routerRespsBytesTotalName, 1),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: serviceReqsTotalName,
|
name: serviceReqsTotalName,
|
||||||
labels: map[string]string{
|
labels: map[string]string{
|
||||||
|
@ -322,6 +388,26 @@ func TestPrometheus(t *testing.T) {
|
||||||
},
|
},
|
||||||
assert: buildGaugeAssert(t, serviceServerUpName, 1),
|
assert: buildGaugeAssert(t, serviceServerUpName, 1),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: serviceReqsBytesTotalName,
|
||||||
|
labels: map[string]string{
|
||||||
|
"code": "200",
|
||||||
|
"method": http.MethodGet,
|
||||||
|
"protocol": "http",
|
||||||
|
"service": "service1",
|
||||||
|
},
|
||||||
|
assert: buildCounterAssert(t, serviceReqsBytesTotalName, 1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: serviceRespsBytesTotalName,
|
||||||
|
labels: map[string]string{
|
||||||
|
"code": "200",
|
||||||
|
"method": http.MethodGet,
|
||||||
|
"protocol": "http",
|
||||||
|
"service": "service1",
|
||||||
|
},
|
||||||
|
assert: buildCounterAssert(t, serviceRespsBytesTotalName, 1),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
|
|
@ -28,11 +28,15 @@ const (
|
||||||
statsdEntryPointReqsTLSName = "entrypoint.request.tls.total"
|
statsdEntryPointReqsTLSName = "entrypoint.request.tls.total"
|
||||||
statsdEntryPointReqDurationName = "entrypoint.request.duration"
|
statsdEntryPointReqDurationName = "entrypoint.request.duration"
|
||||||
statsdEntryPointOpenConnsName = "entrypoint.connections.open"
|
statsdEntryPointOpenConnsName = "entrypoint.connections.open"
|
||||||
|
statsdEntryPointReqsBytesName = "entrypoint.requests.bytes.total"
|
||||||
|
statsdEntryPointRespsBytesName = "entrypoint.responses.bytes.total"
|
||||||
|
|
||||||
statsdRouterReqsName = "router.request.total"
|
statsdRouterReqsName = "router.request.total"
|
||||||
statsdRouterReqsTLSName = "router.request.tls.total"
|
statsdRouterReqsTLSName = "router.request.tls.total"
|
||||||
statsdRouterReqsDurationName = "router.request.duration"
|
statsdRouterReqsDurationName = "router.request.duration"
|
||||||
statsdRouterOpenConnsName = "router.connections.open"
|
statsdRouterOpenConnsName = "router.connections.open"
|
||||||
|
statsdRouterReqsBytesName = "router.requests.bytes.total"
|
||||||
|
statsdRouterRespsBytesName = "router.responses.bytes.total"
|
||||||
|
|
||||||
statsdServiceReqsName = "service.request.total"
|
statsdServiceReqsName = "service.request.total"
|
||||||
statsdServiceReqsTLSName = "service.request.tls.total"
|
statsdServiceReqsTLSName = "service.request.tls.total"
|
||||||
|
@ -40,6 +44,8 @@ const (
|
||||||
statsdServiceRetriesTotalName = "service.retries.total"
|
statsdServiceRetriesTotalName = "service.retries.total"
|
||||||
statsdServiceServerUpName = "service.server.up"
|
statsdServiceServerUpName = "service.server.up"
|
||||||
statsdServiceOpenConnsName = "service.connections.open"
|
statsdServiceOpenConnsName = "service.connections.open"
|
||||||
|
statsdServiceReqsBytesName = "service.requests.bytes.total"
|
||||||
|
statsdServiceRespsBytesName = "service.responses.bytes.total"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterStatsd registers the metrics pusher if this didn't happen yet and creates a statsd Registry instance.
|
// RegisterStatsd registers the metrics pusher if this didn't happen yet and creates a statsd Registry instance.
|
||||||
|
@ -72,6 +78,8 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry {
|
||||||
registry.entryPointReqsTLSCounter = statsdClient.NewCounter(statsdEntryPointReqsTLSName, 1.0)
|
registry.entryPointReqsTLSCounter = statsdClient.NewCounter(statsdEntryPointReqsTLSName, 1.0)
|
||||||
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(statsdClient.NewTiming(statsdEntryPointReqDurationName, 1.0), time.Millisecond)
|
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(statsdClient.NewTiming(statsdEntryPointReqDurationName, 1.0), time.Millisecond)
|
||||||
registry.entryPointOpenConnsGauge = statsdClient.NewGauge(statsdEntryPointOpenConnsName)
|
registry.entryPointOpenConnsGauge = statsdClient.NewGauge(statsdEntryPointOpenConnsName)
|
||||||
|
registry.entryPointReqsBytesCounter = statsdClient.NewCounter(statsdEntryPointReqsBytesName, 1.0)
|
||||||
|
registry.entryPointRespsBytesCounter = statsdClient.NewCounter(statsdEntryPointRespsBytesName, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddRoutersLabels {
|
if config.AddRoutersLabels {
|
||||||
|
@ -80,6 +88,8 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry {
|
||||||
registry.routerReqsTLSCounter = statsdClient.NewCounter(statsdRouterReqsTLSName, 1.0)
|
registry.routerReqsTLSCounter = statsdClient.NewCounter(statsdRouterReqsTLSName, 1.0)
|
||||||
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(statsdClient.NewTiming(statsdRouterReqsDurationName, 1.0), time.Millisecond)
|
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(statsdClient.NewTiming(statsdRouterReqsDurationName, 1.0), time.Millisecond)
|
||||||
registry.routerOpenConnsGauge = statsdClient.NewGauge(statsdRouterOpenConnsName)
|
registry.routerOpenConnsGauge = statsdClient.NewGauge(statsdRouterOpenConnsName)
|
||||||
|
registry.routerReqsBytesCounter = statsdClient.NewCounter(statsdRouterReqsBytesName, 1.0)
|
||||||
|
registry.routerRespsBytesCounter = statsdClient.NewCounter(statsdRouterRespsBytesName, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AddServicesLabels {
|
if config.AddServicesLabels {
|
||||||
|
@ -90,6 +100,8 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry {
|
||||||
registry.serviceRetriesCounter = statsdClient.NewCounter(statsdServiceRetriesTotalName, 1.0)
|
registry.serviceRetriesCounter = statsdClient.NewCounter(statsdServiceRetriesTotalName, 1.0)
|
||||||
registry.serviceOpenConnsGauge = statsdClient.NewGauge(statsdServiceOpenConnsName)
|
registry.serviceOpenConnsGauge = statsdClient.NewGauge(statsdServiceOpenConnsName)
|
||||||
registry.serviceServerUpGauge = statsdClient.NewGauge(statsdServiceServerUpName)
|
registry.serviceServerUpGauge = statsdClient.NewGauge(statsdServiceServerUpName)
|
||||||
|
registry.serviceReqsBytesCounter = statsdClient.NewCounter(statsdServiceReqsBytesName, 1.0)
|
||||||
|
registry.serviceRespsBytesCounter = statsdClient.NewCounter(statsdServiceRespsBytesName, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return registry
|
return registry
|
||||||
|
|
|
@ -59,11 +59,15 @@ func testRegistry(t *testing.T, metricsPrefix string, registry Registry) {
|
||||||
metricsPrefix + ".entrypoint.request.tls.total:1.000000|c\n",
|
metricsPrefix + ".entrypoint.request.tls.total:1.000000|c\n",
|
||||||
metricsPrefix + ".entrypoint.request.duration:10000.000000|ms",
|
metricsPrefix + ".entrypoint.request.duration:10000.000000|ms",
|
||||||
metricsPrefix + ".entrypoint.connections.open:1.000000|g\n",
|
metricsPrefix + ".entrypoint.connections.open:1.000000|g\n",
|
||||||
|
metricsPrefix + ".entrypoint.requests.bytes.total:1.000000|c\n",
|
||||||
|
metricsPrefix + ".entrypoint.responses.bytes.total:1.000000|c\n",
|
||||||
|
|
||||||
metricsPrefix + ".router.request.total:2.000000|c\n",
|
metricsPrefix + ".router.request.total:2.000000|c\n",
|
||||||
metricsPrefix + ".router.request.tls.total:1.000000|c\n",
|
metricsPrefix + ".router.request.tls.total:1.000000|c\n",
|
||||||
metricsPrefix + ".router.request.duration:10000.000000|ms",
|
metricsPrefix + ".router.request.duration:10000.000000|ms",
|
||||||
metricsPrefix + ".router.connections.open:1.000000|g\n",
|
metricsPrefix + ".router.connections.open:1.000000|g\n",
|
||||||
|
metricsPrefix + ".router.requests.bytes.total:1.000000|c\n",
|
||||||
|
metricsPrefix + ".router.responses.bytes.total:1.000000|c\n",
|
||||||
|
|
||||||
metricsPrefix + ".service.request.total:2.000000|c\n",
|
metricsPrefix + ".service.request.total:2.000000|c\n",
|
||||||
metricsPrefix + ".service.request.tls.total:1.000000|c\n",
|
metricsPrefix + ".service.request.tls.total:1.000000|c\n",
|
||||||
|
@ -71,6 +75,8 @@ func testRegistry(t *testing.T, metricsPrefix string, registry Registry) {
|
||||||
metricsPrefix + ".service.connections.open:1.000000|g\n",
|
metricsPrefix + ".service.connections.open:1.000000|g\n",
|
||||||
metricsPrefix + ".service.retries.total:2.000000|c\n",
|
metricsPrefix + ".service.retries.total:2.000000|c\n",
|
||||||
metricsPrefix + ".service.server.up:1.000000|g\n",
|
metricsPrefix + ".service.server.up:1.000000|g\n",
|
||||||
|
metricsPrefix + ".service.requests.bytes.total:1.000000|c\n",
|
||||||
|
metricsPrefix + ".service.responses.bytes.total:1.000000|c\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
udp.ShouldReceiveAll(t, expected, func() {
|
udp.ShouldReceiveAll(t, expected, func() {
|
||||||
|
@ -85,12 +91,16 @@ func testRegistry(t *testing.T, metricsPrefix string, registry Registry) {
|
||||||
registry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
registry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
registry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
registry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
|
||||||
registry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
registry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
|
||||||
|
registry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
registry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
|
||||||
registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
||||||
registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
registry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
registry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
|
||||||
registry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
registry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
|
||||||
registry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
registry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
|
||||||
|
registry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
registry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
|
||||||
registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
|
||||||
|
@ -100,5 +110,7 @@ func testRegistry(t *testing.T, metricsPrefix string, registry Registry) {
|
||||||
registry.ServiceRetriesCounter().With("service", "test").Add(1)
|
registry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
registry.ServiceRetriesCounter().With("service", "test").Add(1)
|
registry.ServiceRetriesCounter().With("service", "test").Add(1)
|
||||||
registry.ServiceServerUpGauge().With("service:test", "url", "http://127.0.0.1").Set(1)
|
registry.ServiceServerUpGauge().With("service:test", "url", "http://127.0.0.1").Set(1)
|
||||||
|
registry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
|
registry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package accesslog
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
type captureRequestReader struct {
|
|
||||||
// source ReadCloser from where the request body is read.
|
|
||||||
source io.ReadCloser
|
|
||||||
// count Counts the number of bytes read (when captureRequestReader.Read is called).
|
|
||||||
count int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *captureRequestReader) Read(p []byte) (int, error) {
|
|
||||||
n, err := r.source.Read(p)
|
|
||||||
r.count += int64(n)
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *captureRequestReader) Close() error {
|
|
||||||
return r.source.Close()
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
package accesslog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/traefik/traefik/v2/pkg/middlewares"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ middlewares.Stateful = &captureResponseWriterWithCloseNotify{}
|
|
||||||
|
|
||||||
type capturer interface {
|
|
||||||
http.ResponseWriter
|
|
||||||
Size() int64
|
|
||||||
Status() int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCaptureResponseWriter(rw http.ResponseWriter) capturer {
|
|
||||||
capt := &captureResponseWriter{rw: rw}
|
|
||||||
if _, ok := rw.(http.CloseNotifier); !ok {
|
|
||||||
return capt
|
|
||||||
}
|
|
||||||
return &captureResponseWriterWithCloseNotify{capt}
|
|
||||||
}
|
|
||||||
|
|
||||||
// captureResponseWriter is a wrapper of type http.ResponseWriter
|
|
||||||
// that tracks request status and size.
|
|
||||||
type captureResponseWriter struct {
|
|
||||||
rw http.ResponseWriter
|
|
||||||
status int
|
|
||||||
size int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type captureResponseWriterWithCloseNotify struct {
|
|
||||||
*captureResponseWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseNotify returns a channel that receives at most a
|
|
||||||
// single value (true) when the client connection has gone away.
|
|
||||||
func (r *captureResponseWriterWithCloseNotify) CloseNotify() <-chan bool {
|
|
||||||
return r.rw.(http.CloseNotifier).CloseNotify()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (crw *captureResponseWriter) Header() http.Header {
|
|
||||||
return crw.rw.Header()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (crw *captureResponseWriter) Write(b []byte) (int, error) {
|
|
||||||
if crw.status == 0 {
|
|
||||||
crw.status = http.StatusOK
|
|
||||||
}
|
|
||||||
size, err := crw.rw.Write(b)
|
|
||||||
crw.size += int64(size)
|
|
||||||
return size, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (crw *captureResponseWriter) WriteHeader(s int) {
|
|
||||||
crw.rw.WriteHeader(s)
|
|
||||||
crw.status = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (crw *captureResponseWriter) Flush() {
|
|
||||||
if f, ok := crw.rw.(http.Flusher); ok {
|
|
||||||
f.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (crw *captureResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|
||||||
if h, ok := crw.rw.(http.Hijacker); ok {
|
|
||||||
return h.Hijack()
|
|
||||||
}
|
|
||||||
return nil, nil, fmt.Errorf("not a hijacker: %T", crw.rw)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (crw *captureResponseWriter) Status() int {
|
|
||||||
return crw.status
|
|
||||||
}
|
|
||||||
|
|
||||||
func (crw *captureResponseWriter) Size() int64 {
|
|
||||||
return crw.size
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
package accesslog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
type rwWithCloseNotify struct {
|
|
||||||
*httptest.ResponseRecorder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *rwWithCloseNotify) CloseNotify() <-chan bool {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCloseNotifier(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
rw http.ResponseWriter
|
|
||||||
desc string
|
|
||||||
implementsCloseNotifier bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
rw: httptest.NewRecorder(),
|
|
||||||
desc: "does not implement CloseNotifier",
|
|
||||||
implementsCloseNotifier: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rw: &rwWithCloseNotify{httptest.NewRecorder()},
|
|
||||||
desc: "implements CloseNotifier",
|
|
||||||
implementsCloseNotifier: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range testCases {
|
|
||||||
test := test
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
_, ok := test.rw.(http.CloseNotifier)
|
|
||||||
assert.Equal(t, test.implementsCloseNotifier, ok)
|
|
||||||
|
|
||||||
rw := newCaptureResponseWriter(test.rw)
|
|
||||||
_, impl := rw.(http.CloseNotifier)
|
|
||||||
assert.Equal(t, test.implementsCloseNotifier, impl)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
|
||||||
"github.com/vulcand/oxy/utils"
|
"github.com/vulcand/oxy/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,16 +51,24 @@ func AddServiceFields(rw http.ResponseWriter, req *http.Request, next http.Handl
|
||||||
|
|
||||||
// AddOriginFields add origin fields.
|
// AddOriginFields add origin fields.
|
||||||
func AddOriginFields(rw http.ResponseWriter, req *http.Request, next http.Handler, data *LogData) {
|
func AddOriginFields(rw http.ResponseWriter, req *http.Request, next http.Handler, data *LogData) {
|
||||||
crw := newCaptureResponseWriter(rw)
|
|
||||||
start := time.Now().UTC()
|
start := time.Now().UTC()
|
||||||
|
|
||||||
next.ServeHTTP(crw, req)
|
next.ServeHTTP(rw, req)
|
||||||
|
|
||||||
// use UTC to handle switchover of daylight saving correctly
|
// use UTC to handle switchover of daylight saving correctly
|
||||||
data.Core[OriginDuration] = time.Now().UTC().Sub(start)
|
data.Core[OriginDuration] = time.Now().UTC().Sub(start)
|
||||||
data.Core[OriginStatus] = crw.Status()
|
// make copy of headers, so we can ensure there is no subsequent mutation
|
||||||
// make copy of headers so we can ensure there is no subsequent mutation during response processing
|
// during response processing
|
||||||
data.OriginResponse = make(http.Header)
|
data.OriginResponse = make(http.Header)
|
||||||
utils.CopyHeaders(data.OriginResponse, crw.Header())
|
utils.CopyHeaders(data.OriginResponse, rw.Header())
|
||||||
data.Core[OriginContentSize] = crw.Size()
|
|
||||||
|
ctx := req.Context()
|
||||||
|
capt, err := capture.FromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.FromContext(log.With(ctx, log.Str(log.MiddlewareType, "AccessLogs"))).Errorf("Could not get Capture: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Core[OriginStatus] = capt.StatusCode()
|
||||||
|
data.Core[OriginContentSize] = capt.ResponseSize()
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
ptypes "github.com/traefik/paerser/types"
|
ptypes "github.com/traefik/paerser/types"
|
||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
|
||||||
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
||||||
"github.com/traefik/traefik/v2/pkg/types"
|
"github.com/traefik/traefik/v2/pkg/types"
|
||||||
)
|
)
|
||||||
|
@ -182,13 +183,17 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
reqWithDataTable := req.WithContext(context.WithValue(req.Context(), DataTableKey, logDataTable))
|
defer func() {
|
||||||
|
if h.config.BufferingSize > 0 {
|
||||||
|
h.logHandlerChan <- handlerParams{
|
||||||
|
logDataTable: logDataTable,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.logTheRoundTrip(logDataTable)
|
||||||
|
}()
|
||||||
|
|
||||||
var crr *captureRequestReader
|
reqWithDataTable := req.WithContext(context.WithValue(req.Context(), DataTableKey, logDataTable))
|
||||||
if req.Body != nil {
|
|
||||||
crr = &captureRequestReader{source: req.Body, count: 0}
|
|
||||||
reqWithDataTable.Body = crr
|
|
||||||
}
|
|
||||||
|
|
||||||
core[RequestCount] = nextRequestCount()
|
core[RequestCount] = nextRequestCount()
|
||||||
if req.Host != "" {
|
if req.Host != "" {
|
||||||
|
@ -222,30 +227,26 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http
|
||||||
core[ClientHost] = forwardedFor
|
core[ClientHost] = forwardedFor
|
||||||
}
|
}
|
||||||
|
|
||||||
crw := newCaptureResponseWriter(rw)
|
next.ServeHTTP(rw, reqWithDataTable)
|
||||||
|
|
||||||
next.ServeHTTP(crw, reqWithDataTable)
|
|
||||||
|
|
||||||
if _, ok := core[ClientUsername]; !ok {
|
if _, ok := core[ClientUsername]; !ok {
|
||||||
core[ClientUsername] = usernameIfPresent(reqWithDataTable.URL)
|
core[ClientUsername] = usernameIfPresent(reqWithDataTable.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
logDataTable.DownstreamResponse = downstreamResponse{
|
logDataTable.DownstreamResponse = downstreamResponse{
|
||||||
headers: crw.Header().Clone(),
|
headers: rw.Header().Clone(),
|
||||||
status: crw.Status(),
|
|
||||||
size: crw.Size(),
|
|
||||||
}
|
|
||||||
if crr != nil {
|
|
||||||
logDataTable.Request.size = crr.count
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.config.BufferingSize > 0 {
|
ctx := req.Context()
|
||||||
h.logHandlerChan <- handlerParams{
|
capt, err := capture.FromContext(ctx)
|
||||||
logDataTable: logDataTable,
|
if err != nil {
|
||||||
}
|
log.FromContext(log.With(ctx, log.Str(log.MiddlewareType, "AccessLogs"))).Errorf("Could not get Capture: %v", err)
|
||||||
} else {
|
return
|
||||||
h.logTheRoundTrip(logDataTable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logDataTable.DownstreamResponse.status = capt.StatusCode()
|
||||||
|
logDataTable.DownstreamResponse.size = capt.ResponseSize()
|
||||||
|
logDataTable.Request.size = capt.RequestSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the Logger (i.e. the file, drain logHandlerChan, etc).
|
// Close closes the Logger (i.e. the file, drain logHandlerChan, etc).
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package accesslog
|
package accesslog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -14,9 +16,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/alice"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
ptypes "github.com/traefik/paerser/types"
|
ptypes "github.com/traefik/paerser/types"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
|
||||||
"github.com/traefik/traefik/v2/pkg/types"
|
"github.com/traefik/traefik/v2/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,23 +50,29 @@ func TestLogRotation(t *testing.T) {
|
||||||
|
|
||||||
config := &types.AccessLog{FilePath: fileName, Format: CommonFormat}
|
config := &types.AccessLog{FilePath: fileName, Format: CommonFormat}
|
||||||
logHandler, err := NewHandler(config)
|
logHandler, err := NewHandler(config)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Error creating new log handler: %s", err)
|
t.Cleanup(func() {
|
||||||
}
|
err := logHandler.Close()
|
||||||
defer logHandler.Close()
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
chain := alice.New()
|
||||||
|
chain = chain.Append(capture.WrapHandler(&capture.Handler{}))
|
||||||
|
chain = chain.Append(WrapHandler(logHandler))
|
||||||
|
handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
||||||
next := func(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
rw.WriteHeader(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
iterations := 20
|
iterations := 20
|
||||||
halfDone := make(chan bool)
|
halfDone := make(chan bool)
|
||||||
writeDone := make(chan bool)
|
writeDone := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; i < iterations; i++ {
|
for i := 0; i < iterations; i++ {
|
||||||
logHandler.ServeHTTP(recorder, req, http.HandlerFunc(next))
|
handler.ServeHTTP(recorder, req)
|
||||||
if i == iterations/2 {
|
if i == iterations/2 {
|
||||||
halfDone <- true
|
halfDone <- true
|
||||||
}
|
}
|
||||||
|
@ -178,7 +188,10 @@ func TestLoggerHeaderFields(t *testing.T) {
|
||||||
|
|
||||||
logger, err := NewHandler(config)
|
logger, err := NewHandler(config)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer logger.Close()
|
t.Cleanup(func() {
|
||||||
|
err := logger.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
if config.FilePath != "" {
|
if config.FilePath != "" {
|
||||||
_, err = os.Stat(config.FilePath)
|
_, err = os.Stat(config.FilePath)
|
||||||
|
@ -196,9 +209,14 @@ func TestLoggerHeaderFields(t *testing.T) {
|
||||||
req.Header.Add(test.header, s)
|
req.Header.Add(test.header, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.ServeHTTP(httptest.NewRecorder(), req, http.HandlerFunc(func(writer http.ResponseWriter, r *http.Request) {
|
chain := alice.New()
|
||||||
writer.WriteHeader(http.StatusOK)
|
chain = chain.Append(capture.WrapHandler(&capture.Handler{}))
|
||||||
|
chain = chain.Append(WrapHandler(logger))
|
||||||
|
handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
}))
|
}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
handler.ServeHTTP(httptest.NewRecorder(), req)
|
||||||
|
|
||||||
logData, err := os.ReadFile(logFile.Name())
|
logData, err := os.ReadFile(logFile.Name())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -224,11 +242,14 @@ func TestLoggerCLF(t *testing.T) {
|
||||||
assertValidLogData(t, expectedLog, logData)
|
assertValidLogData(t, expectedLog, logData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAsyncLoggerCLF(t *testing.T) {
|
func TestLoggerCLFWithBufferingSize(t *testing.T) {
|
||||||
logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix)
|
logFilePath := filepath.Join(t.TempDir(), logFileNameSuffix)
|
||||||
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat, BufferingSize: 1024}
|
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat, BufferingSize: 1024}
|
||||||
doLogging(t, config)
|
doLogging(t, config)
|
||||||
|
|
||||||
|
// wait a bit for the buffer to be written in the file.
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
logData, err := os.ReadFile(logFilePath)
|
logData, err := os.ReadFile(logFilePath)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -691,9 +712,7 @@ func assertValidLogData(t *testing.T, expected string, logData []byte) {
|
||||||
resultExpected, err := ParseAccessLog(expected)
|
resultExpected, err := ParseAccessLog(expected)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
formatErrMessage := fmt.Sprintf(`
|
formatErrMessage := fmt.Sprintf("Expected:\t%q\nActual:\t%q", expected, string(logData))
|
||||||
Expected: %s
|
|
||||||
Actual: %s`, expected, string(logData))
|
|
||||||
|
|
||||||
require.Equal(t, len(resultExpected), len(result), formatErrMessage)
|
require.Equal(t, len(resultExpected), len(result), formatErrMessage)
|
||||||
assert.Equal(t, resultExpected[ClientHost], result[ClientHost], formatErrMessage)
|
assert.Equal(t, resultExpected[ClientHost], result[ClientHost], formatErrMessage)
|
||||||
|
@ -722,7 +741,7 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
|
||||||
|
|
||||||
restoreStdout = func() {
|
restoreStdout = func() {
|
||||||
os.Stdout = original
|
os.Stdout = original
|
||||||
os.RemoveAll(file.Name())
|
_ = os.RemoveAll(file.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
return file, restoreStdout
|
return file, restoreStdout
|
||||||
|
@ -730,10 +749,12 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
|
||||||
|
|
||||||
func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
|
func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
logger, err := NewHandler(config)
|
logger, err := NewHandler(config)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer logger.Close()
|
t.Cleanup(func() {
|
||||||
|
err := logger.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
if config.FilePath != "" {
|
if config.FilePath != "" {
|
||||||
_, err = os.Stat(config.FilePath)
|
_, err = os.Stat(config.FilePath)
|
||||||
|
@ -753,6 +774,7 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
|
||||||
User: url.UserPassword(testUsername, ""),
|
User: url.UserPassword(testUsername, ""),
|
||||||
Path: testPath,
|
Path: testPath,
|
||||||
},
|
},
|
||||||
|
Body: io.NopCloser(bytes.NewReader([]byte("bar"))),
|
||||||
}
|
}
|
||||||
if enableTLS {
|
if enableTLS {
|
||||||
req.TLS = &tls.ConnectionState{
|
req.TLS = &tls.ConnectionState{
|
||||||
|
@ -761,7 +783,13 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.ServeHTTP(httptest.NewRecorder(), req, http.HandlerFunc(logWriterTestHandlerFunc))
|
chain := alice.New()
|
||||||
|
chain = chain.Append(capture.WrapHandler(&capture.Handler{}))
|
||||||
|
chain = chain.Append(WrapHandler(logger))
|
||||||
|
handler, err := chain.Then(http.HandlerFunc(logWriterTestHandlerFunc))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
handler.ServeHTTP(httptest.NewRecorder(), req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func doLoggingTLS(t *testing.T, config *types.AccessLog) {
|
func doLoggingTLS(t *testing.T, config *types.AccessLog) {
|
||||||
|
|
198
pkg/middlewares/capture/capture.go
Normal file
198
pkg/middlewares/capture/capture.go
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
// Package capture is a middleware that captures requests/responses size, and status.
|
||||||
|
//
|
||||||
|
// For another middleware to get those attributes of a request/response, this middleware
|
||||||
|
// should be added before in the middleware chain.
|
||||||
|
//
|
||||||
|
// handler, _ := NewHandler()
|
||||||
|
// chain := alice.New().
|
||||||
|
// Append(WrapHandler(handler)).
|
||||||
|
// Append(myOtherMiddleware).
|
||||||
|
// then(...)
|
||||||
|
//
|
||||||
|
// As this middleware stores those data in the request's context, the data can
|
||||||
|
// be retrieved at anytime after the ServerHTTP.
|
||||||
|
//
|
||||||
|
// func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http.Handler) {
|
||||||
|
// capt, err := capture.FromContext(req.Context())
|
||||||
|
// if err != nil {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fmt.Println(capt.Status())
|
||||||
|
// fmt.Println(capt.ResponseSize())
|
||||||
|
// fmt.Println(capt.RequestSize())
|
||||||
|
// }
|
||||||
|
package capture
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/containous/alice"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares"
|
||||||
|
)
|
||||||
|
|
||||||
|
type key string
|
||||||
|
|
||||||
|
const capturedData key = "capturedData"
|
||||||
|
|
||||||
|
// Handler will store each request data to its context.
|
||||||
|
type Handler struct{}
|
||||||
|
|
||||||
|
// WrapHandler wraps capture handler into an Alice Constructor.
|
||||||
|
func WrapHandler(handler *Handler) 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)
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http.Handler) {
|
||||||
|
c := Capture{}
|
||||||
|
if req.Body != nil {
|
||||||
|
readCounter := &readCounter{source: req.Body}
|
||||||
|
c.rr = readCounter
|
||||||
|
req.Body = readCounter
|
||||||
|
}
|
||||||
|
responseWriter := newResponseWriter(rw)
|
||||||
|
c.rw = responseWriter
|
||||||
|
ctx := context.WithValue(req.Context(), capturedData, &c)
|
||||||
|
next.ServeHTTP(responseWriter, req.WithContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture is the object populated by the capture middleware,
|
||||||
|
// allowing to gather information about the request and response.
|
||||||
|
type Capture struct {
|
||||||
|
rr *readCounter
|
||||||
|
rw responseWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext returns the Capture value found in ctx, or an empty Capture otherwise.
|
||||||
|
func FromContext(ctx context.Context) (*Capture, error) {
|
||||||
|
c := ctx.Value(capturedData)
|
||||||
|
if c == nil {
|
||||||
|
return nil, errors.New("value not found")
|
||||||
|
}
|
||||||
|
capt, ok := c.(*Capture)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("value stored in Context is not a *Capture")
|
||||||
|
}
|
||||||
|
return capt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Capture) ResponseSize() int64 {
|
||||||
|
return c.rw.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Capture) StatusCode() int {
|
||||||
|
return c.rw.Status()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestSize returns the size of the request's body if it applies,
|
||||||
|
// zero otherwise.
|
||||||
|
func (c Capture) RequestSize() int64 {
|
||||||
|
if c.rr == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return c.rr.size
|
||||||
|
}
|
||||||
|
|
||||||
|
type readCounter struct {
|
||||||
|
// source ReadCloser from where the request body is read.
|
||||||
|
source io.ReadCloser
|
||||||
|
// size is total the number of bytes read.
|
||||||
|
size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *readCounter) Read(p []byte) (int, error) {
|
||||||
|
n, err := r.source.Read(p)
|
||||||
|
r.size += int64(n)
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *readCounter) Close() error {
|
||||||
|
return r.source.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ middlewares.Stateful = &responseWriterWithCloseNotify{}
|
||||||
|
|
||||||
|
type responseWriter interface {
|
||||||
|
http.ResponseWriter
|
||||||
|
Size() int64
|
||||||
|
Status() int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newResponseWriter(rw http.ResponseWriter) responseWriter {
|
||||||
|
capt := &captureResponseWriter{rw: rw}
|
||||||
|
if _, ok := rw.(http.CloseNotifier); !ok {
|
||||||
|
return capt
|
||||||
|
}
|
||||||
|
|
||||||
|
return &responseWriterWithCloseNotify{capt}
|
||||||
|
}
|
||||||
|
|
||||||
|
// captureResponseWriter is a wrapper of type http.ResponseWriter
|
||||||
|
// that tracks response status and size.
|
||||||
|
type captureResponseWriter struct {
|
||||||
|
rw http.ResponseWriter
|
||||||
|
status int
|
||||||
|
size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crw *captureResponseWriter) Header() http.Header {
|
||||||
|
return crw.rw.Header()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crw *captureResponseWriter) Size() int64 {
|
||||||
|
return crw.size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crw *captureResponseWriter) Status() int {
|
||||||
|
return crw.status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crw *captureResponseWriter) Write(b []byte) (int, error) {
|
||||||
|
if crw.status == 0 {
|
||||||
|
crw.status = http.StatusOK
|
||||||
|
}
|
||||||
|
|
||||||
|
size, err := crw.rw.Write(b)
|
||||||
|
crw.size += int64(size)
|
||||||
|
|
||||||
|
return size, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crw *captureResponseWriter) WriteHeader(s int) {
|
||||||
|
crw.rw.WriteHeader(s)
|
||||||
|
crw.status = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crw *captureResponseWriter) Flush() {
|
||||||
|
if f, ok := crw.rw.(http.Flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crw *captureResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
if h, ok := crw.rw.(http.Hijacker); ok {
|
||||||
|
return h.Hijack()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil, fmt.Errorf("not a hijacker: %T", crw.rw)
|
||||||
|
}
|
||||||
|
|
||||||
|
type responseWriterWithCloseNotify struct {
|
||||||
|
*captureResponseWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseNotify returns a channel that receives at most a
|
||||||
|
// single value (true) when the client connection has gone away.
|
||||||
|
func (r *responseWriterWithCloseNotify) CloseNotify() <-chan bool {
|
||||||
|
return r.rw.(http.CloseNotifier).CloseNotify()
|
||||||
|
}
|
234
pkg/middlewares/capture/capture_test.go
Normal file
234
pkg/middlewares/capture/capture_test.go
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
package capture
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containous/alice"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCapture(t *testing.T) {
|
||||||
|
wrapMiddleware := func(next http.Handler) (http.Handler, error) {
|
||||||
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
capt, err := FromContext(req.Context())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = fmt.Fprintf(rw, "%d,%d,%d,", capt.RequestSize(), capt.ResponseSize(), capt.StatusCode())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
next.ServeHTTP(rw, req)
|
||||||
|
|
||||||
|
_, err = fmt.Fprintf(rw, ",%d,%d,%d", capt.RequestSize(), capt.ResponseSize(), capt.StatusCode())
|
||||||
|
require.NoError(t, err)
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
_, err := rw.Write([]byte("foo"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
all, err := io.ReadAll(req.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "bar", string(all))
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapped := WrapHandler(&Handler{})
|
||||||
|
chain := alice.New()
|
||||||
|
chain = chain.Append(wrapped)
|
||||||
|
chain = chain.Append(wrapMiddleware)
|
||||||
|
handlers, err := chain.Then(handler)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
request, err := http.NewRequest(http.MethodGet, "/", bytes.NewReader([]byte("bar")))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
handlers.ServeHTTP(recorder, request)
|
||||||
|
// 3 = len("bar")
|
||||||
|
// 9 = len("0,0,0,toto")
|
||||||
|
assert.Equal(t, "0,0,0,foo,3,9,200", recorder.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkCapture with response writer and request reader
|
||||||
|
// $ go test -bench=. ./pkg/middlewares/capture/
|
||||||
|
// goos: linux
|
||||||
|
// goarch: amd64
|
||||||
|
// pkg: github.com/traefik/traefik/v2/pkg/middlewares/capture
|
||||||
|
// cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
|
||||||
|
// BenchmarkCapture/2k-12 280507 4015 ns/op 510.03 MB/s 5072 B/op 14 allocs/op
|
||||||
|
// BenchmarkCapture/20k-12 135726 8301 ns/op 2467.26 MB/s 41936 B/op 14 allocs/op
|
||||||
|
// BenchmarkCapture/100k-12 45494 26059 ns/op 3929.54 MB/s 213968 B/op 14 allocs/op
|
||||||
|
// BenchmarkCapture/2k_captured-12 263713 4356 ns/op 470.20 MB/s 5552 B/op 18 allocs/op
|
||||||
|
// BenchmarkCapture/20k_captured-12 132243 8790 ns/op 2329.98 MB/s 42416 B/op 18 allocs/op
|
||||||
|
// BenchmarkCapture/100k_captured-12 45650 26587 ns/op 3851.57 MB/s 214448 B/op 18 allocs/op
|
||||||
|
// BenchmarkCapture/2k_body-12 274135 7471 ns/op 274.12 MB/s 5624 B/op 20 allocs/op
|
||||||
|
// BenchmarkCapture/20k_body-12 130206 21149 ns/op 968.36 MB/s 42488 B/op 20 allocs/op
|
||||||
|
// BenchmarkCapture/100k_body-12 41600 51716 ns/op 1980.06 MB/s 214520 B/op 20 allocs/op
|
||||||
|
// PASS
|
||||||
|
func BenchmarkCapture(b *testing.B) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
size int
|
||||||
|
capture bool
|
||||||
|
body bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "2k",
|
||||||
|
size: 2048,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "20k",
|
||||||
|
size: 20480,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "100k",
|
||||||
|
size: 102400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "2k captured",
|
||||||
|
size: 2048,
|
||||||
|
capture: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "20k captured",
|
||||||
|
size: 20480,
|
||||||
|
capture: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "100k captured",
|
||||||
|
size: 102400,
|
||||||
|
capture: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "2k body",
|
||||||
|
size: 2048,
|
||||||
|
body: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "20k body",
|
||||||
|
size: 20480,
|
||||||
|
body: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "100k body",
|
||||||
|
size: 102400,
|
||||||
|
body: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
b.Run(test.name, func(b *testing.B) {
|
||||||
|
baseBody := generateBytes(test.size)
|
||||||
|
|
||||||
|
next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
n, err := rw.Write(baseBody)
|
||||||
|
require.Equal(b, test.size, n)
|
||||||
|
require.NoError(b, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
var body io.Reader
|
||||||
|
if test.body {
|
||||||
|
body = bytes.NewReader(baseBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "http://foo/", body)
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
chain := alice.New()
|
||||||
|
if test.capture || test.body {
|
||||||
|
captureWrapped := WrapHandler(&Handler{})
|
||||||
|
chain = chain.Append(captureWrapped)
|
||||||
|
}
|
||||||
|
handlers, err := chain.Then(next)
|
||||||
|
require.NoError(b, err)
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.SetBytes(int64(test.size))
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
runBenchmark(b, test.size, req, handlers)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runBenchmark(b *testing.B, size int, req *http.Request, handler http.Handler) {
|
||||||
|
b.Helper()
|
||||||
|
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
handler.ServeHTTP(recorder, req)
|
||||||
|
if code := recorder.Code; code != 200 {
|
||||||
|
b.Fatalf("Expected 200 but got %d", code)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(b, size, len(recorder.Body.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateBytes(length int) []byte {
|
||||||
|
var value []byte
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
value = append(value, 0x61+byte(i%26))
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequestReader(t *testing.T) {
|
||||||
|
buff := bytes.NewBuffer([]byte("foo"))
|
||||||
|
rr := readCounter{source: io.NopCloser(buff)}
|
||||||
|
assert.Equal(t, int64(0), rr.size)
|
||||||
|
|
||||||
|
n, err := rr.Read([]byte("bar"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, 3, n)
|
||||||
|
|
||||||
|
err = rr.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, int64(3), rr.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
type rwWithCloseNotify struct {
|
||||||
|
*httptest.ResponseRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rwWithCloseNotify) CloseNotify() <-chan bool {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCloseNotifier(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
rw http.ResponseWriter
|
||||||
|
desc string
|
||||||
|
implementsCloseNotifier bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
rw: httptest.NewRecorder(),
|
||||||
|
desc: "does not implement CloseNotifier",
|
||||||
|
implementsCloseNotifier: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rw: &rwWithCloseNotify{httptest.NewRecorder()},
|
||||||
|
desc: "implements CloseNotifier",
|
||||||
|
implementsCloseNotifier: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
_, ok := test.rw.(http.CloseNotifier)
|
||||||
|
assert.Equal(t, test.implementsCloseNotifier, ok)
|
||||||
|
|
||||||
|
rw := newResponseWriter(test.rw)
|
||||||
|
_, impl := rw.(http.CloseNotifier)
|
||||||
|
assert.Equal(t, test.implementsCloseNotifier, impl)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
"github.com/traefik/traefik/v2/pkg/metrics"
|
"github.com/traefik/traefik/v2/pkg/metrics"
|
||||||
"github.com/traefik/traefik/v2/pkg/middlewares"
|
"github.com/traefik/traefik/v2/pkg/middlewares"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
|
||||||
"github.com/traefik/traefik/v2/pkg/middlewares/retry"
|
"github.com/traefik/traefik/v2/pkg/middlewares/retry"
|
||||||
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
||||||
)
|
)
|
||||||
|
@ -32,6 +33,8 @@ type metricsMiddleware struct {
|
||||||
reqsTLSCounter gokitmetrics.Counter
|
reqsTLSCounter gokitmetrics.Counter
|
||||||
reqDurationHistogram metrics.ScalableHistogram
|
reqDurationHistogram metrics.ScalableHistogram
|
||||||
openConnsGauge gokitmetrics.Gauge
|
openConnsGauge gokitmetrics.Gauge
|
||||||
|
reqsBytesCounter gokitmetrics.Counter
|
||||||
|
respsBytesCounter gokitmetrics.Counter
|
||||||
baseLabels []string
|
baseLabels []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +48,8 @@ func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry me
|
||||||
reqsTLSCounter: registry.EntryPointReqsTLSCounter(),
|
reqsTLSCounter: registry.EntryPointReqsTLSCounter(),
|
||||||
reqDurationHistogram: registry.EntryPointReqDurationHistogram(),
|
reqDurationHistogram: registry.EntryPointReqDurationHistogram(),
|
||||||
openConnsGauge: registry.EntryPointOpenConnsGauge(),
|
openConnsGauge: registry.EntryPointOpenConnsGauge(),
|
||||||
|
reqsBytesCounter: registry.EntryPointReqsBytesCounter(),
|
||||||
|
respsBytesCounter: registry.EntryPointRespsBytesCounter(),
|
||||||
baseLabels: []string{"entrypoint", entryPointName},
|
baseLabels: []string{"entrypoint", entryPointName},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +64,8 @@ func NewRouterMiddleware(ctx context.Context, next http.Handler, registry metric
|
||||||
reqsTLSCounter: registry.RouterReqsTLSCounter(),
|
reqsTLSCounter: registry.RouterReqsTLSCounter(),
|
||||||
reqDurationHistogram: registry.RouterReqDurationHistogram(),
|
reqDurationHistogram: registry.RouterReqDurationHistogram(),
|
||||||
openConnsGauge: registry.RouterOpenConnsGauge(),
|
openConnsGauge: registry.RouterOpenConnsGauge(),
|
||||||
|
reqsBytesCounter: registry.RouterReqsBytesCounter(),
|
||||||
|
respsBytesCounter: registry.RouterRespsBytesCounter(),
|
||||||
baseLabels: []string{"router", routerName, "service", serviceName},
|
baseLabels: []string{"router", routerName, "service", serviceName},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +80,8 @@ func NewServiceMiddleware(ctx context.Context, next http.Handler, registry metri
|
||||||
reqsTLSCounter: registry.ServiceReqsTLSCounter(),
|
reqsTLSCounter: registry.ServiceReqsTLSCounter(),
|
||||||
reqDurationHistogram: registry.ServiceReqDurationHistogram(),
|
reqDurationHistogram: registry.ServiceReqDurationHistogram(),
|
||||||
openConnsGauge: registry.ServiceOpenConnsGauge(),
|
openConnsGauge: registry.ServiceOpenConnsGauge(),
|
||||||
|
reqsBytesCounter: registry.ServiceReqsBytesCounter(),
|
||||||
|
respsBytesCounter: registry.ServiceRespsBytesCounter(),
|
||||||
baseLabels: []string{"service", serviceName},
|
baseLabels: []string{"service", serviceName},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,16 +125,22 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||||
m.reqsTLSCounter.With(tlsLabels...).Add(1)
|
m.reqsTLSCounter.With(tlsLabels...).Add(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder := newResponseRecorder(rw)
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
m.next.ServeHTTP(recorder, req)
|
m.next.ServeHTTP(rw, req)
|
||||||
|
|
||||||
labels = append(labels, "code", strconv.Itoa(recorder.getCode()))
|
ctx := req.Context()
|
||||||
|
capt, err := capture.FromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.FromContext(middlewares.GetLoggerCtx(ctx, nameEntrypoint, typeName)).Errorf("Could not get Capture: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
labels = append(labels, "code", strconv.Itoa(capt.StatusCode()))
|
||||||
m.reqDurationHistogram.With(labels...).ObserveFromStart(start)
|
m.reqDurationHistogram.With(labels...).ObserveFromStart(start)
|
||||||
|
|
||||||
m.reqsCounter.With(labels...).Add(1)
|
m.reqsCounter.With(labels...).Add(1)
|
||||||
|
m.respsBytesCounter.With(labels...).Add(float64(capt.ResponseSize()))
|
||||||
|
m.reqsBytesCounter.With(labels...).Add(float64(capt.RequestSize()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRequestProtocol(req *http.Request) string {
|
func getRequestProtocol(req *http.Request) string {
|
||||||
|
@ -201,6 +216,6 @@ type RetryListener struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retried tracks the retry in the RequestMetrics implementation.
|
// Retried tracks the retry in the RequestMetrics implementation.
|
||||||
func (m *RetryListener) Retried(req *http.Request, attempt int) {
|
func (m *RetryListener) Retried(_ *http.Request, _ int) {
|
||||||
m.retryMetrics.ServiceRetriesCounter().With("service", m.serviceName).Add(1)
|
m.retryMetrics.ServiceRetriesCounter().With("service", m.serviceName).Add(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,13 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/containous/alice"
|
"github.com/containous/alice"
|
||||||
"github.com/traefik/traefik/v2/pkg/config/static"
|
|
||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
"github.com/traefik/traefik/v2/pkg/metrics"
|
"github.com/traefik/traefik/v2/pkg/metrics"
|
||||||
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
|
||||||
metricsmiddleware "github.com/traefik/traefik/v2/pkg/middlewares/metrics"
|
metricsmiddleware "github.com/traefik/traefik/v2/pkg/middlewares/metrics"
|
||||||
mTracing "github.com/traefik/traefik/v2/pkg/middlewares/tracing"
|
mTracing "github.com/traefik/traefik/v2/pkg/middlewares/tracing"
|
||||||
"github.com/traefik/traefik/v2/pkg/tracing"
|
"github.com/traefik/traefik/v2/pkg/tracing"
|
||||||
"github.com/traefik/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.
|
// 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.
|
||||||
|
@ -19,14 +18,16 @@ type ChainBuilder struct {
|
||||||
metricsRegistry metrics.Registry
|
metricsRegistry metrics.Registry
|
||||||
accessLoggerMiddleware *accesslog.Handler
|
accessLoggerMiddleware *accesslog.Handler
|
||||||
tracer *tracing.Tracing
|
tracer *tracing.Tracing
|
||||||
|
captureMiddleware *capture.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChainBuilder Creates a new ChainBuilder.
|
// NewChainBuilder Creates a new ChainBuilder.
|
||||||
func NewChainBuilder(staticConfiguration static.Configuration, metricsRegistry metrics.Registry, accessLoggerMiddleware *accesslog.Handler) *ChainBuilder {
|
func NewChainBuilder(metricsRegistry metrics.Registry, accessLoggerMiddleware *accesslog.Handler, tracer *tracing.Tracing, captureMiddleware *capture.Handler) *ChainBuilder {
|
||||||
return &ChainBuilder{
|
return &ChainBuilder{
|
||||||
metricsRegistry: metricsRegistry,
|
metricsRegistry: metricsRegistry,
|
||||||
accessLoggerMiddleware: accessLoggerMiddleware,
|
accessLoggerMiddleware: accessLoggerMiddleware,
|
||||||
tracer: setupTracing(staticConfiguration.Tracing),
|
tracer: tracer,
|
||||||
|
captureMiddleware: captureMiddleware,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +35,10 @@ func NewChainBuilder(staticConfiguration static.Configuration, metricsRegistry m
|
||||||
func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.Chain {
|
func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.Chain {
|
||||||
chain := alice.New()
|
chain := alice.New()
|
||||||
|
|
||||||
|
if c.captureMiddleware != nil {
|
||||||
|
chain = chain.Append(capture.WrapHandler(c.captureMiddleware))
|
||||||
|
}
|
||||||
|
|
||||||
if c.accessLoggerMiddleware != nil {
|
if c.accessLoggerMiddleware != nil {
|
||||||
chain = chain.Append(accesslog.WrapHandler(c.accessLoggerMiddleware))
|
chain = chain.Append(accesslog.WrapHandler(c.accessLoggerMiddleware))
|
||||||
}
|
}
|
||||||
|
@ -61,69 +66,3 @@ func (c *ChainBuilder) Close() {
|
||||||
c.tracer.Close()
|
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 conf.Elastic != nil {
|
|
||||||
if backend != nil {
|
|
||||||
log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Elastic backend.")
|
|
||||||
} else {
|
|
||||||
backend = conf.Elastic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,13 +8,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containous/alice"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
||||||
"github.com/traefik/traefik/v2/pkg/config/static"
|
|
||||||
"github.com/traefik/traefik/v2/pkg/metrics"
|
"github.com/traefik/traefik/v2/pkg/metrics"
|
||||||
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
|
||||||
"github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator"
|
"github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator"
|
||||||
"github.com/traefik/traefik/v2/pkg/server/middleware"
|
"github.com/traefik/traefik/v2/pkg/server/middleware"
|
||||||
"github.com/traefik/traefik/v2/pkg/server/service"
|
"github.com/traefik/traefik/v2/pkg/server/service"
|
||||||
|
@ -315,7 +316,7 @@ func TestRouterManager_Get(t *testing.T) {
|
||||||
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
||||||
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
||||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
||||||
chainBuilder := middleware.NewChainBuilder(static.Configuration{}, nil, nil)
|
chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil)
|
||||||
|
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
||||||
|
|
||||||
|
@ -421,7 +422,7 @@ func TestAccessLog(t *testing.T) {
|
||||||
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
||||||
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
||||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
||||||
chainBuilder := middleware.NewChainBuilder(static.Configuration{}, nil, nil)
|
chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil)
|
||||||
|
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
||||||
|
|
||||||
|
@ -437,7 +438,10 @@ func TestAccessLog(t *testing.T) {
|
||||||
|
|
||||||
reqHost := requestdecorator.New(nil)
|
reqHost := requestdecorator.New(nil)
|
||||||
|
|
||||||
accesslogger.ServeHTTP(w, req, http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
chain := alice.New()
|
||||||
|
chain = chain.Append(capture.WrapHandler(&capture.Handler{}))
|
||||||
|
chain = chain.Append(accesslog.WrapHandler(accesslogger))
|
||||||
|
handler, err := chain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
reqHost.ServeHTTP(w, req, handlers["web"].ServeHTTP)
|
reqHost.ServeHTTP(w, req, handlers["web"].ServeHTTP)
|
||||||
|
|
||||||
data := accesslog.GetLogData(req)
|
data := accesslog.GetLogData(req)
|
||||||
|
@ -445,6 +449,9 @@ func TestAccessLog(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, test.expected, data.Core[accesslog.RouterName])
|
assert.Equal(t, test.expected, data.Core[accesslog.RouterName])
|
||||||
}))
|
}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
handler.ServeHTTP(w, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -710,7 +717,7 @@ func TestRuntimeConfiguration(t *testing.T) {
|
||||||
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
||||||
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
||||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
||||||
chainBuilder := middleware.NewChainBuilder(static.Configuration{}, nil, nil)
|
chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil)
|
||||||
|
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
||||||
|
|
||||||
|
@ -743,14 +750,6 @@ func TestRuntimeConfiguration(t *testing.T) {
|
||||||
func TestProviderOnMiddlewares(t *testing.T) {
|
func TestProviderOnMiddlewares(t *testing.T) {
|
||||||
entryPoints := []string{"web"}
|
entryPoints := []string{"web"}
|
||||||
|
|
||||||
staticCfg := static.Configuration{
|
|
||||||
EntryPoints: map[string]*static.EntryPoint{
|
|
||||||
"web": {
|
|
||||||
Address: ":80",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
rtConf := runtime.NewConfig(dynamic.Configuration{
|
rtConf := runtime.NewConfig(dynamic.Configuration{
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
|
@ -793,7 +792,7 @@ func TestProviderOnMiddlewares(t *testing.T) {
|
||||||
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
||||||
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
serviceManager := service.NewManager(rtConf.Services, nil, nil, roundTripperManager)
|
||||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
||||||
chainBuilder := middleware.NewChainBuilder(staticCfg, nil, nil)
|
chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil)
|
||||||
|
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
||||||
|
|
||||||
|
@ -861,7 +860,7 @@ func BenchmarkRouterServe(b *testing.B) {
|
||||||
|
|
||||||
serviceManager := service.NewManager(rtConf.Services, nil, nil, staticRoundTripperGetter{res})
|
serviceManager := service.NewManager(rtConf.Services, nil, nil, staticRoundTripperGetter{res})
|
||||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager, nil)
|
||||||
chainBuilder := middleware.NewChainBuilder(static.Configuration{}, nil, nil)
|
chainBuilder := middleware.NewChainBuilder(nil, nil, nil, nil)
|
||||||
|
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry())
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ func TestReuseService(t *testing.T) {
|
||||||
managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil)
|
managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil)
|
||||||
tlsManager := tls.NewManager()
|
tlsManager := tls.NewManager()
|
||||||
|
|
||||||
factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(staticConfig, metrics.NewVoidRegistry(), nil), nil, metrics.NewVoidRegistry())
|
factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil, nil), nil, metrics.NewVoidRegistry())
|
||||||
|
|
||||||
entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs}))
|
entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs}))
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
||||||
managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil)
|
managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil)
|
||||||
tlsManager := tls.NewManager()
|
tlsManager := tls.NewManager()
|
||||||
|
|
||||||
factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(staticConfig, metrics.NewVoidRegistry(), nil), nil, metrics.NewVoidRegistry())
|
factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil, nil), nil, metrics.NewVoidRegistry())
|
||||||
|
|
||||||
entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: test.config(testServer.URL)}))
|
entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: test.config(testServer.URL)}))
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ func TestInternalServices(t *testing.T) {
|
||||||
|
|
||||||
voidRegistry := metrics.NewVoidRegistry()
|
voidRegistry := metrics.NewVoidRegistry()
|
||||||
|
|
||||||
factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(staticConfig, voidRegistry, nil), nil, voidRegistry)
|
factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(voidRegistry, nil, nil, nil), nil, voidRegistry)
|
||||||
|
|
||||||
entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs}))
|
entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs}))
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package server
|
package server
|
||||||
|
|
Loading…
Reference in a new issue