2018-01-25 14:00:05 +03:00
package integration
import (
2024-01-08 11:10:06 +03:00
"encoding/json"
"io"
2018-01-25 14:00:05 +03:00
"net/http"
2024-01-08 11:10:06 +03:00
"net/url"
2018-01-25 14:00:05 +03:00
"os"
2024-01-08 11:10:06 +03:00
"strings"
2018-01-25 14:00:05 +03:00
"time"
"github.com/go-check/check"
2024-01-08 11:10:06 +03:00
"github.com/tidwall/gjson"
2023-02-03 17:24:05 +03:00
"github.com/traefik/traefik/v3/integration/try"
2018-01-25 14:00:05 +03:00
checker "github.com/vdemeester/shakers"
)
type TracingSuite struct {
BaseSuite
2024-01-08 11:10:06 +03:00
whoamiIP string
whoamiPort int
tempoIP string
otelCollectorIP string
2018-01-25 14:00:05 +03:00
}
type TracingTemplate struct {
2021-11-25 13:10:06 +03:00
WhoamiIP string
WhoamiPort int
2019-10-15 17:30:06 +03:00
IP string
TraceContextHeaderName string
2024-01-08 11:10:06 +03:00
IsHTTP bool
2018-01-25 14:00:05 +03:00
}
func ( s * TracingSuite ) SetUpSuite ( c * check . C ) {
s . createComposeProject ( c , "tracing" )
2021-11-25 13:10:06 +03:00
s . composeUp ( c )
2024-01-08 11:10:06 +03:00
}
func ( s * TracingSuite ) SetUpTest ( c * check . C ) {
s . composeUp ( c , "tempo" , "otel-collector" , "whoami" )
2018-01-25 14:00:05 +03:00
2021-11-25 13:10:06 +03:00
s . whoamiIP = s . getComposeServiceIP ( c , "whoami" )
s . whoamiPort = 80
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
// Wait for whoami to turn ready.
err := try . GetRequest ( "http://" + s . whoamiIP + ":80" , 30 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
s . tempoIP = s . getComposeServiceIP ( c , "tempo" )
// Wait for tempo to turn ready.
err = try . GetRequest ( "http://" + s . tempoIP + ":3200/ready" , 30 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
s . otelCollectorIP = s . getComposeServiceIP ( c , "otel-collector" )
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
// Wait for otel collector to turn ready.
err = try . GetRequest ( "http://" + s . otelCollectorIP + ":13133/" , 30 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
2018-01-25 14:00:05 +03:00
c . Assert ( err , checker . IsNil )
}
2024-01-08 11:10:06 +03:00
func ( s * TracingSuite ) TearDownTest ( c * check . C ) {
s . composeStop ( c , "tempo" )
}
2021-11-25 13:10:06 +03:00
2024-01-08 11:10:06 +03:00
func ( s * TracingSuite ) TestOpentelemetryBasic_HTTP ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/tracing/simple-opentelemetry.toml" , TracingTemplate {
2021-11-25 13:10:06 +03:00
WhoamiIP : s . whoamiIP ,
WhoamiPort : s . whoamiPort ,
2024-01-08 11:10:06 +03:00
IP : s . otelCollectorIP ,
IsHTTP : true ,
2018-01-25 14:00:05 +03:00
} )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-25 14:00:05 +03:00
2019-05-16 11:58:06 +03:00
// wait for traefik
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , time . Second , try . BodyContains ( "basic-auth" ) )
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
err = try . GetRequest ( "http://127.0.0.1:8000/basic" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
2018-01-25 14:00:05 +03:00
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
contains := [ ] map [ string ] string {
{
"batches.0.scopeSpans.0.scope.name" : "github.com/traefik/traefik" ,
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.0.name" : "EntryPoint" ,
"batches.0.scopeSpans.0.spans.0.kind" : "SPAN_KIND_SERVER" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue" : "GET" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue" : "web" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue" : "/basic" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue" : "200" ,
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.1.name" : "Router" ,
"batches.0.scopeSpans.0.spans.1.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue" : "router0@file" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service0@file" ,
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.2.name" : "Service" ,
"batches.0.scopeSpans.0.spans.2.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service0@file" ,
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.3.name" : "ReverseProxy" ,
"batches.0.scopeSpans.0.spans.3.kind" : "SPAN_KIND_CLIENT" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"url.scheme\").value.stringValue" : "http" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"http.response.status_code\").value.intValue" : "200" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"user_agent.original\").value.stringValue" : "Go-http-client/1.1" ,
} ,
}
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
checkTraceContent ( c , s . tempoIP , contains )
}
2021-11-25 13:10:06 +03:00
2024-01-08 11:10:06 +03:00
func ( s * TracingSuite ) TestOpentelemetryBasic_gRPC ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/tracing/simple-opentelemetry.toml" , TracingTemplate {
2021-11-25 13:10:06 +03:00
WhoamiIP : s . whoamiIP ,
2024-01-08 11:10:06 +03:00
WhoamiPort : s . whoamiPort ,
IP : s . otelCollectorIP ,
IsHTTP : false ,
2018-01-25 14:00:05 +03:00
} )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-25 14:00:05 +03:00
2019-05-16 11:58:06 +03:00
// wait for traefik
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , time . Second , try . BodyContains ( "basic-auth" ) )
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
err = try . GetRequest ( "http://127.0.0.1:8000/basic" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
2018-01-25 14:00:05 +03:00
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
contains := [ ] map [ string ] string {
{
"batches.0.scopeSpans.0.scope.name" : "github.com/traefik/traefik" ,
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.0.name" : "EntryPoint" ,
"batches.0.scopeSpans.0.spans.0.kind" : "SPAN_KIND_SERVER" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue" : "GET" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue" : "web" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue" : "/basic" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue" : "200" ,
2021-11-25 13:10:06 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.1.name" : "Router" ,
"batches.0.scopeSpans.0.spans.1.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue" : "router0@file" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service0@file" ,
2018-01-25 14:00:05 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.2.name" : "Service" ,
"batches.0.scopeSpans.0.spans.2.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service0@file" ,
2019-06-28 01:16:04 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.3.name" : "ReverseProxy" ,
"batches.0.scopeSpans.0.spans.3.kind" : "SPAN_KIND_CLIENT" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"url.scheme\").value.stringValue" : "http" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"http.response.status_code\").value.intValue" : "200" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"user_agent.original\").value.stringValue" : "Go-http-client/1.1" ,
} ,
}
2019-06-28 01:16:04 +03:00
2024-01-08 11:10:06 +03:00
checkTraceContent ( c , s . tempoIP , contains )
2019-06-28 01:16:04 +03:00
}
2024-01-08 11:10:06 +03:00
func ( s * TracingSuite ) TestOpentelemetryRateLimit ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/tracing/simple-opentelemetry.toml" , TracingTemplate {
WhoamiIP : s . whoamiIP ,
WhoamiPort : s . whoamiPort ,
IP : s . otelCollectorIP ,
2019-06-28 01:16:04 +03:00
} )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2019-06-28 01:16:04 +03:00
// wait for traefik
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , time . Second , try . BodyContains ( "basic-auth" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/ratelimit" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/ratelimit" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/ratelimit" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusTooManyRequests ) )
c . Assert ( err , checker . IsNil )
// sleep for 4 seconds to be certain the configured time period has elapsed
// then test another request and verify a 200 status code
time . Sleep ( 4 * time . Second )
err = try . GetRequest ( "http://127.0.0.1:8000/ratelimit" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
// continue requests at 3 second intervals to test the other rate limit time period
time . Sleep ( 3 * time . Second )
err = try . GetRequest ( "http://127.0.0.1:8000/ratelimit" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
time . Sleep ( 3 * time . Second )
err = try . GetRequest ( "http://127.0.0.1:8000/ratelimit" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/ratelimit" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusTooManyRequests ) )
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
contains := [ ] map [ string ] string {
{
"batches.0.scopeSpans.0.scope.name" : "github.com/traefik/traefik" ,
"batches.0.scopeSpans.0.spans.0.name" : "EntryPoint" ,
"batches.0.scopeSpans.0.spans.0.kind" : "SPAN_KIND_SERVER" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue" : "GET" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue" : "web" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue" : "/ratelimit" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue" : "200" ,
"batches.0.scopeSpans.0.spans.1.name" : "Router" ,
"batches.0.scopeSpans.0.spans.1.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue" : "router1@file" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service1@file" ,
"batches.0.scopeSpans.0.spans.2.name" : "Retry" ,
"batches.0.scopeSpans.0.spans.2.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
"batches.0.scopeSpans.0.spans.3.name" : "RateLimiter" ,
"batches.0.scopeSpans.0.spans.3.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "ratelimit-1@file" ,
"batches.0.scopeSpans.0.spans.4.name" : "Service" ,
"batches.0.scopeSpans.0.spans.4.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service1@file" ,
"batches.0.scopeSpans.0.spans.5.name" : "ReverseProxy" ,
"batches.0.scopeSpans.0.spans.5.kind" : "SPAN_KIND_CLIENT" ,
"batches.0.scopeSpans.0.spans.5.attributes.#(key=\"url.scheme\").value.stringValue" : "http" ,
"batches.0.scopeSpans.0.spans.5.attributes.#(key=\"http.response.status_code\").value.intValue" : "200" ,
"batches.0.scopeSpans.0.spans.5.attributes.#(key=\"user_agent.original\").value.stringValue" : "Go-http-client/1.1" ,
} ,
{
"batches.0.scopeSpans.0.scope.name" : "github.com/traefik/traefik" ,
"batches.0.scopeSpans.0.spans.0.name" : "EntryPoint" ,
"batches.0.scopeSpans.0.spans.0.kind" : "SPAN_KIND_SERVER" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue" : "GET" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue" : "web" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue" : "/ratelimit" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue" : "429" ,
"batches.0.scopeSpans.0.spans.1.name" : "Router" ,
"batches.0.scopeSpans.0.spans.1.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue" : "router1@file" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service1@file" ,
"batches.0.scopeSpans.0.spans.2.name" : "Retry" ,
"batches.0.scopeSpans.0.spans.2.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
"batches.0.scopeSpans.0.spans.3.name" : "RateLimiter" ,
"batches.0.scopeSpans.0.spans.3.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "ratelimit-1@file" ,
"batches.0.scopeSpans.0.spans.4.name" : "Retry" ,
"batches.0.scopeSpans.0.spans.4.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"http.resend_count\").value.intValue" : "1" ,
"batches.0.scopeSpans.0.spans.5.name" : "RateLimiter" ,
"batches.0.scopeSpans.0.spans.5.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.5.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "ratelimit-1@file" ,
"batches.0.scopeSpans.0.spans.6.name" : "Retry" ,
"batches.0.scopeSpans.0.spans.6.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.6.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
"batches.0.scopeSpans.0.spans.6.attributes.#(key=\"http.resend_count\").value.intValue" : "2" ,
"batches.0.scopeSpans.0.spans.7.name" : "RateLimiter" ,
"batches.0.scopeSpans.0.spans.7.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.7.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "ratelimit-1@file" ,
} ,
}
checkTraceContent ( c , s . tempoIP , contains )
2019-06-28 01:16:04 +03:00
}
2024-01-08 11:10:06 +03:00
func ( s * TracingSuite ) TestOpentelemetryRetry ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/tracing/simple-opentelemetry.toml" , TracingTemplate {
WhoamiIP : s . whoamiIP ,
WhoamiPort : 81 ,
IP : s . otelCollectorIP ,
2019-06-28 01:16:04 +03:00
} )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2019-06-28 01:16:04 +03:00
// wait for traefik
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , time . Second , try . BodyContains ( "basic-auth" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/retry" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusBadGateway ) )
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
contains := [ ] map [ string ] string {
{
"batches.0.scopeSpans.0.scope.name" : "github.com/traefik/traefik" ,
"batches.0.scopeSpans.0.spans.0.name" : "EntryPoint" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue" : "GET" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue" : "/retry" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue" : "502" ,
"batches.0.scopeSpans.0.spans.0.status.code" : "STATUS_CODE_ERROR" ,
"batches.0.scopeSpans.0.spans.1.name" : "Router" ,
"batches.0.scopeSpans.0.spans.1.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service2@file" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue" : "router2@file" ,
"batches.0.scopeSpans.0.spans.2.name" : "Retry" ,
"batches.0.scopeSpans.0.spans.2.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
"batches.0.scopeSpans.0.spans.3.name" : "Service" ,
"batches.0.scopeSpans.0.spans.3.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service2@file" ,
"batches.0.scopeSpans.0.spans.4.name" : "ReverseProxy" ,
"batches.0.scopeSpans.0.spans.4.kind" : "SPAN_KIND_CLIENT" ,
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"url.scheme\").value.stringValue" : "http" ,
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"http.response.status_code\").value.intValue" : "502" ,
"batches.0.scopeSpans.0.spans.4.attributes.#(key=\"user_agent.original\").value.stringValue" : "Go-http-client/1.1" ,
"batches.0.scopeSpans.0.spans.5.name" : "Retry" ,
"batches.0.scopeSpans.0.spans.5.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.5.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
"batches.0.scopeSpans.0.spans.5.attributes.#(key=\"http.resend_count\").value.intValue" : "1" ,
"batches.0.scopeSpans.0.spans.6.name" : "Service" ,
"batches.0.scopeSpans.0.spans.6.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.6.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service2@file" ,
"batches.0.scopeSpans.0.spans.7.name" : "ReverseProxy" ,
"batches.0.scopeSpans.0.spans.7.kind" : "SPAN_KIND_CLIENT" ,
"batches.0.scopeSpans.0.spans.7.attributes.#(key=\"url.scheme\").value.stringValue" : "http" ,
"batches.0.scopeSpans.0.spans.7.attributes.#(key=\"http.response.status_code\").value.intValue" : "502" ,
"batches.0.scopeSpans.0.spans.7.attributes.#(key=\"user_agent.original\").value.stringValue" : "Go-http-client/1.1" ,
"batches.0.scopeSpans.0.spans.8.name" : "Retry" ,
"batches.0.scopeSpans.0.spans.8.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.8.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
"batches.0.scopeSpans.0.spans.8.attributes.#(key=\"http.resend_count\").value.intValue" : "2" ,
"batches.0.scopeSpans.0.spans.9.name" : "Service" ,
"batches.0.scopeSpans.0.spans.9.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.9.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service2@file" ,
"batches.0.scopeSpans.0.spans.10.name" : "ReverseProxy" ,
"batches.0.scopeSpans.0.spans.10.kind" : "SPAN_KIND_CLIENT" ,
"batches.0.scopeSpans.0.spans.10.attributes.#(key=\"url.scheme\").value.stringValue" : "http" ,
"batches.0.scopeSpans.0.spans.10.attributes.#(key=\"http.response.status_code\").value.intValue" : "502" ,
"batches.0.scopeSpans.0.spans.10.attributes.#(key=\"user_agent.original\").value.stringValue" : "Go-http-client/1.1" ,
} ,
}
checkTraceContent ( c , s . tempoIP , contains )
2019-06-28 01:16:04 +03:00
}
2024-01-08 11:10:06 +03:00
func ( s * TracingSuite ) TestOpentelemetryAuth ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/tracing/simple-opentelemetry.toml" , TracingTemplate {
WhoamiIP : s . whoamiIP ,
WhoamiPort : s . whoamiPort ,
IP : s . otelCollectorIP ,
2019-10-15 17:30:06 +03:00
} )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2019-10-15 17:30:06 +03:00
// wait for traefik
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , time . Second , try . BodyContains ( "basic-auth" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/auth" , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusUnauthorized ) )
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
contains := [ ] map [ string ] string {
{
"batches.0.scopeSpans.0.scope.name" : "github.com/traefik/traefik" ,
2019-10-15 17:30:06 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.0.name" : "EntryPoint" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue" : "GET" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue" : "/auth" ,
"batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue" : "401" ,
2021-11-25 13:10:06 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.1.name" : "Router" ,
"batches.0.scopeSpans.0.spans.1.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue" : "router3@file" ,
"batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue" : "service3@file" ,
2019-06-28 01:16:04 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.2.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "retry@file" ,
2019-06-28 01:16:04 +03:00
2024-01-08 11:10:06 +03:00
"batches.0.scopeSpans.0.spans.3.kind" : "SPAN_KIND_INTERNAL" ,
"batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.middleware.name\").value.stringValue" : "basic-auth@file" ,
} ,
}
checkTraceContent ( c , s . tempoIP , contains )
}
func checkTraceContent ( c * check . C , tempoIP string , expectedJSON [ ] map [ string ] string ) {
baseURL , err := url . Parse ( "http://" + tempoIP + ":3200/api/search" )
2019-06-28 01:16:04 +03:00
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
req := & http . Request {
Method : http . MethodGet ,
URL : baseURL ,
}
// Wait for traces to be available.
time . Sleep ( 10 * time . Second )
resp , err := try . Response ( req , 5 * time . Second )
2019-06-28 01:16:04 +03:00
c . Assert ( err , checker . IsNil )
2024-01-08 11:10:06 +03:00
out := & TraceResponse { }
content , err := io . ReadAll ( resp . Body )
c . Assert ( err , checker . IsNil )
err = json . Unmarshal ( content , & out )
2018-01-25 14:00:05 +03:00
c . Assert ( err , checker . IsNil )
2019-07-15 15:52:04 +03:00
2024-01-08 11:10:06 +03:00
if len ( out . Traces ) == 0 {
c . Fatalf ( "expected at least one trace, got %d (%s)" , len ( out . Traces ) , string ( content ) )
}
2021-11-25 13:10:06 +03:00
2024-01-08 11:10:06 +03:00
var contents [ ] string
for _ , t := range out . Traces {
baseURL , err := url . Parse ( "http://" + tempoIP + ":3200/api/traces/" + t . TraceID )
c . Assert ( err , checker . IsNil )
2019-07-15 15:52:04 +03:00
2024-01-08 11:10:06 +03:00
req := & http . Request {
Method : http . MethodGet ,
URL : baseURL ,
}
2019-07-15 15:52:04 +03:00
2024-01-08 11:10:06 +03:00
resp , err := try . Response ( req , 5 * time . Second )
c . Assert ( err , checker . IsNil )
2019-07-15 15:52:04 +03:00
2024-01-08 11:10:06 +03:00
content , err := io . ReadAll ( resp . Body )
c . Assert ( err , checker . IsNil )
2019-07-15 15:52:04 +03:00
2024-01-08 11:10:06 +03:00
contents = append ( contents , string ( content ) )
}
for _ , expected := range expectedJSON {
containsAll ( c , expected , contents )
}
}
func containsAll ( c * check . C , expectedJSON map [ string ] string , contents [ ] string ) {
for k , v := range expectedJSON {
found := false
for _ , content := range contents {
if gjson . Get ( content , k ) . String ( ) == v {
found = true
break
}
}
if ! found {
c . Log ( "[" + strings . Join ( contents , "," ) + "]" )
c . Errorf ( "missing element: \nKey: %q\nValue: %q " , k , v )
}
}
}
// TraceResponse contains a list of traces.
type TraceResponse struct {
Traces [ ] Trace ` json:"traces" `
}
// Trace represents a simplified grafana tempo trace.
type Trace struct {
TraceID string ` json:"traceID" `
2019-07-15 15:52:04 +03:00
}