traefik/integration/tracing_test.go

499 lines
23 KiB
Go
Raw Normal View History

2018-01-25 11:00:05 +00:00
package integration
import (
2024-01-08 08:10:06 +00:00
"encoding/json"
"io"
2018-01-25 11:00:05 +00:00
"net/http"
2024-01-08 08:10:06 +00:00
"net/url"
2018-01-25 11:00:05 +00:00
"os"
2024-01-08 08:10:06 +00:00
"strings"
2018-01-25 11:00:05 +00:00
"time"
"github.com/go-check/check"
2024-01-08 08:10:06 +00:00
"github.com/tidwall/gjson"
2023-02-03 14:24:05 +00:00
"github.com/traefik/traefik/v3/integration/try"
2018-01-25 11:00:05 +00:00
checker "github.com/vdemeester/shakers"
)
type TracingSuite struct {
BaseSuite
2024-01-08 08:10:06 +00:00
whoamiIP string
whoamiPort int
tempoIP string
otelCollectorIP string
2018-01-25 11:00:05 +00:00
}
type TracingTemplate struct {
WhoamiIP string
WhoamiPort int
2019-10-15 14:30:06 +00:00
IP string
TraceContextHeaderName string
2024-01-08 08:10:06 +00:00
IsHTTP bool
2018-01-25 11:00:05 +00:00
}
func (s *TracingSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "tracing")
s.composeUp(c)
2024-01-08 08:10:06 +00:00
}
func (s *TracingSuite) SetUpTest(c *check.C) {
s.composeUp(c, "tempo", "otel-collector", "whoami")
2018-01-25 11:00:05 +00:00
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
s.whoamiPort = 80
2018-01-25 11:00:05 +00:00
2024-01-08 08:10:06 +00: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 11:00:05 +00:00
2024-01-08 08:10:06 +00: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 11:00:05 +00:00
c.Assert(err, checker.IsNil)
}
2024-01-08 08:10:06 +00:00
func (s *TracingSuite) TearDownTest(c *check.C) {
s.composeStop(c, "tempo")
}
2024-01-08 08:10:06 +00:00
func (s *TracingSuite) TestOpentelemetryBasic_HTTP(c *check.C) {
file := s.adaptFile(c, "fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
2024-01-08 08:10:06 +00:00
IP: s.otelCollectorIP,
IsHTTP: true,
2018-01-25 11:00:05 +00: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 07:32:03 +00:00
defer s.killCmd(cmd)
2018-01-25 11:00:05 +00: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 08:10:06 +00:00
err = try.GetRequest("http://127.0.0.1:8000/basic", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
2018-01-25 11:00:05 +00:00
c.Assert(err, checker.IsNil)
2024-01-08 08:10:06 +00:00
contains := []map[string]string{
{
"batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik",
2018-01-25 11:00:05 +00:00
2024-01-08 08:10:06 +00: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 11:00:05 +00:00
2024-01-08 08:10:06 +00: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 11:00:05 +00:00
2024-01-08 08:10:06 +00: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 11:00:05 +00:00
2024-01-08 08:10:06 +00: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 11:00:05 +00:00
2024-01-08 08:10:06 +00:00
checkTraceContent(c, s.tempoIP, contains)
}
2024-01-08 08:10:06 +00:00
func (s *TracingSuite) TestOpentelemetryBasic_gRPC(c *check.C) {
file := s.adaptFile(c, "fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{
WhoamiIP: s.whoamiIP,
2024-01-08 08:10:06 +00:00
WhoamiPort: s.whoamiPort,
IP: s.otelCollectorIP,
IsHTTP: false,
2018-01-25 11:00:05 +00: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 07:32:03 +00:00
defer s.killCmd(cmd)
2018-01-25 11:00:05 +00: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 08:10:06 +00:00
err = try.GetRequest("http://127.0.0.1:8000/basic", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
2018-01-25 11:00:05 +00:00
c.Assert(err, checker.IsNil)
2024-01-08 08:10:06 +00:00
contains := []map[string]string{
{
"batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik",
2018-01-25 11:00:05 +00:00
2024-01-08 08:10:06 +00: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",
2024-01-08 08:10:06 +00: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 11:00:05 +00:00
2024-01-08 08:10:06 +00: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-27 22:16:04 +00:00
2024-01-08 08:10:06 +00: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-27 22:16:04 +00:00
2024-01-08 08:10:06 +00:00
checkTraceContent(c, s.tempoIP, contains)
2019-06-27 22:16:04 +00:00
}
2024-01-08 08:10:06 +00: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-27 22:16:04 +00: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 07:32:03 +00:00
defer s.killCmd(cmd)
2019-06-27 22:16:04 +00: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 08:10:06 +00: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-27 22:16:04 +00:00
}
2024-01-08 08:10:06 +00: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-27 22:16:04 +00: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 07:32:03 +00:00
defer s.killCmd(cmd)
2019-06-27 22:16:04 +00: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 08:10:06 +00: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-27 22:16:04 +00:00
}
2024-01-08 08:10:06 +00: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 14:30:06 +00: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 07:32:03 +00:00
defer s.killCmd(cmd)
2019-10-15 14:30:06 +00: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 08:10:06 +00:00
contains := []map[string]string{
{
"batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik",
2019-10-15 14:30:06 +00:00
2024-01-08 08:10:06 +00: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",
2024-01-08 08:10:06 +00: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-27 22:16:04 +00:00
2024-01-08 08:10:06 +00: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-27 22:16:04 +00:00
2024-01-08 08:10:06 +00: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-27 22:16:04 +00:00
c.Assert(err, checker.IsNil)
2024-01-08 08:10:06 +00: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-27 22:16:04 +00:00
c.Assert(err, checker.IsNil)
2024-01-08 08:10:06 +00:00
out := &TraceResponse{}
content, err := io.ReadAll(resp.Body)
c.Assert(err, checker.IsNil)
err = json.Unmarshal(content, &out)
2018-01-25 11:00:05 +00:00
c.Assert(err, checker.IsNil)
2019-07-15 12:52:04 +00:00
2024-01-08 08:10:06 +00:00
if len(out.Traces) == 0 {
c.Fatalf("expected at least one trace, got %d (%s)", len(out.Traces), string(content))
}
2024-01-08 08:10:06 +00: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 12:52:04 +00:00
2024-01-08 08:10:06 +00:00
req := &http.Request{
Method: http.MethodGet,
URL: baseURL,
}
2019-07-15 12:52:04 +00:00
2024-01-08 08:10:06 +00:00
resp, err := try.Response(req, 5*time.Second)
c.Assert(err, checker.IsNil)
2019-07-15 12:52:04 +00:00
2024-01-08 08:10:06 +00:00
content, err := io.ReadAll(resp.Body)
c.Assert(err, checker.IsNil)
2019-07-15 12:52:04 +00:00
2024-01-08 08:10:06 +00: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 12:52:04 +00:00
}