From 513f41578d1c7c32b9d997e84cf85c6663a3dc13 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 16 Dec 2024 17:49:40 +0100 Subject: [PATCH] remove unused code --- .github/workflows/pull_request.yml | 3 +- examples/compose/compose_metrics_otel_test.go | 92 --- examples/compose/compose_metrics_test.go | 90 --- examples/compose/compose_suite_test.go | 13 - examples/compose/compose_test.go | 212 ------- examples/compose/configs/agent-config.river | 47 -- .../configs/instrumenter-config-traces.yml | 6 - examples/compose/configs/mimir-config.yaml | 47 -- examples/compose/configs/otelcol-config.yml | 26 - .../compose/configs/prometheus-config.yml | 13 - examples/compose/configs/tempo-config.yaml | 40 -- examples/compose/docker-compose-metrics.yml | 77 --- examples/compose/docker-compose-traces.yml | 82 --- examples/dockertest/README.md | 15 - ...ap_observability_endpoint_en_suite_test.go | 71 --- .../en_suite_provisioning_suite_test.go | 35 -- examples/dockertest/examples_suite_test.go | 13 - examples/dockertest/send_simple_trace_test.go | 90 --- ...le_trace_with_individual_endpoints_test.go | 136 ---- testhelpers/common/container_network.go | 58 -- testhelpers/common/host_port.go | 37 -- testhelpers/common/local_endpoint_address.go | 6 - testhelpers/common/network_protocols.go | 5 - .../local_observability_endpoint.go | 248 -------- .../local_observability_endpoint_test.go | 100 --- .../observability/observability_suite_test.go | 13 - .../local_otel_collector_endpoint.go | 484 -------------- .../local_otel_collector_endpoint_test.go | 174 ------ .../otel_collector_config_template.go | 44 -- .../otelcol-builder-manifest.yaml | 43 -- testhelpers/otelcollector/otelcol.dockerfile | 11 - .../otelcollector/otelcollector_suite_test.go | 13 - .../prometheus/local_prometheus_endpoint.go | 339 ---------- .../local_prometheus_endpoint_test.go | 64 -- .../prometheus/prometheus_config_template.go | 16 - .../prometheus/prometheus_suite_test.go | 13 - .../prometheus/responses/response_helpers.go | 28 - testhelpers/requests/http.go | 15 - testhelpers/tempo/local_tempo_endpoint.go | 543 ---------------- .../tempo/local_tempo_endpoint_test.go | 161 ----- .../tempo/responses/response_helpers.go | 45 -- testhelpers/tempo/tempo_config_template.go | 53 -- testhelpers/tempo/tempo_suite_test.go | 13 - testkit/.gitignore | 3 - testkit/Makefile | 6 - testkit/README.md | 27 - testkit/go.mod | 55 -- testkit/go.sum | 591 ------------------ testkit/internal/harness/traces_to_metrics.go | 56 -- testkit/internal/util/metrics.go | 13 - testkit/internal/util/noop_host.go | 21 - testkit/internal/util/traces.go | 39 -- testkit/servicegraph/metrics_test.go | 198 ------ .../servicegraph/servicegraph_suite_test.go | 13 - .../testdata/config_with_peer_attributes.yaml | 9 - .../5b584103c6fc5ddf423cb2fb6552d0f0.json | 4 - 56 files changed, 1 insertion(+), 4668 deletions(-) delete mode 100644 examples/compose/compose_metrics_otel_test.go delete mode 100644 examples/compose/compose_metrics_test.go delete mode 100644 examples/compose/compose_suite_test.go delete mode 100644 examples/compose/compose_test.go delete mode 100644 examples/compose/configs/agent-config.river delete mode 100644 examples/compose/configs/instrumenter-config-traces.yml delete mode 100644 examples/compose/configs/mimir-config.yaml delete mode 100644 examples/compose/configs/otelcol-config.yml delete mode 100644 examples/compose/configs/prometheus-config.yml delete mode 100644 examples/compose/configs/tempo-config.yaml delete mode 100644 examples/compose/docker-compose-metrics.yml delete mode 100644 examples/compose/docker-compose-traces.yml delete mode 100644 examples/dockertest/README.md delete mode 100644 examples/dockertest/en_suite_provisioning/bootstrap_observability_endpoint_en_suite_test.go delete mode 100644 examples/dockertest/en_suite_provisioning/en_suite_provisioning_suite_test.go delete mode 100644 examples/dockertest/examples_suite_test.go delete mode 100644 examples/dockertest/send_simple_trace_test.go delete mode 100644 examples/dockertest/send_simple_trace_with_individual_endpoints_test.go delete mode 100644 testhelpers/common/container_network.go delete mode 100644 testhelpers/common/host_port.go delete mode 100644 testhelpers/common/local_endpoint_address.go delete mode 100644 testhelpers/common/network_protocols.go delete mode 100644 testhelpers/observability/local_observability_endpoint.go delete mode 100644 testhelpers/observability/local_observability_endpoint_test.go delete mode 100644 testhelpers/observability/observability_suite_test.go delete mode 100644 testhelpers/otelcollector/local_otel_collector_endpoint.go delete mode 100644 testhelpers/otelcollector/local_otel_collector_endpoint_test.go delete mode 100644 testhelpers/otelcollector/otel_collector_config_template.go delete mode 100644 testhelpers/otelcollector/otelcol-builder-manifest.yaml delete mode 100644 testhelpers/otelcollector/otelcol.dockerfile delete mode 100644 testhelpers/otelcollector/otelcollector_suite_test.go delete mode 100644 testhelpers/prometheus/local_prometheus_endpoint.go delete mode 100644 testhelpers/prometheus/local_prometheus_endpoint_test.go delete mode 100644 testhelpers/prometheus/prometheus_config_template.go delete mode 100644 testhelpers/prometheus/prometheus_suite_test.go delete mode 100644 testhelpers/tempo/local_tempo_endpoint.go delete mode 100644 testhelpers/tempo/local_tempo_endpoint_test.go delete mode 100644 testhelpers/tempo/tempo_config_template.go delete mode 100644 testhelpers/tempo/tempo_suite_test.go delete mode 100644 testkit/.gitignore delete mode 100644 testkit/Makefile delete mode 100644 testkit/README.md delete mode 100644 testkit/go.mod delete mode 100644 testkit/go.sum delete mode 100644 testkit/internal/harness/traces_to_metrics.go delete mode 100644 testkit/internal/util/metrics.go delete mode 100644 testkit/internal/util/noop_host.go delete mode 100644 testkit/internal/util/traces.go delete mode 100644 testkit/servicegraph/metrics_test.go delete mode 100644 testkit/servicegraph/servicegraph_suite_test.go delete mode 100644 testkit/servicegraph/testdata/config_with_peer_attributes.yaml delete mode 100644 testkit/servicegraph/testdata/traces/5b584103c6fc5ddf423cb2fb6552d0f0.json diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 47e9c88..af7c346 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -17,5 +17,4 @@ jobs: with: go-version: 1.23 - name: test - # todo fix or remove tempo tests - run: go test $(go list ./... |grep -v examples |grep -v tempo) + run: go test $(go list ./...) diff --git a/examples/compose/compose_metrics_otel_test.go b/examples/compose/compose_metrics_otel_test.go deleted file mode 100644 index d21d85d..0000000 --- a/examples/compose/compose_metrics_otel_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package compose_test - -import ( - "context" - "github.com/grafana/oats/observability" - "github.com/grafana/oats/testhelpers/remote" - "net" - "path" - "time" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/grafana/oats/testhelpers/compose" - "github.com/grafana/oats/testhelpers/prometheus/responses" - "github.com/grafana/oats/testhelpers/requests" -) - -var _ = Describe("provisioning a local observability endpoint with Docker", Ordered, Label("docker", "integration", "slow"), func() { - var otelComposeEndpoint observability.Endpoint - - BeforeAll(func() { - var ctx = context.Background() - var startErr error - - otelComposeEndpoint = compose.NewEndpoint(path.Join(".", "docker-compose-metrics.yml"), remote.PortsConfig{PrometheusHTTPPort: 9090}, nil) - startErr = otelComposeEndpoint.Start(ctx) - Expect(startErr).ToNot(HaveOccurred(), "expected no error starting a local observability endpoint") - }) - - AfterAll(func() { - var ctx = context.Background() - var stopErr error - - if otelComposeEndpoint != nil { - stopErr = otelComposeEndpoint.Stop(ctx) - Expect(stopErr).ToNot(HaveOccurred(), "expected no error stopping the local observability endpoint") - } - }) - - // Traces generated by auto-instrumentation - Describe("observability.LocalEndpoint", func() { - It("can create metrics with auto-instrumentation", func() { - ctx := context.Background() - const apiCount = 3 - - // Run repeated /smoke APIs to ensure data is flowing from the application to Tempo - Eventually(ctx, func(g Gomega) { - err := requests.DoHTTPGet("http://localhost:8080/smoke", 200) - g.Expect(err).ToNot(HaveOccurred()) - - b, err := otelComposeEndpoint.RunPromQL(ctx, `http_server_duration_count{http_route="/smoke"}`) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(b)).Should(BeNumerically(">", 0)) - - pr, err := responses.ParseQueryOutput(b) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(pr)).Should(BeNumerically(">", 0)) - }).WithTimeout(30*time.Second).Should(Succeed(), "calling /smoke for 30 seconds should cause metrics in Prometheus") - - for i := 0; i < apiCount; i++ { - Expect(requests.DoHTTPGet("http://localhost:8080/greeting?delay=30ms&status=204", 204)).ShouldNot(HaveOccurred()) - } - - var pr []responses.Result - - Eventually(ctx, func(g Gomega) { - b, err := otelComposeEndpoint.RunPromQL(ctx, `http_server_duration_count{`+ - `http_method="GET",`+ - `http_status_code="204",`+ - `service_namespace="integration-test",`+ - `service_name="testserver",`+ - `http_route="/greeting"}`) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(b)).Should(BeNumerically(">", 0)) - - pr, err = responses.ParseQueryOutput(b) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(pr)).Should(BeNumerically(">", 0)) - }).WithTimeout(30*time.Second).Should(Succeed(), "metrics should appear in Prometheus with /greeting as http.target") - - Expect(responses.EnoughPromResults(pr)).ToNot(HaveOccurred()) - count, err := responses.TotalPromCount(pr) - Expect(err).ToNot(HaveOccurred()) - Expect(count).Should(Equal(apiCount)) - - res := pr[0] - addr := net.ParseIP(res.Metric["net_sock_peer_addr"]) - Expect(addr).ToNot(BeNil()) - }) - }) -}) diff --git a/examples/compose/compose_metrics_test.go b/examples/compose/compose_metrics_test.go deleted file mode 100644 index 4139ddc..0000000 --- a/examples/compose/compose_metrics_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package compose_test - -import ( - "context" - "github.com/grafana/oats/observability" - "github.com/grafana/oats/testhelpers/remote" - "path" - "time" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/grafana/oats/testhelpers/compose" - "github.com/grafana/oats/testhelpers/prometheus/responses" - "github.com/grafana/oats/testhelpers/requests" -) - -var _ = Describe("provisioning a local observability endpoint with Docker", Ordered, Label("docker", "integration", "slow"), func() { - var endpoint observability.Endpoint - - BeforeAll(func() { - var ctx = context.Background() - var startErr error - - endpoint = compose.NewEndpoint(path.Join(".", "docker-compose-traces.yml"), remote.PortsConfig{MimirHTTPPort: 9009}, nil) - startErr = endpoint.Start(ctx) - Expect(startErr).ToNot(HaveOccurred(), "expected no error starting a local observability endpoint") - }) - - AfterAll(func() { - var ctx = context.Background() - var stopErr error - - if endpoint != nil { - stopErr = endpoint.Stop(ctx) - Expect(stopErr).ToNot(HaveOccurred(), "expected no error stopping the local observability endpoint") - } - }) - - // Traces generated by auto-instrumentation - Describe("observability.LocalEndpoint", func() { - It("can create metrics with auto-instrumentation", func() { - ctx := context.Background() - const apiCount = 3 - - // Run repeated /smoke APIs to ensure data is flowing from the application to Tempo - Eventually(ctx, func(g Gomega) { - err := requests.DoHTTPGet("http://localhost:8080/smoke", 200) - g.Expect(err).ToNot(HaveOccurred()) - - b, err := endpoint.RunPromQL(ctx, `http_server_duration_count{http_route="/smoke"}`) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(b)).Should(BeNumerically(">", 0)) - - pr, err := responses.ParseQueryOutput(b) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(pr)).Should(BeNumerically(">", 0)) - }).WithTimeout(30*time.Second).Should(Succeed(), "calling /smoke for 30 seconds should cause metrics in Mimir") - - for i := 0; i < apiCount; i++ { - Expect(requests.DoHTTPGet("http://localhost:8080/greeting?delay=30ms&status=204", 204)).ShouldNot(HaveOccurred()) - } - - var pr []responses.Result - - Eventually(ctx, func(g Gomega) { - b, err := endpoint.RunPromQL(ctx, `http_server_duration_count{`+ - `http_method="GET",`+ - `http_status_code="204",`+ - `job="integration-test/testserver",`+ - `http_route="/greeting"}`) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(b)).Should(BeNumerically(">", 0)) - - pr, err = responses.ParseQueryOutput(b) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(pr)).Should(BeNumerically(">", 0)) - - count, err := responses.TotalPromCount(pr) - Expect(err).ToNot(HaveOccurred()) - Expect(count).Should(Equal(apiCount)) - }).WithTimeout(30*time.Second).Should(Succeed(), "metrics should appear in Mimir with /greeting as http.target") - - Expect(responses.EnoughPromResults(pr)).ToNot(HaveOccurred()) - count, err := responses.TotalPromCount(pr) - Expect(err).ToNot(HaveOccurred()) - Expect(count).Should(Equal(apiCount)) - }) - }) -}) diff --git a/examples/compose/compose_suite_test.go b/examples/compose/compose_suite_test.go deleted file mode 100644 index ec9c408..0000000 --- a/examples/compose/compose_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package compose_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestCompose(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Compose Suite") -} diff --git a/examples/compose/compose_test.go b/examples/compose/compose_test.go deleted file mode 100644 index 872aeca..0000000 --- a/examples/compose/compose_test.go +++ /dev/null @@ -1,212 +0,0 @@ -package compose_test - -import ( - "context" - "github.com/grafana/oats/observability" - "github.com/grafana/oats/testhelpers/remote" - "path" - "time" - - "go.opentelemetry.io/collector/pdata/pcommon" - "go.opentelemetry.io/collector/pdata/ptrace" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.17.0" - - "github.com/grafana/oats/testhelpers/compose" - "github.com/grafana/oats/testhelpers/requests" - "github.com/grafana/oats/testhelpers/tempo/responses" -) - -var _ = Describe("provisioning a local observability endpoint with Docker", Ordered, Label("docker", "integration", "slow"), func() { - var composeEndpoint observability.Endpoint - - BeforeAll(func() { - var ctx = context.Background() - var startErr error - - composeEndpoint = compose.NewEndpoint(path.Join(".", "docker-compose-traces.yml"), remote.PortsConfig{TracesGRPCPort: 4017, TempoHTTPPort: 3200}, nil) - startErr = composeEndpoint.Start(ctx) - Expect(startErr).ToNot(HaveOccurred(), "expected no error starting a local observability endpoint") - }) - - AfterAll(func() { - var ctx = context.Background() - var stopErr error - - if composeEndpoint != nil { - stopErr = composeEndpoint.Stop(ctx) - Expect(stopErr).ToNot(HaveOccurred(), "expected no error stopping the local observability endpoint") - } - }) - - // Traces generated by auto-instrumentation - Describe("observability.LocalEndpoint", func() { - It("can create traces with auto-instrumentation", func() { - ctx := context.Background() - - // Run repeated /smoke APIs to ensure data is flowing from the application to Tempo - Eventually(ctx, func(g Gomega) { - err := requests.DoHTTPGet("http://localhost:8080/smoke", 200) - g.Expect(err).ToNot(HaveOccurred()) - - b, err := composeEndpoint.SearchTags(ctx, map[string]string{"http.method": "GET"}) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(b)).Should(BeNumerically(">", 0)) - - sr, err := responses.ParseTempoSearchResult(b) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(sr.Traces)).Should(BeNumerically(">", 0)) - }).WithTimeout(30*time.Second).Should(Succeed(), "calling /smoke for 30 seconds should cause traces in Tempo") - - // Make a single /create-trace event, no need to loop, we know data is flowing by now - err := requests.DoHTTPGet("http://localhost:8080/create-trace?delay=30&response=200", 200) - Expect(err).ShouldNot(HaveOccurred()) - - var sr responses.TempoSearchResult - - // Loop until we find a /create-trace trace - Eventually(ctx, func(g Gomega) { - b, err := composeEndpoint.SearchTags(ctx, map[string]string{"http.target": "/create-trace"}) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(b)).Should(BeNumerically(">", 0)) - - sr, err = responses.ParseTempoSearchResult(b) - - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(sr.Traces)).Should(BeNumerically(">", 0)) - }).WithTimeout(30*time.Second).Should(Succeed(), "we should see a single /create-trace trace in Tempo after 30 seconds") - - Expect(sr).NotTo(BeNil()) - Expect(len(sr.Traces)).Should(BeNumerically(">=", 1)) - - tr := sr.Traces[0] - - traceBytes, err := composeEndpoint.GetTraceByID(ctx, tr.TraceID) - Expect(err).ToNot(HaveOccurred(), "we should find the traceID from the search tags") - Expect(len(traceBytes)).Should(BeNumerically(">", 0)) - - td, err := responses.ParseTraceDetails(traceBytes) - Expect(err).ToNot(HaveOccurred(), "we should be able to parse the GET trace by traceID API output") - - parents := responses.FindSpans(td, "GET /create-trace") - Expect(len(parents)).Should(Equal(1)) - parent := parents[0] - - Expect(parent.Kind()).To(Equal(ptrace.SpanKindServer)) - Expect(responses.TimeIsIncreasing(parent)).ToNot(HaveOccurred(), "the parent span duration must be a positive value") - - err = responses.AttributesMatch( - parent.Attributes(), - []responses.AttributeMatch{ - {Type: pcommon.ValueTypeStr, Key: "http.target", Value: "/create-trace"}, - {Type: pcommon.ValueTypeStr, Key: "http.route", Value: "/create-trace"}, - {Type: pcommon.ValueTypeStr, Key: "http.method", Value: "GET"}, - {Type: pcommon.ValueTypeInt, Key: "net.host.port", Value: "8080"}, - {Type: pcommon.ValueTypeInt, Key: "http.status_code", Value: "200"}, - {Type: pcommon.ValueTypeInt, Key: "http.request_content_length", Value: "0"}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "parent attributes must match") - - err = responses.AttributesExist( - parent.Attributes(), - []responses.AttributeMatch{ - {Type: pcommon.ValueTypeStr, Key: "net.host.name"}, - {Type: pcommon.ValueTypeStr, Key: "net.sock.peer.addr"}, - }, - ) - Expect(err).ToNot(HaveOccurred(), "parent host and peer attributes must exist") - - children := responses.ChildrenOf(td, parent.SpanID().String()) - Expect(len(children)).Should(Equal(2)) - - inQueue := false - processing := false - for _, c := range children { - Expect(c.Kind()).To(Equal(ptrace.SpanKindInternal)) - Expect(parent.SpanID()).To(Equal(c.ParentSpanID())) - Expect(responses.TimeIsIncreasing(c)).ToNot(HaveOccurred(), "the child span duration must be a positive value") - Expect(c.SpanID()).ToNot(Equal(c.ParentSpanID())) - Expect(parent.TraceID()).To(Equal(c.TraceID())) - Expect(c.Attributes().Len()).To(Equal(0)) // internal spans don't have the attributes set - - if c.Name() == "in queue" { - inQueue = true - } - - if c.Name() == "processing" { - processing = true - } - } - - Expect(inQueue).To(BeTrue(), "we must find an 'in queue' internal span") - Expect(processing).To(BeTrue(), "we must find a 'processing' internal span") - }) - }) - - // Here only to ensure we can actually directly use the TracerProvider - Describe("observability.LocalEndpoint", func() { - It("provides an OpenTelemetry TraceProvider for sending traces", func() { - ctx := context.Background() - - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - "", // use the SchemaURL from the default resource - semconv.ServiceName("LocalObservabilityEndpointExample"), - ), - ) - - Expect(err).ToNot(HaveOccurred(), "expected no error creating an OpenTelemetry resource") - - traceProvider, err := composeEndpoint.TracerProvider(ctx, r) - Expect(err).ToNot(HaveOccurred(), "expected no error getting a tracer provider from the local observability endpoint") - - Expect(traceProvider).ToNot(Equal(nil), "expected non-nil traceProvider") - - defer traceProvider.Shutdown(ctx) - - tracer := traceProvider.Tracer("LocalObservabilityEndpointExampleTracer") - - parentCtx, parentSpan := tracer.Start(ctx, "local-observability-endpoint-example-parent") - - const eventMessage = "taking a little siesta" - - // create a closure over the tracer, parent context, and event message - helloOtelExample := func() { - _, childSpan := tracer.Start(parentCtx, "hello-observability-example") - defer childSpan.End() - - childSpan.AddEvent(eventMessage) - - time.Sleep(250 * time.Millisecond) - } - - helloOtelExample() - parentSpan.End() - - parentSpanContext := parentSpan.SpanContext() - Expect(parentSpanContext.HasTraceID()).To(BeTrue(), "expected the parent local observability endpoint example span to have a valid TraceID") - - err = traceProvider.ForceFlush(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error flushing the trace provider") - - traceID := parentSpanContext.TraceID() - - var fetchedTrace []byte - - Eventually(ctx, func() error { - fetchedTrace, err = composeEndpoint.GetTraceByID(ctx, traceID.String()) - return err - }).WithTimeout(30 * time.Second).Should(BeNil()) - - Expect(err).ToNot(HaveOccurred(), "expected no error fetching the exported trace from the local observability endpoint") - - Expect(string(fetchedTrace)).ToNot(BeEmpty(), "expected a non empty response from the local observability endpoint when getting an exported trace by ID") - Expect(string(fetchedTrace)).To(ContainSubstring(eventMessage), "expected the event message to be contained in the returned trace") - }) - }) -}) diff --git a/examples/compose/configs/agent-config.river b/examples/compose/configs/agent-config.river deleted file mode 100644 index 1838ce9..0000000 --- a/examples/compose/configs/agent-config.river +++ /dev/null @@ -1,47 +0,0 @@ -logging { - level = "debug" - format = "logfmt" -} - -otelcol.receiver.otlp "default" { - grpc { - endpoint = "0.0.0.0:4017" - } - http { - endpoint = "0.0.0.0:4018" - } - - output { - metrics = [otelcol.processor.batch.default.input] - traces = [otelcol.processor.batch.default.input] - } -} - -otelcol.processor.batch "default" { - output { - metrics = [otelcol.exporter.prometheus.default.input] - traces = [otelcol.exporter.otlp.tempo.input] - } -} - -otelcol.exporter.prometheus "default" { - include_target_info = true - include_scope_info = true - forward_to = [prometheus.remote_write.mimir.receiver] -} - -prometheus.remote_write "mimir" { - endpoint { - url = "http://mimir:9009/api/v1/push" - } -} - -otelcol.exporter.otlp "tempo" { - client { - endpoint = "tempo:4317" - tls { - insecure = true - insecure_skip_verify = true - } - } -} diff --git a/examples/compose/configs/instrumenter-config-traces.yml b/examples/compose/configs/instrumenter-config-traces.yml deleted file mode 100644 index 3d62f70..0000000 --- a/examples/compose/configs/instrumenter-config-traces.yml +++ /dev/null @@ -1,6 +0,0 @@ -routes: - patterns: - - /create-trace - - /smoke - - /greeting - unmatch: path \ No newline at end of file diff --git a/examples/compose/configs/mimir-config.yaml b/examples/compose/configs/mimir-config.yaml deleted file mode 100644 index ca2111e..0000000 --- a/examples/compose/configs/mimir-config.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# Do not use this configuration in production. -# It is for demonstration purposes only. -multitenancy_enabled: false - -blocks_storage: - backend: filesystem - bucket_store: - sync_dir: /tmp/mimir/tsdb-sync - filesystem: - dir: /tmp/mimir/data/tsdb - tsdb: - dir: /tmp/mimir/tsdb - -compactor: - data_dir: /tmp/mimir/compactor - sharding_ring: - kvstore: - store: memberlist - -distributor: - ring: - instance_addr: 127.0.0.1 - kvstore: - store: memberlist - -ingester: - ring: - instance_addr: 127.0.0.1 - kvstore: - store: memberlist - replication_factor: 1 - -ruler_storage: - backend: local - local: - directory: /tmp/mimir/rules - -server: - http_listen_port: 9009 - log_level: error - -store_gateway: - sharding_ring: - replication_factor: 1 - -limits: - max_global_exemplars_per_user: 100000 diff --git a/examples/compose/configs/otelcol-config.yml b/examples/compose/configs/otelcol-config.yml deleted file mode 100644 index 32d73b2..0000000 --- a/examples/compose/configs/otelcol-config.yml +++ /dev/null @@ -1,26 +0,0 @@ -receivers: - otlp: - protocols: - grpc: - http: - cors: - allowed_origins: - - "http://*" - - "https://*" -exporters: - prometheus: - endpoint: "otelcol:9464" - resource_to_telemetry_conversion: - enabled: true - enable_open_metrics: true -processors: - batch: -service: - pipelines: - metrics: - receivers: [otlp] - processors: [batch] - exporters: [prometheus] -# telemetry: -# logs: -# level: debug \ No newline at end of file diff --git a/examples/compose/configs/prometheus-config.yml b/examples/compose/configs/prometheus-config.yml deleted file mode 100644 index cc4215c..0000000 --- a/examples/compose/configs/prometheus-config.yml +++ /dev/null @@ -1,13 +0,0 @@ -global: - evaluation_interval: 30s - scrape_interval: 5s -scrape_configs: - - job_name: otel - honor_labels: true - static_configs: - - targets: - - 'otelcol:9464' - - job_name: otel-collector - static_configs: - - targets: - - 'otelcol:8888' diff --git a/examples/compose/configs/tempo-config.yaml b/examples/compose/configs/tempo-config.yaml deleted file mode 100644 index 9d59089..0000000 --- a/examples/compose/configs/tempo-config.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# Do not use this configuration in production. -# It is for demonstration purposes only. -# metrics_generator_enabled: true -# search_enabled: true - -server: - http_listen_port: 3200 - -distributor: - receivers: - otlp: - protocols: - http: - grpc: - -metrics_generator: - ring: - kvstore: {} - processor: - service_graphs: {} - span_metrics: {} - registry: - external_labels: - source: tempo - storage: - path: /tmp/tempo/generator/wal - remote_write: - - url: http://mimir:9009/api/v1/push - send_exemplars: true - -storage: - trace: - backend: local - wal: - path: /tmp/tempo/wal - local: - path: /tmp/tempo/blocks - -overrides: - metrics_generator_processors: ["service-graphs", "span-metrics"] \ No newline at end of file diff --git a/examples/compose/docker-compose-metrics.yml b/examples/compose/docker-compose-metrics.yml deleted file mode 100644 index b6743e9..0000000 --- a/examples/compose/docker-compose-metrics.yml +++ /dev/null @@ -1,77 +0,0 @@ -version: '3.8' - -services: - # Go based test server - testserver: - image: grcevski/tests:gotestserver - container_name: hatest-testserver - ports: - - "8080:8080" - - "8081:8081" - - "8082:8082" - - "8083:8083" - - "50051:50051" - environment: - LOG_LEVEL: DEBUG - - # eBPF auto instrumenter - autoinstrumenter: - image: grafana/ebpf-autoinstrument:latest - command: - - /otelauto - - --config=/configs/instrumenter-config-traces.yml - volumes: - - ./configs/:/configs - - ./testoutput/run:/var/run/otelauto - container_name: hatest-autoinstrumenter - privileged: true # in some environments (not GH Pull Requests) you can set it to false and then cap_add: [ SYS_ADMIN ] - network_mode: "service:testserver" - pid: "service:testserver" - environment: - PRINT_TRACES: "true" - OPEN_PORT: "8080" - SERVICE_NAMESPACE: "integration-test" - METRICS_INTERVAL: "10ms" - BPF_BATCH_TIMEOUT: "10ms" - LOG_LEVEL: "DEBUG" - METRICS_REPORT_PEER: "true" - OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: "http://otelcol:4318/v1/metrics" - depends_on: - testserver: - condition: service_started - - # OpenTelemetry Collector for Metrics. For Traces, we use directly Jaeger - otelcol: - image: otel/opentelemetry-collector-contrib:0.83.0 - container_name: otel-col - deploy: - resources: - limits: - memory: 125M - restart: unless-stopped - command: [ "--config=/etc/otelcol-config/otelcol-config.yml" ] - volumes: - - ./configs/:/etc/otelcol-config - ports: - - "4317" # OTLP over gRPC receiver - - "4318" # OTLP over HTTP receiver - - "9464" # Prometheus exporter - - "8888" # metrics endpoint - depends_on: - autoinstrumenter: - condition: service_started - prometheus: - condition: service_started - - prometheus: - image: quay.io/prometheus/prometheus:v2.34.0 - container_name: prometheus - command: - - --config.file=/etc/prometheus/prometheus-config.yml - - --storage.tsdb.path=/tmp/prometheus - - --web.enable-lifecycle - - --web.route-prefix=/ - volumes: - - ./configs/:/etc/prometheus - ports: - - "9090:9090" \ No newline at end of file diff --git a/examples/compose/docker-compose-traces.yml b/examples/compose/docker-compose-traces.yml deleted file mode 100644 index 575c7ef..0000000 --- a/examples/compose/docker-compose-traces.yml +++ /dev/null @@ -1,82 +0,0 @@ -version: '3.8' - -services: - # Go based test server - testserver: - image: grcevski/tests:gotestserver - container_name: hatest-testserver - ports: - - "8080:8080" - - "8081:8081" - - "8082:8082" - - "8083:8083" - - "50051:50051" - environment: - LOG_LEVEL: DEBUG - - # eBPF auto instrumenter - autoinstrumenter: - image: grafana/ebpf-autoinstrument:latest - command: - - /otelauto - - --config=/configs/instrumenter-config-traces.yml - volumes: - - ./configs/:/configs - - ./testoutput/run:/var/run/otelauto - container_name: hatest-autoinstrumenter - privileged: true # in some environments (not GH Pull Requests) you can set it to false and then cap_add: [ SYS_ADMIN ] - network_mode: "service:testserver" - pid: "service:testserver" - environment: - PRINT_TRACES: "true" - OPEN_PORT: "8080" - SERVICE_NAMESPACE: "integration-test" - METRICS_INTERVAL: "10ms" - BPF_BATCH_TIMEOUT: "10ms" - LOG_LEVEL: "DEBUG" - OTEL_EXPORTER_OTLP_ENDPOINT: "http://agent:4018" - depends_on: - testserver: - condition: service_started - - # Agent - agent: - image: grafana/agent - container_name: hatest-agent - command: - - run - - /etc/agent/agent-config.river - volumes: - - ./configs/:/etc/agent - environment: - AGENT_MODE: "flow" - ports: - - "4017:4017" - - "4018:4018" - - # Tempo - tempo: - image: grafana/tempo - container_name: hatest-tempo - command: - - -config.file - - /etc/tempo/tempo-config.yaml - volumes: - - ./configs/:/etc/tempo - ports: - - "3200:3200" - - "4317:4317" - - "4318:4318" - - # Mimir -config.file=config-mimir.yaml -server.grpc-listen-port=9096 - mimir: - image: grafana/mimir - container_name: hatest-mimir - command: - - -config.file=/etc/mimir/mimir-config.yaml - - -server.grpc-listen-port=9096 - volumes: - - ./configs/:/etc/mimir - ports: - - "9009:9009" - - "9096:9096" diff --git a/examples/dockertest/README.md b/examples/dockertest/README.md deleted file mode 100644 index 35ae63f..0000000 --- a/examples/dockertest/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## dockertest - -Examples utilizing [dockertest][] to provision self contained telemetry pipelines for use in integration testing. - -[dockertest]: https://github.com/ory/dockertest - -## Goals - -1. Self contained, programmatic provisioning of [Tempo][], the [OpenTelemetry Collector][], and [Prometheus][] with [dockertest][]. -1. Straightforward support for externally provisioned observability endpoints. -1. Opportunity to learn how to stand up the services the Application Observability product suite depends on. - -[Tempo]: https://github.com/grafana/tempo -[OpenTelemetry Collector]: https://github.com/open-telemetry/opentelemetry-collector -[Prometheus]: https://github.com/prometheus/prometheus diff --git a/examples/dockertest/en_suite_provisioning/bootstrap_observability_endpoint_en_suite_test.go b/examples/dockertest/en_suite_provisioning/bootstrap_observability_endpoint_en_suite_test.go deleted file mode 100644 index ee05026..0000000 --- a/examples/dockertest/en_suite_provisioning/bootstrap_observability_endpoint_en_suite_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package en_suite_provisioning_test - -import ( - "context" - "time" - - "go.opentelemetry.io/otel/sdk/resource" - - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var _ = Describe("setting up the local observability endpoint inside the Ginkgo suite bootstrapping", func() { - It("hides the setup and teardown of the local observability endpoint", func() { - if localEndpoint == nil { - Skip("the local observability endpoint is nil?! bye!") - } - - ctx := context.Background() - - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - "", // use the SchemaURL from the default resource - semconv.ServiceName("LocalObservabilityEndpointExample"), - ), - ) - - Expect(err).ToNot(HaveOccurred(), "expected no error creating an OpenTelemetry resource") - - traceProvider, err := localEndpoint.TracerProvider(ctx, r) - Expect(err).ToNot(HaveOccurred(), "expected no error getting a tracer provider from the local observability endpoint") - - defer traceProvider.Shutdown(ctx) - - tracer := traceProvider.Tracer("LocalObservabilityEndpointExampleTracer") - - parentCtx, parentSpan := tracer.Start(ctx, "local-observability-endpoint-example-parent") - - const eventMessage = "taking a little siesta" - - // create a closure over the tracer, parent context, and event message - helloOtelExample := func() { - _, childSpan := tracer.Start(parentCtx, "hello-observability-example") - defer childSpan.End() - - childSpan.AddEvent(eventMessage) - - time.Sleep(250 * time.Millisecond) - } - - helloOtelExample() - parentSpan.End() - - parentSpanContext := parentSpan.SpanContext() - Expect(parentSpanContext.HasTraceID()).To(BeTrue(), "expected the parent local observability endpoint example span to have a valid TraceID") - - err = traceProvider.ForceFlush(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error flushing the trace provider") - - traceID := parentSpanContext.TraceID() - - fetchedTrace, err := localEndpoint.GetTraceByID(ctx, traceID.String()) - Expect(err).ToNot(HaveOccurred(), "expected no error fetching the exported trace from the local observability endpoint") - - Expect(string(fetchedTrace)).ToNot(BeEmpty(), "expected a non empty response from the local observability endpoint when getting an exported trace by ID") - Expect(string(fetchedTrace)).To(ContainSubstring(eventMessage), "expected the event message to be contained in the returned trace") - }) -}) diff --git a/examples/dockertest/en_suite_provisioning/en_suite_provisioning_suite_test.go b/examples/dockertest/en_suite_provisioning/en_suite_provisioning_suite_test.go deleted file mode 100644 index 625319d..0000000 --- a/examples/dockertest/en_suite_provisioning/en_suite_provisioning_suite_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package en_suite_provisioning_test - -import ( - "context" - "testing" - - impl "github.com/grafana/oats/testhelpers/observability" - - "github.com/grafana/oats/observability" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var localEndpoint observability.Endpoint - -var _ = BeforeSuite(func() { - var startCtx context.Context = context.Background() - - localEndpoint = impl.NewLocalEndpoint() - - DeferCleanup(func() { - var stopCtx context.Context = context.Background() - - if localEndpoint != nil { - Expect(localEndpoint.Stop(stopCtx)).To(Succeed(), "expected no error stopping the local observability endpoint") - } - }) - - Expect(localEndpoint.Start(startCtx)).To(Succeed(), "expected no error starting a local observability endpoint") -}) - -func TestEnSuiteProvisioning(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Ginkgo Bootstrap Provisioning Suite") -} diff --git a/examples/dockertest/examples_suite_test.go b/examples/dockertest/examples_suite_test.go deleted file mode 100644 index 4650af0..0000000 --- a/examples/dockertest/examples_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestExamples(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Examples Suite") -} diff --git a/examples/dockertest/send_simple_trace_test.go b/examples/dockertest/send_simple_trace_test.go deleted file mode 100644 index 378032a..0000000 --- a/examples/dockertest/send_simple_trace_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package examples_test - -import ( - "context" - "time" - - "go.opentelemetry.io/otel/sdk/resource" - - "github.com/grafana/oats/observability" - - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - impl "github.com/grafana/oats/testhelpers/observability" -) - -var localEndpoint observability.Endpoint - -var _ = Describe("provisioning a local observability endpoint with Docker", Ordered, Label("docker", "integration", "slow"), func() { - BeforeAll(func() { - var ctx context.Context = context.Background() - - localEndpoint = impl.NewLocalEndpoint() - Expect(localEndpoint.Start(ctx)).To(Succeed(), "expected no error starting a local observability endpoint") - }) - - AfterAll(func() { - var ctx context.Context = context.Background() - - if localEndpoint != nil { - Expect(localEndpoint.Stop(ctx)).To(Succeed(), "expected no error stopping the local observability endpoint") - } - }) - - Describe("observability.LocalEndpoint", func() { - It("provides an OpenTelemetry TraceProvider for sending traces", func() { - ctx := context.Background() - - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - "", // use the SchemaURL from the default resource - semconv.ServiceName("LocalObservabilityEndpointExample"), - ), - ) - - Expect(err).ToNot(HaveOccurred(), "expected no error creating an OpenTelemetry resource") - - traceProvider, err := localEndpoint.TracerProvider(ctx, r) - Expect(err).ToNot(HaveOccurred(), "expected no error getting a tracer provider from the local observability endpoint") - - defer traceProvider.Shutdown(ctx) - - tracer := traceProvider.Tracer("LocalObservabilityEndpointExampleTracer") - - parentCtx, parentSpan := tracer.Start(ctx, "local-observability-endpoint-example-parent") - - const eventMessage = "taking a little siesta" - - // create a closure over the tracer, parent context, and event message - helloOtelExample := func() { - _, childSpan := tracer.Start(parentCtx, "hello-observability-example") - defer childSpan.End() - - childSpan.AddEvent(eventMessage) - - time.Sleep(250 * time.Millisecond) - } - - helloOtelExample() - parentSpan.End() - - parentSpanContext := parentSpan.SpanContext() - Expect(parentSpanContext.HasTraceID()).To(BeTrue(), "expected the parent local observability endpoint example span to have a valid TraceID") - - err = traceProvider.ForceFlush(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error flushing the trace provider") - - traceID := parentSpanContext.TraceID() - - fetchedTrace, err := localEndpoint.GetTraceByID(ctx, traceID.String()) - Expect(err).ToNot(HaveOccurred(), "expected no error fetching the exported trace from the local observability endpoint") - - Expect(string(fetchedTrace)).ToNot(BeEmpty(), "expected a non empty response from the local observability endpoint when getting an exported trace by ID") - Expect(string(fetchedTrace)).To(ContainSubstring(eventMessage), "expected the event message to be contained in the returned trace") - }) - }) -}) diff --git a/examples/dockertest/send_simple_trace_with_individual_endpoints_test.go b/examples/dockertest/send_simple_trace_with_individual_endpoints_test.go deleted file mode 100644 index e8a9e28..0000000 --- a/examples/dockertest/send_simple_trace_with_individual_endpoints_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package examples_test - -import ( - "context" - "fmt" - "time" - - "github.com/google/uuid" - "github.com/grafana/oats/testhelpers/common" - "github.com/grafana/oats/testhelpers/otelcollector" - "github.com/grafana/oats/testhelpers/prometheus" - "github.com/grafana/oats/testhelpers/tempo" - "go.opentelemetry.io/otel/sdk/resource" - - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var localTempoEndpoint *tempo.LocalEndpoint -var localCollectorEndpoint *otelcollector.LocalEndpoint -var localPromEndpoint *prometheus.LocalEndpoint -var sharedNetworkName string - -var _ = Describe("sending a simple trace to Tempo through the OpenTelemetry Collector", Ordered, Serial, Label("docker", "integration", "slow", "example"), func() { - BeforeAll(func() { - ctx := context.Background() - - sharedNetworkUUID, err := uuid.NewRandom() - Expect(err).ToNot(HaveOccurred(), "expected no error creating a new UUID for the shared container network name") - - sharedNetworkName = fmt.Sprintf("ginkgoTest%s", sharedNetworkUUID.String()) - - _, err = common.ContainerNetwork(sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a shared container network") - - localPromEndpoint, err = prometheus.NewLocalEndpoint(ctx, sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Prometheus endpoint") - - promAddress, err := localPromEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting the local Prometheus endpoint") - - localTempoEndpoint, err = tempo.NewLocalEndpoint(ctx, sharedNetworkName, promAddress) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Tempo endpoint") - - _, err = localTempoEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting the local Tempo endpoint") - - traceEndpoint, err := localTempoEndpoint.OTLPTraceEndpoint(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error getting the Tempo trace ingestion endpoint") - - localCollectorEndpoint, err = otelcollector.NewLocalEndpoint(ctx, sharedNetworkName, traceEndpoint, promAddress) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local OpenTelemetry collector endpoint") - - _, err = localCollectorEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting the local OpenTelemetry collector endpoint") - }) - - AfterAll(func() { - var cleanupErr error - var ctx context.Context = context.Background() - - if localCollectorEndpoint != nil { - cleanupErr = localCollectorEndpoint.Stop(ctx) - Expect(cleanupErr).ToNot(HaveOccurred(), "expected no error stopping the local OpenTelemetry Collector endpoint") - } - - if localTempoEndpoint != nil { - cleanupErr = localTempoEndpoint.Stop(ctx) - Expect(cleanupErr).ToNot(HaveOccurred(), "expected no error stopping the local Tempo endpoint") - } - - if localPromEndpoint != nil { - cleanupErr = localPromEndpoint.Stop(ctx) - Expect(cleanupErr).ToNot(HaveOccurred(), "expected no error stopping the local Prometheus endpoint") - } - - if sharedNetworkName != "" { - cleanupErr = common.DestroyContainerNetwork(sharedNetworkName) - Expect(cleanupErr).ToNot(HaveOccurred(), "expected no error destroying the shared container network") - } - }) - - It("is possible to send traces to Tempo through the OpenTelemetry Collector", func() { - ctx := context.Background() - - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - "", // use the SchemaURL from the default resource - semconv.ServiceName("LocalOTelCollectorEndpointExample"), - ), - ) - - Expect(err).ToNot(HaveOccurred(), "expected no error creating an OpenTelemetry resource") - - traceProvider, err := localCollectorEndpoint.TracerProvider(ctx, r) - Expect(err).ToNot(HaveOccurred(), "expected no error getting a trace provider") - - defer traceProvider.Shutdown(ctx) - - tracer := traceProvider.Tracer("LocalOTelCollectorEndpointExampleTracer") - - parentCtx, parentSpan := tracer.Start(ctx, "local-otel-collector-endpoint-example-parent") - - const eventMessage = "taking a little siesta" - - // create a closure over the tracer, parent context, and event message - helloOtelExample := func() { - _, childSpan := tracer.Start(parentCtx, "hello-otel-example") - defer childSpan.End() - - childSpan.AddEvent(eventMessage) - - time.Sleep(250 * time.Millisecond) - } - - helloOtelExample() - parentSpan.End() - - parentSpanContext := parentSpan.SpanContext() - Expect(parentSpanContext.HasTraceID()).To(BeTrue(), "expected the parent local OpenTelemetry Collector endpoint example span to have a valid TraceID") - - err = traceProvider.ForceFlush(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error flushing the trace provider") - - traceID := parentSpanContext.TraceID() - - fetchedTrace, err := localTempoEndpoint.GetTraceByID(ctx, traceID.String()) - Expect(err).ToNot(HaveOccurred(), "expected no error fetching the exported trace from Tempo") - - Expect(string(fetchedTrace)).ToNot(BeEmpty(), "expected a non empty response from Tempo when getting an exported trace by ID") - Expect(string(fetchedTrace)).To(ContainSubstring(eventMessage), "expected the event message to be contained in the returned trace") - }) -}) diff --git a/testhelpers/common/container_network.go b/testhelpers/common/container_network.go deleted file mode 100644 index 68dc530..0000000 --- a/testhelpers/common/container_network.go +++ /dev/null @@ -1,58 +0,0 @@ -package common - -import ( - "sync" - - "github.com/ory/dockertest/v3" -) - -var networks map[string]*dockertest.Network -var mutex *sync.Mutex - -func init() { - networks = map[string]*dockertest.Network{} - mutex = &sync.Mutex{} -} - -func ContainerNetwork(networkName string) (*dockertest.Network, error) { - mutex.Lock() - defer mutex.Unlock() - - existingNetwork := networks[networkName] - if existingNetwork != nil { - return existingNetwork, nil - } - - pool, err := dockertest.NewPool("") - if err != nil { - return nil, err - } - - network, err := pool.CreateNetwork(networkName) - if err != nil { - return nil, err - } - - networks[networkName] = network - - return network, nil -} - -func DestroyContainerNetwork(networkName string) error { - mutex.Lock() - defer mutex.Unlock() - - existingNetwork := networks[networkName] - if existingNetwork == nil { - return nil - } - - err := existingNetwork.Close() - if err != nil { - return err - } - - delete(networks, networkName) - - return nil -} diff --git a/testhelpers/common/host_port.go b/testhelpers/common/host_port.go deleted file mode 100644 index e81610b..0000000 --- a/testhelpers/common/host_port.go +++ /dev/null @@ -1,37 +0,0 @@ -package common - -import ( - "fmt" - "math/rand" - "net" -) - -func HostTCPPort() (string, error) { - var selectedPort int - - for trials := 0; trials < 10000; trials++ { - trialPort := rand.Intn(65535) - if trialPort <= 1024 { - continue - } - - conn, connErr := net.Listen("tcp", fmt.Sprintf(":%d", trialPort)) - if connErr != nil { - continue - } - - closeErr := conn.Close() - if closeErr != nil { - continue - } - - selectedPort = trialPort - break - } - - if selectedPort == 0 { - return "", fmt.Errorf("could not find open unprivileged port after 10,000 attempts") - } - - return fmt.Sprintf("%d", selectedPort), nil -} diff --git a/testhelpers/common/local_endpoint_address.go b/testhelpers/common/local_endpoint_address.go deleted file mode 100644 index f9f4d31..0000000 --- a/testhelpers/common/local_endpoint_address.go +++ /dev/null @@ -1,6 +0,0 @@ -package common - -type LocalEndpointAddress struct { - HostEndpoint string - ContainerEndpoint string -} diff --git a/testhelpers/common/network_protocols.go b/testhelpers/common/network_protocols.go deleted file mode 100644 index fde4818..0000000 --- a/testhelpers/common/network_protocols.go +++ /dev/null @@ -1,5 +0,0 @@ -package common - -const ( - TCPSuffix = "/tcp" -) diff --git a/testhelpers/observability/local_observability_endpoint.go b/testhelpers/observability/local_observability_endpoint.go deleted file mode 100644 index 735c35d..0000000 --- a/testhelpers/observability/local_observability_endpoint.go +++ /dev/null @@ -1,248 +0,0 @@ -package observability - -import ( - "context" - "fmt" - "sync" - - "github.com/google/uuid" - "github.com/grafana/oats/observability" - "github.com/grafana/oats/testhelpers/common" - "github.com/grafana/oats/testhelpers/otelcollector" - "github.com/grafana/oats/testhelpers/prometheus" - "github.com/grafana/oats/testhelpers/tempo" - "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/otel/sdk/trace" -) - -func NewLocalEndpoint() *LocalEndpoint { - endpoint := &LocalEndpoint{ - mutex: &sync.Mutex{}, - } - - return endpoint -} - -var _ observability.Endpoint = &LocalEndpoint{} - -type LocalEndpoint struct { - mutex *sync.Mutex - stopped bool - - networkName string - tempoEndpoint *tempo.LocalEndpoint - prometheusEndpoint *prometheus.LocalEndpoint - otelCollectorEndpoint *otelcollector.LocalEndpoint -} - -func (e *LocalEndpoint) Start(ctx context.Context) error { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return ctx.Err() - } - - if e.networkName == "" { - sharedNetworkUUID, err := uuid.NewRandom() - if err != nil { - return err - } - - sharedNetworkName := fmt.Sprintf("ginkgoTest%s", sharedNetworkUUID.String()) - - _, err = common.ContainerNetwork(sharedNetworkName) - if err != nil { - return fmt.Errorf("getting shared container network: %s", err) - } - - e.networkName = sharedNetworkName - } - - promEndpoint, err := prometheus.NewLocalEndpoint(ctx, e.networkName) - if err != nil { - return fmt.Errorf("creating local Prometheus endpoint: %s", err) - } - - promEndpointAddress, err := promEndpoint.Start(ctx) - if err != nil { - return fmt.Errorf("starting local Prometheus endpoint: %s", err) - } - - tempoEndpoint, err := tempo.NewLocalEndpoint(ctx, e.networkName, promEndpointAddress) - if err != nil { - return fmt.Errorf("creating local Tempo endpoint: %s", err) - } - - _, err = tempoEndpoint.Start(ctx) - if err != nil { - _ = promEndpoint.Stop(ctx) - - return fmt.Errorf("starting local Tempo endpoint: %s", err) - } - - otlpTraceEndpoint, err := tempoEndpoint.OTLPTraceEndpoint(ctx) - if err != nil { - _ = promEndpoint.Stop(ctx) - _ = tempoEndpoint.Stop(ctx) - - return fmt.Errorf("getting OTLP trace endpoint from local Tempo endpoint: %s", err) - } - - collectorEndpoint, err := otelcollector.NewLocalEndpoint(ctx, e.networkName, otlpTraceEndpoint, promEndpointAddress) - if err != nil { - _ = promEndpoint.Stop(ctx) - _ = tempoEndpoint.Stop(ctx) - - return fmt.Errorf("creating a local OpenTelemetry Collector: %s", err) - } - - _, err = collectorEndpoint.Start(ctx) - if err != nil { - _ = promEndpoint.Stop(ctx) - _ = tempoEndpoint.Stop(ctx) - - return fmt.Errorf("starting local OpenTelemetry Collector: %s", err) - } - - e.tempoEndpoint = tempoEndpoint - e.prometheusEndpoint = promEndpoint - e.otelCollectorEndpoint = collectorEndpoint - - return nil -} - -func (e *LocalEndpoint) Stop(ctx context.Context) error { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return ctx.Err() - } - - if e.stopped { - return nil - } - - var stopErr error - - if e.otelCollectorEndpoint != nil { - stopErr = e.otelCollectorEndpoint.Stop(ctx) - if stopErr != nil { - return stopErr - } - - e.otelCollectorEndpoint = nil - } - - if e.prometheusEndpoint != nil { - stopErr = e.prometheusEndpoint.Stop(ctx) - if stopErr != nil { - return stopErr - } - - e.prometheusEndpoint = nil - } - - if e.tempoEndpoint != nil { - stopErr = e.tempoEndpoint.Stop(ctx) - if stopErr != nil { - return stopErr - } - - e.tempoEndpoint = nil - } - - e.stopped = true - - return nil -} - -func (e *LocalEndpoint) TracerProvider(ctx context.Context, r *resource.Resource) (*trace.TracerProvider, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.stopped { - return nil, fmt.Errorf("cannot return OpenTelemetry TraceProvider from stopped local observability endpoint") - } - - if e.otelCollectorEndpoint == nil { - return nil, fmt.Errorf("cannot return OpenTelemetry TraceProvider from nil OpenTelemetry Collector endpoint") - } - - return e.otelCollectorEndpoint.TracerProvider(ctx, r) -} - -func (e *LocalEndpoint) GetTraceByID(ctx context.Context, traceID string) ([]byte, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.tempoEndpoint == nil { - return nil, fmt.Errorf("cannot search for traces from nil Tempo endpoint") - } - - return e.tempoEndpoint.GetTraceByID(ctx, traceID) -} - -func (e *LocalEndpoint) SearchTags(ctx context.Context, tags map[string]string) ([]byte, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.tempoEndpoint == nil { - return nil, fmt.Errorf("cannot search for tags from nil Tempo endpoint") - } - - return e.tempoEndpoint.SearchTags(ctx, tags) -} - -func (e *LocalEndpoint) OTLPEndpointAddress(ctx context.Context) (*common.LocalEndpointAddress, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.otelCollectorEndpoint == nil { - return nil, fmt.Errorf("cannot return OpenTelemetry Endpoint from nil OpenTelemetry Collector endpoint") - } - - return e.otelCollectorEndpoint.OTLPEndpoint(ctx) -} - -func (e *LocalEndpoint) ContainerNetwork(ctx context.Context) (string, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return "", ctx.Err() - } - - if e.networkName == "" { - return "", fmt.Errorf("empty container network name") - } - - // Create the network if it does not exist - _, err := common.ContainerNetwork(e.networkName) - if err != nil { - return "", fmt.Errorf("getting, or creating container network: %s", err) - } - - return e.networkName, nil -} - -func (e *LocalEndpoint) RunPromQL(ctx context.Context, query string) ([]byte, error) { - return nil, nil -} diff --git a/testhelpers/observability/local_observability_endpoint_test.go b/testhelpers/observability/local_observability_endpoint_test.go deleted file mode 100644 index a2aa011..0000000 --- a/testhelpers/observability/local_observability_endpoint_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package observability_test - -import ( - "context" - "time" - - "go.opentelemetry.io/otel/sdk/resource" - - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/grafana/oats/testhelpers/observability" -) - -var localEndpoint *observability.LocalEndpoint - -var _ = Describe("provisioning a local observability endpoint with Docker", Ordered, Label("docker", "integration", "slow"), func() { - BeforeAll(func() { - var ctx context.Context = context.Background() - var startErr error - - localEndpoint = observability.NewLocalEndpoint() - startErr = localEndpoint.Start(ctx) - Expect(startErr).ToNot(HaveOccurred(), "expected no error starting a local observability endpoint") - }) - - AfterAll(func() { - var ctx context.Context = context.Background() - var stopErr error - - if localEndpoint != nil { - stopErr = localEndpoint.Stop(ctx) - Expect(stopErr).ToNot(HaveOccurred(), "expected no error stopping the local observability endpoint") - } - }) - - Describe("LocalEndpoint", func() { - It("provides an OpenTelemetry TraceProvider for sending traces", func() { - ctx := context.Background() - - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - "", // use the SchemaURL from the default resource - semconv.ServiceName("LocalObservabilityEndpointTest"), - ), - ) - - Expect(err).ToNot(HaveOccurred(), "expected no error creating an OpenTelemetry resource") - - traceProvider, err := localEndpoint.TracerProvider(ctx, r) - Expect(err).ToNot(HaveOccurred(), "expected no error getting a trace provider from the local observability endpoint") - - defer traceProvider.Shutdown(ctx) - - tracer := traceProvider.Tracer("LocalObservabilityEndpointTestTracer") - - parentCtx, parentSpan := tracer.Start(ctx, "local-observability-endpoint-test-parent") - - const eventMessage = "taking a little nickerchen" - - // create a closure over the tracer, parent context, and event message - helloOtelExample := func() { - _, childSpan := tracer.Start(parentCtx, "hello-observability-test") - defer childSpan.End() - - childSpan.AddEvent(eventMessage) - - time.Sleep(250 * time.Millisecond) - } - - helloOtelExample() - parentSpan.End() - - parentSpanContext := parentSpan.SpanContext() - Expect(parentSpanContext.HasTraceID()).To(BeTrue(), "expected the parent local observability endpoint example span to have a valid TraceID") - - err = traceProvider.ForceFlush(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error flushing the trace provider") - - traceID := parentSpanContext.TraceID() - - fetchedTrace, err := localEndpoint.GetTraceByID(ctx, traceID.String()) - Expect(err).ToNot(HaveOccurred(), "expected no error fetching the exported trace from the local observability endpoint") - - Expect(string(fetchedTrace)).ToNot(BeEmpty(), "expected a non empty response from the local observability endpoint when getting an exported trace by ID") - Expect(string(fetchedTrace)).To(ContainSubstring(eventMessage), "expected the event message to be contained in the returned trace") - }) - - XIt("provides something to send metrics", func() { - Fail("test not written") - }) - - XIt("provides something to send logs", func() { - Fail("test not written") - }) - }) -}) diff --git a/testhelpers/observability/observability_suite_test.go b/testhelpers/observability/observability_suite_test.go deleted file mode 100644 index f8f76ef..0000000 --- a/testhelpers/observability/observability_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package observability_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestObservability(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Observability Suite") -} diff --git a/testhelpers/otelcollector/local_otel_collector_endpoint.go b/testhelpers/otelcollector/local_otel_collector_endpoint.go deleted file mode 100644 index 12d064a..0000000 --- a/testhelpers/otelcollector/local_otel_collector_endpoint.go +++ /dev/null @@ -1,484 +0,0 @@ -package otelcollector - -import ( - "context" - "fmt" - "net/http" - "os" - "path/filepath" - "strings" - "sync" - "text/template" - - _ "embed" - - "github.com/google/uuid" - "github.com/grafana/oats/testhelpers/common" - "github.com/ory/dockertest/v3" - "github.com/ory/dockertest/v3/docker" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/otel/sdk/trace" - "google.golang.org/grpc" -) - -const ( - GRPCContainerPort = "4317/tcp" - HealthCheckContainerPort = "13133/tcp" -) - -//go:embed otelcol.dockerfile -var otelCollectorDockerfileBytes []byte - -//go:embed otelcol-builder-manifest.yaml -var builderManifestBytes []byte - -func NewLocalEndpoint(ctx context.Context, networkName string, traceEndpoint *common.LocalEndpointAddress, promEndpoint *common.LocalEndpointAddress) (*LocalEndpoint, error) { - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if traceEndpoint == nil { - return nil, fmt.Errorf("address for sending traces to cannot be nil") - } - - pool, err := dockertest.NewPool("") - if err != nil { - return nil, err - } - - err = pool.Client.Ping() - if err != nil { - return nil, fmt.Errorf("pinging Docker daemon: %s", err.Error()) - } - - fileExporterOutput, err := os.CreateTemp("", "file-exporter-output") - if err != nil { - return nil, err - } - - fileExporterOutputPath := fileExporterOutput.Name() - - err = fileExporterOutput.Close() - if err != nil { - return nil, err - } - - collectorConfig, err := os.CreateTemp("", "otel-collector-config") - if err != nil { - _ = os.Remove(fileExporterOutputPath) - - return nil, err - } - - configData := &ConfigTemplateData{ - TempoEndpoint: traceEndpoint.ContainerEndpoint, - PrometheusEndpoint: promEndpoint.ContainerEndpoint, - FileExporterOutputPath: "/etc/file-exporter-output.jsonl", - HealthCheckPort: strings.ReplaceAll(HealthCheckContainerPort, common.TCPSuffix, ""), - } - - configTemplate, err := template.New("otel-collector-config").Parse(ConfigTemplate) - if err != nil { - _ = collectorConfig.Close() - - _ = os.Remove(collectorConfig.Name()) - _ = os.Remove(fileExporterOutputPath) - - return nil, err - } - - err = configTemplate.Execute(collectorConfig, configData) - if err != nil { - _ = collectorConfig.Close() - - _ = os.Remove(collectorConfig.Name()) - _ = os.Remove(fileExporterOutputPath) - - return nil, err - } - - collectorConfigPath := collectorConfig.Name() - - err = collectorConfig.Close() - if err != nil { - _ = os.Remove(collectorConfig.Name()) - _ = os.Remove(fileExporterOutputPath) - - return nil, err - } - - endpoint := &LocalEndpoint{ - mutex: &sync.Mutex{}, - networkName: networkName, - traceEndpoint: traceEndpoint, - prometheusEndpoint: promEndpoint, - collectorConfigPath: collectorConfigPath, - fileExporterOutputPath: fileExporterOutputPath, - stopped: true, - } - - return endpoint, nil -} - -type LocalEndpoint struct { - mutex *sync.Mutex - stopped bool - - container *dockertest.Resource - networkName string - collectorConfigPath string - fileExporterOutputPath string - traceEndpoint *common.LocalEndpointAddress - prometheusEndpoint *common.LocalEndpointAddress -} - -func (e *LocalEndpoint) Start(ctx context.Context) (*common.LocalEndpointAddress, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.container != nil && e.networkName != "" { - existingContainerNetwork, getExistingNetworkErr := common.ContainerNetwork(e.networkName) - if getExistingNetworkErr != nil { - e.container.Close() - e.container = nil - - return nil, fmt.Errorf("getting container network:% s", getExistingNetworkErr) - } - - existingContainerNetworkIP := e.container.GetIPInNetwork(existingContainerNetwork) - if existingContainerNetworkIP == "" { - return nil, fmt.Errorf("got no IP for Tempo container on the shared container network") - } - - existingContainerPort := strings.ReplaceAll(GRPCContainerPort, common.TCPSuffix, "") - - existingContainerHostEndpoint := e.container.GetHostPort(GRPCContainerPort) - if existingContainerHostEndpoint == "" { - return nil, fmt.Errorf("got no host gRPC OpenTelemetry host endpoint for Tempo container") - } - - endpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: existingContainerHostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", existingContainerNetworkIP, existingContainerPort), - } - - return endpointAddress, nil - } - - resChan := make(chan *dockertest.Resource) - errsChan := make(chan error) - - var funcConfig struct { - traceEndpointAddress string - configPath string - fileExporterOutputPath string - networkName string - } - - funcConfig.traceEndpointAddress = e.traceEndpoint.HostEndpoint - funcConfig.configPath = e.collectorConfigPath - funcConfig.fileExporterOutputPath = e.fileExporterOutputPath - funcConfig.networkName = e.networkName - - go func() { - if ctx.Err() != nil { - // expect this error to be delivered in the select - return - } - - pool, createClientErr := dockertest.NewPool("") - if createClientErr != nil { - errsChan <- fmt.Errorf("creating a Docker client: %s", createClientErr) - return - } - - pingErr := pool.Client.Ping() - if pingErr != nil { - errsChan <- fmt.Errorf("pinging Docker daemon: %s", pingErr.Error()) - return - } - - conn, dialTraceEndpointErr := grpc.Dial(funcConfig.traceEndpointAddress, grpc.WithInsecure()) - if dialTraceEndpointErr != nil { - errsChan <- fmt.Errorf("dialing trace endpoint: %s which is assumed to be gRPC: %s", funcConfig.traceEndpointAddress, dialTraceEndpointErr) - return - } - - buildDir, createBuildDirErr := os.MkdirTemp("", "opentelemetry-collector-build") - if createBuildDirErr != nil { - errsChan <- fmt.Errorf("creating build context for OpenTelemetry Collector: %s", createBuildDirErr) - return - } - - defer os.RemoveAll(buildDir) - - dockerfilePath := filepath.Join(buildDir, "Dockerfile") - builderManifestPath := filepath.Join(buildDir, "otelcol-builder-manifest.yaml") - - writeDockerfileErr := os.WriteFile(dockerfilePath, otelCollectorDockerfileBytes, 0666) - if writeDockerfileErr != nil { - errsChan <- writeDockerfileErr - return - } - - writeBuilderManifestErr := os.WriteFile(builderManifestPath, builderManifestBytes, 0666) - if writeBuilderManifestErr != nil { - errsChan <- writeBuilderManifestErr - return - } - - traceEndpointCloseConnErr := conn.Close() - if traceEndpointCloseConnErr != nil { - errsChan <- traceEndpointCloseConnErr - return - } - - network, err := common.ContainerNetwork(funcConfig.networkName) - if err != nil { - errsChan <- fmt.Errorf("getting container network:% s", err) - return - } - - hostGRPCContainerPort, getPortErr := common.HostTCPPort() - if getPortErr != nil { - errsChan <- getPortErr - return - } - - hostHealthCheckContainerPort, getPortErr := common.HostTCPPort() - if getPortErr != nil { - errsChan <- getPortErr - return - } - - nameUUID, uuidErr := uuid.NewRandom() - if uuidErr != nil { - errsChan <- uuidErr - return - } - - containerName := fmt.Sprintf("otelcol-ginkgo%s", nameUUID.String()) - - options := &dockertest.RunOptions{ - Name: containerName, - Cmd: []string{"/otelcol", "--config=/etc/otel-collector.yaml"}, // attempting to specify the command manually causes otelcol to fail (╯°□°)╯︵ ┻━┻ - Networks: []*dockertest.Network{network}, - - Mounts: []string{ - fmt.Sprintf("%s:/etc/otel-collector.yaml:z", funcConfig.configPath), - fmt.Sprintf("%s:/etc/file-exporter-output.jsonl:z", funcConfig.fileExporterOutputPath), // we'd like this file to be available from the host after creating the volume - }, - - ExposedPorts: []string{ - GRPCContainerPort, - HealthCheckContainerPort, - }, - - // to update, look at the upstream DockerFile: https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol/Dockerfile - PortBindings: map[docker.Port][]docker.PortBinding{ - GRPCContainerPort: []docker.PortBinding{{HostPort: hostGRPCContainerPort}}, - HealthCheckContainerPort: []docker.PortBinding{{HostPort: hostHealthCheckContainerPort}}, - }, - } - - resource, runErr := pool.BuildAndRunWithOptions(dockerfilePath, options) - if runErr != nil { - errsChan <- fmt.Errorf("running container: %s", runErr.Error()) - return - } - - connectionErr := pool.Retry(func() error { - url := fmt.Sprintf("http://localhost:%s/health/status", resource.GetPort(HealthCheckContainerPort)) - - resp, getErr := http.Get(url) - if getErr != nil { - return getErr - } - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("expected HTTP status 200, but got: %d", resp.StatusCode) - } - - defer resp.Body.Close() - - return nil - }) - - if ctx.Err() != nil { - resource.Close() - // do not send the context error through the channel because we're going to check if the context is closed - return - } - - if connectionErr != nil { - resource.Close() - errsChan <- connectionErr - return - } - - resChan <- resource - return - }() - - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - - case containerResource := <-resChan: - containerNetwork, err := common.ContainerNetwork(e.networkName) - if err != nil { - containerResource.Close() - return nil, fmt.Errorf("getting container network:% s", err) - } - - containerNetworkIP := containerResource.GetIPInNetwork(containerNetwork) - if containerNetworkIP == "" { - containerResource.Close() - return nil, fmt.Errorf("got no IP for Tempo container on the container network") - } - - containerPort := strings.ReplaceAll(GRPCContainerPort, common.TCPSuffix, "") - - hostEndpoint := containerResource.GetHostPort(GRPCContainerPort) - if hostEndpoint == "" { - return nil, fmt.Errorf("got no host gRPC OpenTelemetry host endpoint for Tempo container") - } - - endpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: hostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", containerNetworkIP, containerPort), - } - - e.container = containerResource - e.stopped = false - - return endpointAddress, nil - - case startErr := <-errsChan: - return nil, startErr - } - } -} - -func (e *LocalEndpoint) Stop(ctx context.Context) error { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return ctx.Err() - } - - if e.stopped { - return nil - } - - if e.container != nil { - containerCloseErr := e.container.Close() - if containerCloseErr != nil { - return containerCloseErr - } - } - - err := os.Remove(e.fileExporterOutputPath) - if err != nil { - return err - } - - err = os.Remove(e.collectorConfigPath) - if err != nil { - return err - } - - e.container = nil - e.stopped = true - - return nil -} - -func (e *LocalEndpoint) TracerProvider(ctx context.Context, r *resource.Resource) (*trace.TracerProvider, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.stopped { - return nil, fmt.Errorf("refusing to return OpenTelemetry TracerProvider for stopped endpoint") - } - - if e.container == nil { - return nil, fmt.Errorf("cannot return OpenTelemetry TracerProvider with nil OpenTelemetry Collector container") - } - - containerPort := e.container.GetPort(GRPCContainerPort) - if containerPort == "" { - return nil, fmt.Errorf("got no container gRPC port for the OpenTelemetry Collector container") - } - - exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint(fmt.Sprintf("localhost:%s", containerPort))) - if err != nil { - return nil, err - } - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - traceProvider := trace.NewTracerProvider( - trace.WithBatcher(exporter), - trace.WithResource(r), - ) - - return traceProvider, nil -} - -func (e *LocalEndpoint) OTLPEndpoint(ctx context.Context) (*common.LocalEndpointAddress, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.stopped { - return nil, fmt.Errorf("refusing to return OTLP endpoint for stopped endpoint") - } - - if e.container == nil { - return nil, fmt.Errorf("cannot return trace endpoint with nil OpenTelemetry Collector container") - } - - containerNetwork, err := common.ContainerNetwork(e.networkName) - if err != nil { - return nil, fmt.Errorf("getting container network:% s", err) - } - - containerNetworkIP := e.container.GetIPInNetwork(containerNetwork) - if containerNetworkIP == "" { - return nil, fmt.Errorf("got no IP for Tempo container on the shared container network") - } - - containerPort := e.container.GetPort(GRPCContainerPort) - if containerPort == "" { - return nil, fmt.Errorf("got no container gRPC port for the OpenTelemetry Collector container") - } - - hostEndpoint := e.container.GetHostPort(GRPCContainerPort) - if hostEndpoint == "" { - return nil, fmt.Errorf("got no host gRPC OpenTelemetry host endpoint for OpenTelemetry Collector container") - } - - endpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: hostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", containerNetworkIP, containerPort), - } - - return endpointAddress, nil -} diff --git a/testhelpers/otelcollector/local_otel_collector_endpoint_test.go b/testhelpers/otelcollector/local_otel_collector_endpoint_test.go deleted file mode 100644 index 9a0e795..0000000 --- a/testhelpers/otelcollector/local_otel_collector_endpoint_test.go +++ /dev/null @@ -1,174 +0,0 @@ -package otelcollector_test - -import ( - "context" - "fmt" - "time" - - "github.com/google/uuid" - "github.com/grafana/oats/testhelpers/common" - "github.com/grafana/oats/testhelpers/prometheus" - "github.com/grafana/oats/testhelpers/tempo" - "go.opentelemetry.io/otel/sdk/resource" - "google.golang.org/grpc" - - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/grafana/oats/testhelpers/otelcollector" -) - -var _ = Describe("provisioning an OpenTelemetry Collector locally using Docker", Label("integration", "docker", "slow"), func() { - Describe("LocalEndpoint", func() { - It("can start a local OpenTelemetry Collector endpoint", func() { - ctx := context.Background() - - sharedNetworkUUID, err := uuid.NewRandom() - Expect(err).ToNot(HaveOccurred(), "expected no error creating a UUID for a shared container network") - - sharedNetworkName := fmt.Sprintf("ginkgoTest%s", sharedNetworkUUID.String()) - - _, err = common.ContainerNetwork(sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a shared container network") - - defer common.DestroyContainerNetwork(sharedNetworkName) - - promEndpoint, err := prometheus.NewLocalEndpoint(ctx, sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Prometheus endpoint") - - promEndpointAddress, err := promEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting the local Prometheus endpoint") - - defer promEndpoint.Stop(ctx) - - tempoEndpoint, err := tempo.NewLocalEndpoint(ctx, sharedNetworkName, promEndpointAddress) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Tempo endpoint") - - _, err = tempoEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting a local Tempo endpoint") - - defer tempoEndpoint.Stop(ctx) - - traceEndpoint, err := tempoEndpoint.OTLPTraceEndpoint(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error getting the endpoint for sending traces to Tempo") - - collectorEndpoint, err := otelcollector.NewLocalEndpoint(ctx, sharedNetworkName, traceEndpoint, promEndpointAddress) - Expect(err).ToNot(HaveOccurred(), "expeccted no error creating a local OpenTelemetry Collector endpoint") - - collectorAddress, err := collectorEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting a local OpenTelemetry Collector endpoint") - - defer collectorEndpoint.Stop(ctx) - - conn, err := grpc.Dial(collectorAddress.HostEndpoint, grpc.WithInsecure()) - Expect(err).ToNot(HaveOccurred(), "expected no error connecting to the gRPC endpoint of the OpenTelemetry Collector") - - err = conn.Close() - Expect(err).ToNot(HaveOccurred(), "expected no error closing the gRPC connection to the OpenTelemetry Collector") - }) - - It("provides an OpenTelemetry TracerProvider for sending trace data", func() { - ctx := context.Background() - - sharedNetworkUUID, err := uuid.NewRandom() - Expect(err).ToNot(HaveOccurred(), "expected no error creating a UUID for a shared container network") - - sharedNetworkName := fmt.Sprintf("ginkgoTest%s", sharedNetworkUUID.String()) - - _, err = common.ContainerNetwork(sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a shared container network") - - defer common.DestroyContainerNetwork(sharedNetworkName) - - promEndpoint, err := prometheus.NewLocalEndpoint(ctx, sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Prometheus endpoint") - - promEndpointAddress, err := promEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting the local Prometheus endpoint") - - defer promEndpoint.Stop(ctx) - - tempoEndpoint, err := tempo.NewLocalEndpoint(ctx, sharedNetworkName, promEndpointAddress) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Tempo endpoint") - - _, err = tempoEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting a local Tempo endpoint") - - defer tempoEndpoint.Stop(ctx) - - traceEndpoint, err := tempoEndpoint.OTLPTraceEndpoint(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error getting the endpoint for sending traces to Tempo") - - collectorEndpoint, err := otelcollector.NewLocalEndpoint(ctx, sharedNetworkName, traceEndpoint, promEndpointAddress) - Expect(err).ToNot(HaveOccurred(), "expeccted no error creating a local OpenTelemetry Collector endpoint") - - _, err = collectorEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting a local OpenTelemetry Collector endpoint") - - defer collectorEndpoint.Stop(ctx) - - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - "", // use the SchemaURL from the default resource - semconv.ServiceName("LocalOTelCollectorEndpointTest"), - ), - ) - - Expect(err).ToNot(HaveOccurred(), "expected no error creating an OpenTelemetry resource") - - traceProvider, err := collectorEndpoint.TracerProvider(ctx, r) - Expect(err).ToNot(HaveOccurred(), "expected no error getting a trace provider") - - defer traceProvider.Shutdown(ctx) - - tracer := traceProvider.Tracer("LocalOTelCollectorEndpointTestTracer") - - parentCtx, parentSpan := tracer.Start(ctx, "local-otel-collector-endpoint-test-parent") - - const eventMessage = "taking a little siesta" - - // create a closure over the tracer, parent context, and event message - helloOtel := func() { - _, childSpan := tracer.Start(parentCtx, "hello-otel") - defer childSpan.End() - - childSpan.AddEvent(eventMessage) - - time.Sleep(250 * time.Millisecond) - } - - helloOtel() - parentSpan.End() - - parentSpanContext := parentSpan.SpanContext() - Expect(parentSpanContext.HasTraceID()).To(BeTrue(), "expected the parent local OpenTelemetry Collector endpoint test span to have a valid TraceID") - - err = traceProvider.ForceFlush(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error flushing the trace provider") - - traceID := parentSpanContext.TraceID() - - fetchedTrace, err := tempoEndpoint.GetTraceByID(ctx, traceID.String()) - if err != nil { - fmt.Println("there was an error fetching the trace from Tempo, you have 60s to investigate.....") - time.Sleep(60 * time.Second) - } - - Expect(err).ToNot(HaveOccurred(), "expected no error fetching the exported trace from Tempo") - - Expect(string(fetchedTrace)).ToNot(BeEmpty(), "expected a non empty response from Tempo when getting an exported trace by ID") - Expect(string(fetchedTrace)).To(ContainSubstring(eventMessage), "expected the event message to be contained in the returned trace") - }) - - XIt("can be stopped", func() { - Fail("test not written") - }) - - XIt("tries to respect context cancellation", func() { - Fail("test not written") - }) - }) -}) diff --git a/testhelpers/otelcollector/otel_collector_config_template.go b/testhelpers/otelcollector/otel_collector_config_template.go deleted file mode 100644 index e249625..0000000 --- a/testhelpers/otelcollector/otel_collector_config_template.go +++ /dev/null @@ -1,44 +0,0 @@ -package otelcollector - -const ConfigTemplate = ` -receivers: - otlp: - protocols: - grpc: - -exporters: - otlp: - endpoint: {{ .TempoEndpoint }} - tls: - insecure: true - file: - path: {{ .FileExporterOutputPath }} - prometheusremotewrite: - endpoint: "http://{{- .PrometheusEndpoint -}}/api/v1/push" - tls: - insecure: true - -extensions: - health_check: - endpoint: 0.0.0.0:{{- .HealthCheckPort }} - path: "/health/status" - -service: - pipelines: - traces: - receivers: [otlp] - exporters: [otlp, file] - metrics: - receivers: [otlp] - exporters: [prometheusremotewrite] - - extensions: [health_check] - -` - -type ConfigTemplateData struct { - TempoEndpoint string - PrometheusEndpoint string - FileExporterOutputPath string - HealthCheckPort string -} diff --git a/testhelpers/otelcollector/otelcol-builder-manifest.yaml b/testhelpers/otelcollector/otelcol-builder-manifest.yaml deleted file mode 100644 index f04467d..0000000 --- a/testhelpers/otelcollector/otelcol-builder-manifest.yaml +++ /dev/null @@ -1,43 +0,0 @@ -dist: - module: github.com/open-telemetry/opentelemetry-collector-releases/core - name: otelcol - description: OpenTelemetry Collector - version: 0.66.0 - output_path: ./_build - otelcol_version: 0.66.0 - -receivers: - - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver v0.66.0 - -exporters: - - gomod: go.opentelemetry.io/collector/exporter/loggingexporter v0.66.0 - - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.66.0 - - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/jaegerexporter v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/kafkaexporter v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/opencensusexporter v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter v0.66.0 - -extensions: - - gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.66.0 - - gomod: go.opentelemetry.io/collector/extension/ballastextension v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/pprofextension v0.66.0 - -processors: - - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.66.0 - - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanprocessor v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.66.0 - - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/filterprocessor v0.66.0 diff --git a/testhelpers/otelcollector/otelcol.dockerfile b/testhelpers/otelcollector/otelcol.dockerfile deleted file mode 100644 index 3985187..0000000 --- a/testhelpers/otelcollector/otelcol.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM golang:1.19.12-bullseye AS builder - -WORKDIR /usr/bin/otelcol - -COPY otelcol-builder-manifest.yaml ./ -RUN go install go.opentelemetry.io/collector/cmd/builder@v0.66.0 -RUN builder --config=otelcol-builder-manifest.yaml - -FROM gcr.io/distroless/base:latest -COPY --from=builder /usr/bin/otelcol/_build/otelcol /otelcol -ENTRYPOINT ["/otelcol"] diff --git a/testhelpers/otelcollector/otelcollector_suite_test.go b/testhelpers/otelcollector/otelcollector_suite_test.go deleted file mode 100644 index 7bd8677..0000000 --- a/testhelpers/otelcollector/otelcollector_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package otelcollector_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestOtelcollector(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Otelcollector Suite") -} diff --git a/testhelpers/prometheus/local_prometheus_endpoint.go b/testhelpers/prometheus/local_prometheus_endpoint.go deleted file mode 100644 index 10bf1ed..0000000 --- a/testhelpers/prometheus/local_prometheus_endpoint.go +++ /dev/null @@ -1,339 +0,0 @@ -package prometheus - -import ( - "context" - "fmt" - "net/http" - "os" - "os/user" - "strings" - "sync" - "text/template" - - _ "embed" - - "github.com/grafana/oats/testhelpers/common" - "github.com/ory/dockertest/v3" - "github.com/ory/dockertest/v3/docker" -) - -const ( - ContainerPort = "9090/tcp" -) - -func NewLocalEndpoint(ctx context.Context, networkName string) (*LocalEndpoint, error) { - if ctx.Err() != nil { - return nil, ctx.Err() - } - - pool, err := dockertest.NewPool("") - if err != nil { - return nil, err - } - - err = pool.Client.Ping() - if err != nil { - return nil, fmt.Errorf("pinging Docker daemon: %s", err.Error()) - } - - promDataDir, err := os.MkdirTemp("", "prom-data") - if err != nil { - return nil, err - } - - promConfigFile, err := os.CreateTemp("", "prom-config") - if err != nil { - return nil, err - } - - configData := &ConfigTemplateData{ - ContainerPort: strings.ReplaceAll(ContainerPort, common.TCPSuffix, ""), - } - - configTemplate, err := template.New("prom-config").Parse(ConfigTemplate) - if err != nil { - _ = promConfigFile.Close() - _ = os.Remove(promConfigFile.Name()) - - return nil, err - } - - err = configTemplate.Execute(promConfigFile, configData) - if err != nil { - _ = promConfigFile.Close() - _ = os.Remove(promConfigFile.Name()) - - return nil, err - } - - promConfigPath := promConfigFile.Name() - - err = promConfigFile.Close() - if err != nil { - _ = os.Remove(promConfigFile.Name()) - - return nil, err - } - - endpoint := &LocalEndpoint{ - mutex: &sync.Mutex{}, - networkName: networkName, - configPath: promConfigPath, - dataDir: promDataDir, - stopped: true, - } - - return endpoint, nil -} - -type LocalEndpoint struct { - mutex *sync.Mutex - - container *dockertest.Resource - networkName string - - tempoEndpoint *common.LocalEndpointAddress - - configPath string - dataDir string - - stopped bool -} - -func (e *LocalEndpoint) Start(ctx context.Context) (*common.LocalEndpointAddress, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.container != nil && e.networkName != "" { - existingContainerNetwork, getExistingNetworkErr := common.ContainerNetwork(e.networkName) - if getExistingNetworkErr != nil { - return nil, fmt.Errorf("getting container network:% s", getExistingNetworkErr) - } - - existingContainerNetworkIP := e.container.GetIPInNetwork(existingContainerNetwork) - if existingContainerNetworkIP == "" { - return nil, fmt.Errorf("got no IP for Prometheus container on the container network") - } - - existingContainerPort := strings.ReplaceAll(ContainerPort, common.TCPSuffix, "") - - existingContainerHostEndpoint := e.container.GetHostPort(ContainerPort) - if existingContainerHostEndpoint == "" { - return nil, fmt.Errorf("got no host endpoint for Prometheus container") - } - - existingEndpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: existingContainerHostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", existingContainerNetworkIP, existingContainerPort), - } - - return existingEndpointAddress, nil - } - - resChan := make(chan *dockertest.Resource) - errsChan := make(chan error) - - var funcConfig struct { - configPath string - networkName string - dataDir string - } - - funcConfig.configPath = e.configPath - funcConfig.dataDir = e.dataDir - funcConfig.networkName = e.networkName - - go func(parentCtx context.Context) { - if ctx.Err() != nil { - // expect this error to be delivered in the select - return - } - - pool, createClientErr := dockertest.NewPool("") - if createClientErr != nil { - errsChan <- fmt.Errorf("creating a Docker client: %s", createClientErr) - return - } - - pingErr := pool.Client.Ping() - if pingErr != nil { - errsChan <- fmt.Errorf("connecting to Docker daemon: %s", pingErr) - return - } - - network, getNetworkErr := common.ContainerNetwork(funcConfig.networkName) - if getNetworkErr != nil { - errsChan <- fmt.Errorf("getting container network: %s", getNetworkErr) - return - } - - currentUser, getCurrentUserErr := user.Current() - if getCurrentUserErr != nil { - errsChan <- fmt.Errorf("getting current user: %s", getCurrentUserErr) - return - } - - promHostPort, getPortErr := common.HostTCPPort() - if getPortErr != nil { - errsChan <- getPortErr - return - } - - options := &dockertest.RunOptions{ - Repository: "prom/prometheus", - Tag: "latest", - Cmd: []string{ - "--config.file=/etc/prometheus.yaml", - "--storage.tsdb.path=/tmp/prometheus", - "--web.enable-admin-api", - "--web.enable-remote-write-receiver", - "--enable-feature=exemplar-storage", - }, - - User: fmt.Sprintf("%s:%s", currentUser.Uid, currentUser.Gid), - Networks: []*dockertest.Network{network}, - - Mounts: []string{ - fmt.Sprintf("%s:/etc/prometheus.yaml:z", funcConfig.configPath), - fmt.Sprintf("%s:/tmp/prometheus:z", funcConfig.dataDir), - }, - - ExposedPorts: []string{ - ContainerPort, - }, - - PortBindings: map[docker.Port][]docker.PortBinding{ - ContainerPort: []docker.PortBinding{{HostPort: promHostPort}}, - }, - } - - resource, runErr := pool.RunWithOptions(options) - if runErr != nil { - errsChan <- fmt.Errorf("running container: %s", runErr.Error()) - return - } - - connectionErr := pool.Retry(func() error { - url := fmt.Sprintf("http://localhost:%s/-/healthy", resource.GetPort(ContainerPort)) - - resp, getErr := http.Get(url) - if getErr != nil { - return getErr - } - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("expected HTTP status 200, but got: %d", resp.StatusCode) - } - - defer resp.Body.Close() - - return nil - }) - - if ctx.Err() != nil { - resource.Close() - // do not send the context error through the channel because we're going to check if the context is closed - return - } - - if connectionErr != nil { - resource.Close() - - errsChan <- connectionErr - return - } - - resChan <- resource - return - }(ctx) - - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - - case containerResource := <-resChan: - containerNetwork, err := common.ContainerNetwork(e.networkName) - if err != nil { - containerResource.Close() - return nil, fmt.Errorf("getting container network:% s", err) - } - - containerNetworkIP := containerResource.GetIPInNetwork(containerNetwork) - if containerNetworkIP == "" { - containerResource.Close() - return nil, fmt.Errorf("got no IP for Tempo container on the shared container network") - } - - containerPort := strings.ReplaceAll(ContainerPort, common.TCPSuffix, "") - - hostEndpoint := containerResource.GetHostPort(ContainerPort) - if hostEndpoint == "" { - return nil, fmt.Errorf("got no host endpoint for HTTP Tempo API of container") - } - - endpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: hostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", containerNetworkIP, containerPort), - } - - e.container = containerResource - e.stopped = false - - return endpointAddress, nil - - case startErr := <-errsChan: - return nil, startErr - } - } -} - -func (e *LocalEndpoint) Stop(ctx context.Context) error { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return ctx.Err() - } - - if e.stopped { - return nil - } - - if e.container != nil { - containerCloseErr := e.container.Close() - if containerCloseErr != nil { - return containerCloseErr - } - } - - err := os.RemoveAll(e.dataDir) - if err != nil { - return err - } - - err = os.Remove(e.configPath) - if err != nil { - return err - } - - e.container = nil - e.stopped = true - - return nil -} - -func (e *LocalEndpoint) PromClient(ctx context.Context) (any, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - return nil, nil -} diff --git a/testhelpers/prometheus/local_prometheus_endpoint_test.go b/testhelpers/prometheus/local_prometheus_endpoint_test.go deleted file mode 100644 index 9383b41..0000000 --- a/testhelpers/prometheus/local_prometheus_endpoint_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package prometheus_test - -import ( - "context" - "fmt" - "io" - "net/http" - - "github.com/google/uuid" - "github.com/grafana/oats/testhelpers/common" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/grafana/oats/testhelpers/prometheus" -) - -var _ = Describe("provisioning a LocalPrometheusEndpoint with Docker", func() { - It("starts a Prometheus endpoint locally", func() { - ctx := context.Background() - - sharedNetworkUUID, err := uuid.NewRandom() - Expect(err).ToNot(HaveOccurred(), "expected no error creating a UUID for a shared container network") - - sharedNetworkName := fmt.Sprintf("ginkgoTest%s", sharedNetworkUUID.String()) - - _, err = common.ContainerNetwork(sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a shared container network") - - defer common.DestroyContainerNetwork(sharedNetworkName) - - endpoint, err := prometheus.NewLocalEndpoint(ctx, sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Prometheus endpoint") - - endpointURL, err := endpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting a local Prometheus endpoint") - - defer endpoint.Stop(ctx) - - resp, err := http.Get(fmt.Sprintf("http://%s/-/healthy", endpointURL.HostEndpoint)) - Expect(err).ToNot(HaveOccurred(), "expected no error getting the status of the local Tempo endpoint") - - defer resp.Body.Close() - - Expect(resp.StatusCode).To(Equal(http.StatusOK), "expected 200 OX from the local Prometheus endpoint") - - respBytes, err := io.ReadAll(resp.Body) - Expect(err).ToNot(HaveOccurred(), "expected no error reading a Tempo status response") - - Expect(string(respBytes)).To(ContainSubstring("Prometheus Server is Healthy."), "expected a healthy response from Promtheus") - }) - - XIt("provides a prometheus client", func() { - - }) - - XIt("can be stopped", func() { - - }) - - XIt("attempts to respect context cancellation", func() { - - }) -}) diff --git a/testhelpers/prometheus/prometheus_config_template.go b/testhelpers/prometheus/prometheus_config_template.go deleted file mode 100644 index c0585fc..0000000 --- a/testhelpers/prometheus/prometheus_config_template.go +++ /dev/null @@ -1,16 +0,0 @@ -package prometheus - -const ConfigTemplate = ` -global: - scrape_interval: 1s - evaluation_interval: 1s - -scrape_configs: - - job_name: 'prometheus' - static_configs: - - targets: [ 'localhost:{{- .ContainerPort -}}' ] -` - -type ConfigTemplateData struct { - ContainerPort string -} diff --git a/testhelpers/prometheus/prometheus_suite_test.go b/testhelpers/prometheus/prometheus_suite_test.go deleted file mode 100644 index 46df2ee..0000000 --- a/testhelpers/prometheus/prometheus_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package prometheus_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestPrometheus(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Prometheus Suite") -} diff --git a/testhelpers/prometheus/responses/response_helpers.go b/testhelpers/prometheus/responses/response_helpers.go index 4f17b68..5a541f3 100644 --- a/testhelpers/prometheus/responses/response_helpers.go +++ b/testhelpers/prometheus/responses/response_helpers.go @@ -3,7 +3,6 @@ package responses import ( "encoding/json" "fmt" - "strconv" ) func ParseQueryOutput(body []byte) ([]Result, error) { @@ -14,30 +13,3 @@ func ParseQueryOutput(body []byte) ([]Result, error) { return qr.Data.Result, nil } - -func EnoughPromResults(results []Result) error { - if len(results) < 1 { - return fmt.Errorf("prometheus query results must have at least 1 element") - } - - return nil -} - -func TotalPromCount(results []Result) (int, error) { - total := 0 - for _, res := range results { - if len(res.Value) < 2 { - return 0, fmt.Errorf("result %v must have at least 2 elements", res) - } - - val, err := strconv.Atoi(res.Value[1].(string)) - - if err != nil { - return 0, err - } - - total += val - } - - return total, nil -} diff --git a/testhelpers/requests/http.go b/testhelpers/requests/http.go index 477b14f..63f2365 100644 --- a/testhelpers/requests/http.go +++ b/testhelpers/requests/http.go @@ -1,7 +1,6 @@ package requests import ( - "bytes" "crypto/tls" "fmt" "net/http" @@ -12,10 +11,6 @@ var tr = &http.Transport{ } var testHTTPClient = &http.Client{Transport: tr} -func DisableKeepAlives(disableKeepAlives bool) { - testHTTPClient.Transport.(*http.Transport).DisableKeepAlives = disableKeepAlives -} - func doRequest(req *http.Request, statusCode int) error { req.Header.Set("Content-Type", "application/json") @@ -32,16 +27,6 @@ func doRequest(req *http.Request, statusCode int) error { return nil } -func DoHTTPPost(url string, statusCode int, jsonBody []byte) error { - req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(jsonBody)) - - if err != nil { - return err - } - - return doRequest(req, statusCode) -} - func DoHTTPGet(url string, statusCode int) error { req, err := http.NewRequest(http.MethodGet, url, nil) diff --git a/testhelpers/tempo/local_tempo_endpoint.go b/testhelpers/tempo/local_tempo_endpoint.go deleted file mode 100644 index 81e7883..0000000 --- a/testhelpers/tempo/local_tempo_endpoint.go +++ /dev/null @@ -1,543 +0,0 @@ -package tempo - -import ( - "context" - "fmt" - "io" - "net/http" - "net/url" - "os" - "os/user" - "strconv" - "strings" - "sync" - "text/template" - - "github.com/grafana/oats/testhelpers/common" - "github.com/ory/dockertest/v3" - "github.com/ory/dockertest/v3/docker" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/otel/sdk/trace" -) - -const ( - HTTPContainerPort = "3200/tcp" - GRPCContainerPort = "9095/tcp" - GRPCOtelContainerPort = "4317/tcp" - HTTPOtelContainerPort = "4318/tcp" -) - -func NewLocalEndpoint(ctx context.Context, networkName string, promEndpoint *common.LocalEndpointAddress) (*LocalEndpoint, error) { - if ctx.Err() != nil { - return nil, ctx.Err() - } - - pool, err := dockertest.NewPool("") - if err != nil { - return nil, err - } - - err = pool.Client.Ping() - if err != nil { - return nil, fmt.Errorf("pinging Docker daemon: %s", err.Error()) - } - - tempoDataDir, err := os.MkdirTemp("", "tempo-data") - if err != nil { - return nil, err - } - - tempoConfig, err := os.CreateTemp("", "tempo-config") - if err != nil { - _ = os.RemoveAll(tempoDataDir) - - return nil, err - } - - httpListenPort, err := strconv.Atoi(strings.ReplaceAll(HTTPContainerPort, common.TCPSuffix, "")) - if err != nil { - _ = tempoConfig.Close() - _ = os.Remove(tempoConfig.Name()) - _ = os.RemoveAll(tempoDataDir) - - return nil, err - } - - configData := &ConfigTemplateData{ - HTTPListenPort: httpListenPort, - PrometheusEndpoint: fmt.Sprintf("http://%s", promEndpoint.ContainerEndpoint), - } - - configTemplate, err := template.New("tempo-config").Parse(ConfigTemplate) - if err != nil { - _ = tempoConfig.Close() - _ = os.Remove(tempoConfig.Name()) - _ = os.RemoveAll(tempoDataDir) - - return nil, err - } - - err = configTemplate.Execute(tempoConfig, configData) - if err != nil { - _ = tempoConfig.Close() - _ = os.RemoveAll(tempoDataDir) - _ = os.Remove(tempoConfig.Name()) - - return nil, err - } - - configPath := tempoConfig.Name() - - err = tempoConfig.Close() - if err != nil { - _ = os.RemoveAll(tempoDataDir) - _ = os.Remove(tempoConfig.Name()) - - return nil, err - } - - endpoint := &LocalEndpoint{ - mutex: &sync.Mutex{}, - dataDir: tempoDataDir, - configPath: configPath, - networkName: networkName, - prometheusEndpoint: promEndpoint, - stopped: true, - } - - return endpoint, nil -} - -type LocalEndpoint struct { - mutex *sync.Mutex - stopped bool - - container *dockertest.Resource - networkName string - prometheusEndpoint *common.LocalEndpointAddress - configPath string - dataDir string -} - -func (e *LocalEndpoint) Start(ctx context.Context) (*common.LocalEndpointAddress, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.container != nil && e.networkName != "" { - existingContainerNetwork, getExistingNetworkErr := common.ContainerNetwork(e.networkName) - if getExistingNetworkErr != nil { - return nil, fmt.Errorf("getting container network:% s", getExistingNetworkErr) - } - - existingContainerNetworkIP := e.container.GetIPInNetwork(existingContainerNetwork) - if existingContainerNetworkIP == "" { - return nil, fmt.Errorf("got no IP for Tempo container on the container network") - } - - existingContainerPort := strings.ReplaceAll(HTTPContainerPort, common.TCPSuffix, "") - - existingContainerHostEndpoint := e.container.GetHostPort(HTTPContainerPort) - if existingContainerHostEndpoint == "" { - return nil, fmt.Errorf("got no host endpoint for HTTP Tempo API of container") - } - - existingEndpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: existingContainerHostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", existingContainerNetworkIP, existingContainerPort), - } - - return existingEndpointAddress, nil - } - - resChan := make(chan *dockertest.Resource) - errsChan := make(chan error) - - var funcConfig struct { - configPath string - networkName string - dataDir string - } - - funcConfig.configPath = e.configPath - funcConfig.dataDir = e.dataDir - funcConfig.networkName = e.networkName - - go func(parentCtx context.Context) { - if ctx.Err() != nil { - // expect this error to be delivered in the select - return - } - - pool, createClientErr := dockertest.NewPool("") - if createClientErr != nil { - errsChan <- fmt.Errorf("creating a Docker client: %s", createClientErr) - return - } - - pingErr := pool.Client.Ping() - if pingErr != nil { - errsChan <- fmt.Errorf("connecting to Docker daemon: %s", pingErr) - return - } - - network, getNetworkErr := common.ContainerNetwork(funcConfig.networkName) - if getNetworkErr != nil { - errsChan <- fmt.Errorf("getting container network: %s", getNetworkErr) - return - } - - promUrl := fmt.Sprintf("http://%s/-/healthy", e.prometheusEndpoint.HostEndpoint) - - promResp, getPromHealthyErr := http.Get(promUrl) - if getPromHealthyErr != nil { - errsChan <- fmt.Errorf("determining if Prometheus is healthy: %s", getPromHealthyErr) - return - } - - if promResp.StatusCode != http.StatusOK { - errsChan <- fmt.Errorf("expected HTTP status 200, but got: %d", promResp.StatusCode) - return - } - - defer promResp.Body.Close() - - currentUser, getCurrentUserErr := user.Current() - if getCurrentUserErr != nil { - errsChan <- fmt.Errorf("getting current user: %s", getCurrentUserErr) - return - } - - hostHTTPContainerPort, getHostPortErr := common.HostTCPPort() - if getHostPortErr != nil { - errsChan <- getHostPortErr - return - } - - hostGRPCContainerPort, getHostPortErr := common.HostTCPPort() - if getHostPortErr != nil { - errsChan <- getHostPortErr - return - } - - hostHTTPOtelContainerPort, getHostPortErr := common.HostTCPPort() - if getHostPortErr != nil { - errsChan <- getHostPortErr - return - } - - hostGRPCOtelContainerPort, getHostPortErr := common.HostTCPPort() - if getHostPortErr != nil { - errsChan <- getHostPortErr - return - } - - options := &dockertest.RunOptions{ - Repository: "grafana/tempo", - Tag: "2.1.1", - Cmd: []string{"/tempo", "-config.file=/etc/tempo.yaml"}, - Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, - User: fmt.Sprintf("%s:%s", currentUser.Uid, currentUser.Gid), - Networks: []*dockertest.Network{network}, - - Mounts: []string{ - fmt.Sprintf("%s:/etc/tempo.yaml:z", funcConfig.configPath), - fmt.Sprintf("%s:/tmp/tempo:z", funcConfig.dataDir), - }, - - ExposedPorts: []string{ - HTTPContainerPort, - GRPCContainerPort, - HTTPOtelContainerPort, - GRPCOtelContainerPort, - }, - - // to update, look at the upstream compose file: https://github.com/grafana/tempo/blob/main/example/docker-compose/local/docker-compose.yaml - PortBindings: map[docker.Port][]docker.PortBinding{ - HTTPContainerPort: []docker.PortBinding{{HostPort: hostHTTPContainerPort}}, - GRPCContainerPort: []docker.PortBinding{{HostPort: hostGRPCContainerPort}}, - HTTPOtelContainerPort: []docker.PortBinding{{HostPort: hostHTTPOtelContainerPort}}, - GRPCOtelContainerPort: []docker.PortBinding{{HostPort: hostGRPCOtelContainerPort}}, - }, - } - - resource, runErr := pool.RunWithOptions(options) - if runErr != nil { - errsChan <- fmt.Errorf("running container: %s", runErr.Error()) - return - } - - connectionErr := pool.Retry(func() error { - url := fmt.Sprintf("http://localhost:%s/ready", resource.GetPort(HTTPContainerPort)) - - resp, getErr := http.Get(url) - if getErr != nil { - return getErr - } - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("expected HTTP status 200, but got: %d", resp.StatusCode) - } - - defer resp.Body.Close() - - return nil - }) - - if ctx.Err() != nil { - resource.Close() - // do not send the context error through the channel because we're going to check if the context is closed - return - } - - if connectionErr != nil { - resource.Close() - - errsChan <- connectionErr - return - } - - resChan <- resource - return - }(ctx) - - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - - case containerResource := <-resChan: - containerNetwork, err := common.ContainerNetwork(e.networkName) - if err != nil { - containerResource.Close() - return nil, fmt.Errorf("getting container network:% s", err) - } - - containerNetworkIP := containerResource.GetIPInNetwork(containerNetwork) - if containerNetworkIP == "" { - containerResource.Close() - return nil, fmt.Errorf("got no IP for Tempo container on the shared container network") - } - - containerPort := strings.ReplaceAll(HTTPContainerPort, common.TCPSuffix, "") - - hostEndpoint := containerResource.GetHostPort(HTTPContainerPort) - if hostEndpoint == "" { - return nil, fmt.Errorf("got no host endpoint for HTTP Tempo API of container") - } - - endpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: hostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", containerNetworkIP, containerPort), - } - - e.container = containerResource - e.stopped = false - - return endpointAddress, nil - - case startErr := <-errsChan: - return nil, startErr - } - } -} - -func (e *LocalEndpoint) Stop(ctx context.Context) error { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return ctx.Err() - } - - if e.stopped { - return nil - } - - if e.container != nil { - containerCloseErr := e.container.Close() - if containerCloseErr != nil { - return containerCloseErr - } - } - - err := os.RemoveAll(e.dataDir) - if err != nil { - return err - } - - err = os.Remove(e.configPath) - if err != nil { - return err - } - - e.container = nil - e.stopped = true - - return nil -} - -func (e *LocalEndpoint) OTLPTraceEndpoint(ctx context.Context) (*common.LocalEndpointAddress, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.stopped { - return nil, fmt.Errorf("refusing to return trace endpoint for stopped endpoint") - } - - if e.container == nil { - return nil, fmt.Errorf("cannot return trace endpoint with nil Tempo container") - } - - containerNetwork, err := common.ContainerNetwork(e.networkName) - if err != nil { - return nil, fmt.Errorf("getting container network:% s", err) - } - - containerNetworkIP := e.container.GetIPInNetwork(containerNetwork) - if containerNetworkIP == "" { - return nil, fmt.Errorf("got no IP for Tempo container on the shared container network") - } - - containerPort := strings.ReplaceAll(GRPCOtelContainerPort, common.TCPSuffix, "") - - hostEndpoint := e.container.GetHostPort(GRPCOtelContainerPort) - if hostEndpoint == "" { - return nil, fmt.Errorf("got no host gRPC OpenTelemetry host endpoint for Tempo container") - } - - endpointAddress := &common.LocalEndpointAddress{ - HostEndpoint: hostEndpoint, - ContainerEndpoint: fmt.Sprintf("%s:%s", containerNetworkIP, containerPort), - } - - return endpointAddress, nil -} - -func (e *LocalEndpoint) TracerProvider(ctx context.Context, r *resource.Resource) (*trace.TracerProvider, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - if e.stopped { - return nil, fmt.Errorf("refusing to return TracerProvider for stopped endpoint") - } - - if e.container == nil { - return nil, fmt.Errorf("cannot return TraceProvider with nil Tempo container") - } - - containerPort := e.container.GetPort(GRPCOtelContainerPort) - if containerPort == "" { - return nil, fmt.Errorf("got no container gRPC OTel port for Tempo") - } - - exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint(fmt.Sprintf("localhost:%s", containerPort))) - if err != nil { - return nil, err - } - - if ctx.Err() != nil { - return nil, ctx.Err() - } - - traceProvider := trace.NewTracerProvider( - trace.WithBatcher(exporter), - trace.WithResource(r), - ) - - return traceProvider, nil -} - -func (e *LocalEndpoint) ensureValidContainer(ctx context.Context) error { - if ctx.Err() != nil { - return ctx.Err() - } - - if e.stopped { - return fmt.Errorf("cannot get trace from stopped endpoint") - } - - if e.container == nil { - return fmt.Errorf("cannot get trace with nil Tempo container") - } - - return nil -} - -func (e *LocalEndpoint) makeGetRequest(url string) ([]byte, error) { - resp, getErr := http.Get(url) - if getErr != nil { - return nil, getErr - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("expected HTTP status 200, but got: %d", resp.StatusCode) - } - - defer resp.Body.Close() - - respBytes, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - return respBytes, nil -} - -func (e *LocalEndpoint) GetTraceByID(ctx context.Context, id string) ([]byte, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if err := e.ensureValidContainer(ctx); err != nil { - return nil, err - } - - containerPort := e.container.GetPort(HTTPContainerPort) - if containerPort == "" { - return nil, fmt.Errorf("got no container HTTP API port for Tempo") - } - - url := fmt.Sprintf("http://localhost:%s/api/traces/%s", containerPort, id) - - return e.makeGetRequest(url) -} - -func (e *LocalEndpoint) SearchTags(ctx context.Context, tags map[string]string) ([]byte, error) { - e.mutex.Lock() - defer e.mutex.Unlock() - - if err := e.ensureValidContainer(ctx); err != nil { - return nil, err - } - - containerPort := e.container.GetPort(HTTPContainerPort) - if containerPort == "" { - return nil, fmt.Errorf("got no container HTTP API port for Tempo") - } - - var tb strings.Builder - - for tag, val := range tags { - if tb.Len() != 0 { - tb.WriteString("&") - } - s := tag + "=" + val - tb.WriteString(url.QueryEscape(s)) - } - - url := fmt.Sprintf("http://localhost:%s/api/search?tags=%s", containerPort, tb.String()) - - return e.makeGetRequest(url) -} diff --git a/testhelpers/tempo/local_tempo_endpoint_test.go b/testhelpers/tempo/local_tempo_endpoint_test.go deleted file mode 100644 index 8e29de9..0000000 --- a/testhelpers/tempo/local_tempo_endpoint_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package tempo_test - -import ( - "context" - "fmt" - "io" - "net/http" - "time" - - "github.com/google/uuid" - "github.com/grafana/oats/testhelpers/common" - "github.com/grafana/oats/testhelpers/prometheus" - "go.opentelemetry.io/otel/sdk/resource" - - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/grafana/oats/testhelpers/tempo" -) - -var _ = Describe("provisioning Tempo locally using Docker", Label("integration", "docker", "slow"), func() { - Describe("LocalEndpoint", func() { - It("can start a local Tempo endpoint", func() { - ctx := context.Background() - - sharedNetworkUUID, err := uuid.NewRandom() - Expect(err).ToNot(HaveOccurred(), "expected no error creating a UUID for a shared container network") - - sharedNetworkName := fmt.Sprintf("ginkgoTest%s", sharedNetworkUUID.String()) - - _, err = common.ContainerNetwork(sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a shared container network") - - defer common.DestroyContainerNetwork(sharedNetworkName) - - promEndpoint, err := prometheus.NewLocalEndpoint(ctx, sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Prometheus endpoint") - - promAddress, err := promEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting the local Prometheus endpoint") - - defer promEndpoint.Stop(ctx) - - endpoint, err := tempo.NewLocalEndpoint(ctx, sharedNetworkName, promAddress) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Tempo endpoint") - - endpointURL, err := endpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting a local Tempo endpoint") - - defer endpoint.Stop(ctx) - - resp, err := http.Get(fmt.Sprintf("http://%s/status", endpointURL.HostEndpoint)) - Expect(err).ToNot(HaveOccurred(), "expected no error getting the status of the local Tempo endpoint") - - defer resp.Body.Close() - - Expect(resp.StatusCode).To(Equal(http.StatusOK), "expected 200 OX from the local Tempo endpoint") - - respBytes, err := io.ReadAll(resp.Body) - Expect(err).ToNot(HaveOccurred(), "expected no error reading a Tempo status response") - - Expect(string(respBytes)).To(ContainSubstring("tempo, version 2.1.1"), "expected to get the Tempo version from the status endpoint") - }) - - It("provides an OpenTelemetry TraceProvider for sending trace data, and an endpoint for returning a trace by ID", func() { - ctx := context.Background() - - sharedNetworkUUID, err := uuid.NewRandom() - Expect(err).ToNot(HaveOccurred(), "expected no error creating a UUID for a shared container network") - - sharedNetworkName := fmt.Sprintf("ginkgoTest%s", sharedNetworkUUID.String()) - - _, err = common.ContainerNetwork(sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a shared container network") - - defer common.DestroyContainerNetwork(sharedNetworkName) - - promEndpoint, err := prometheus.NewLocalEndpoint(ctx, sharedNetworkName) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Prometheus endpoint") - - promAddress, err := promEndpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting the local Prometheus endpoint") - - defer promEndpoint.Stop(ctx) - - endpoint, err := tempo.NewLocalEndpoint(ctx, sharedNetworkName, promAddress) - Expect(err).ToNot(HaveOccurred(), "expected no error creating a local Tempo endpoint") - - _, err = endpoint.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error starting a local Tempo endpoint") - - defer endpoint.Stop(ctx) - - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - "", // use the SchemaURL from the default resource - semconv.ServiceName("LocalTempoEndpointTest"), - ), - ) - - Expect(err).ToNot(HaveOccurred(), "expected no error creating an OpenTelemetry resource") - - traceProvider, err := endpoint.TracerProvider(ctx, r) - Expect(err).ToNot(HaveOccurred(), "expected no error getting a trace provider") - - defer traceProvider.Shutdown(ctx) - - tracer := traceProvider.Tracer("LocalTempoEndpointTestTracer") - - parentCtx, parentSpan := tracer.Start(ctx, "local-tempo-endpoint-test-parent") - - const eventMessage = "taking a little nap" - - // create a closure over the tracer, parent context, and event message - helloTempo := func() { - _, childSpan := tracer.Start(parentCtx, "hello-tempo") - defer childSpan.End() - - childSpan.AddEvent(eventMessage) - - time.Sleep(250 * time.Millisecond) - } - - helloTempo() - parentSpan.End() - - parentSpanContext := parentSpan.SpanContext() - Expect(parentSpanContext.HasTraceID()).To(BeTrue(), "expected the parent local tempo endpoint test span to have a valid TraceID") - - err = traceProvider.ForceFlush(ctx) - Expect(err).ToNot(HaveOccurred(), "expected no error flushing the trace provider") - - traceID := parentSpanContext.TraceID() - - fetchedTrace, err := endpoint.GetTraceByID(ctx, traceID.String()) - Expect(err).ToNot(HaveOccurred(), "expected no error fetching the exported trace from Tempo") - - Expect(string(fetchedTrace)).ToNot(BeEmpty(), "expected a non empty response from Tempo when getting an exported trace by ID") - Expect(string(fetchedTrace)).To(ContainSubstring(eventMessage), "expected the event message to be contained in the returned trace") - }) - - XIt("returns the gRPC endpoint for sending traces to", func() { - Fail("test not written") - }) - - XIt("can be stopped", func() { - Fail("test not written") - }) - - XIt("tries to respect context cancellation", func() { - Fail("test not written") - }) - - XIt("starts idempotently", func() { - Fail("test not written") - }) - }) -}) diff --git a/testhelpers/tempo/responses/response_helpers.go b/testhelpers/tempo/responses/response_helpers.go index b127c28..9728042 100644 --- a/testhelpers/tempo/responses/response_helpers.go +++ b/testhelpers/tempo/responses/response_helpers.go @@ -36,44 +36,6 @@ type AttributeMatch struct { Type pcommon.ValueType } -func AttributesMatch(attributes pcommon.Map, match []AttributeMatch) error { - for _, m := range match { - if err := MatchTraceAttribute(attributes, m.Type, m.Key, m.Value); err != nil { - return err - } - } - - return nil -} - -func AttributesExist(attributes pcommon.Map, match []AttributeMatch) error { - for _, m := range match { - if err := MatchTraceAttribute(attributes, m.Type, m.Key, ""); err != nil { - return err - } - } - - return nil -} - -func TimeIsIncreasing(span ptrace.Span) error { - start := span.StartTimestamp() - if start == 0 { - return fmt.Errorf("span must have start time") - } - - end := span.EndTimestamp() - if end == 0 { - return fmt.Errorf("span must have end time") - } - - if end < start { - return fmt.Errorf("span end time %d is less than the start time %d", end, start) - } - - return nil -} - func ParseTraceDetails(body []byte) (ptrace.Traces, error) { body = fixIds(body, regexp.MustCompile(`"traceId":\s*"(.*?)"`), "traceId", 16) body = fixIds(body, regexp.MustCompile(`"spanId":\s*"(.*?)"`), "spanId", 8) @@ -117,13 +79,6 @@ func FindSpansWithAttributes(td ptrace.Traces, name string) ([]ptrace.Span, map[ }) } -func ChildrenOf(td ptrace.Traces, spanId string) []ptrace.Span { - spans, _ := FindSpansFunc(td, func(span *ptrace.Span) bool { - return span.ParentSpanID().String() == spanId - }) - return spans -} - func FindSpansFunc(td ptrace.Traces, pred func(*ptrace.Span) bool) ([]ptrace.Span, map[string]any) { var result []ptrace.Span atts := map[string]any{} diff --git a/testhelpers/tempo/tempo_config_template.go b/testhelpers/tempo/tempo_config_template.go deleted file mode 100644 index 3f4c392..0000000 --- a/testhelpers/tempo/tempo_config_template.go +++ /dev/null @@ -1,53 +0,0 @@ -package tempo - -const ConfigTemplate = ` -server: - http_listen_port: {{ .HTTPListenPort }} - - http_tls_config: - client_auth_type: NoClientCert - - grpc_tls_config: - client_auth_type: NoClientCert - -distributor: - receivers: - otlp: - protocols: - http: - grpc: - -ingester: - max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally - -compactor: - compaction: - block_retention: 1h # overall Tempo trace retention. set for demo purposes - -metrics_generator: - registry: - external_labels: - source: tempo - cluster: ginkgo-oats - storage: - path: /tmp/tempo/generator/wal - remote_write: - - url: "{{ .PrometheusEndpoint -}}/api/v1/write" - send_exemplars: true - -storage: - trace: - backend: local # backend configuration to use - wal: - path: /tmp/tempo/wal # where to store the the wal locally - local: - path: /tmp/tempo/blocks - -overrides: - metrics_generator_processors: [service-graphs, span-metrics] # enables metrics generator -` - -type ConfigTemplateData struct { - PrometheusEndpoint string - HTTPListenPort int -} diff --git a/testhelpers/tempo/tempo_suite_test.go b/testhelpers/tempo/tempo_suite_test.go deleted file mode 100644 index e6b10c7..0000000 --- a/testhelpers/tempo/tempo_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package tempo_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestTempo(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Tempo Suite") -} diff --git a/testkit/.gitignore b/testkit/.gitignore deleted file mode 100644 index 0be81f1..0000000 --- a/testkit/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.DS_Store -.idea/ -vendor/ diff --git a/testkit/Makefile b/testkit/Makefile deleted file mode 100644 index f9ba2b3..0000000 --- a/testkit/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - - -.PHONY: run -run: - @echo "Running test suite" - ginkgo -r -v run . diff --git a/testkit/README.md b/testkit/README.md deleted file mode 100644 index 5580a4d..0000000 --- a/testkit/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# TestKit - -TestKit is a collection of test suites and utilities intended to provide verification for the App O11y data ingestion pipeline. -The purpose of this module is to create unit-style test suites that can run without external dependencies. Unit testing specific -components directly allows debugging of components under test with ease. - -## Running Tests - -The test suites are built using the [Ginkgo Testing Framework]. Install the ginkgo executable before running - -```sh -go install github.com/onsi/ginkgo/v2/ginkgo -``` - -To execute all test suites in the repository, run - -```sh -make run -``` - -To run an individual suite, use `ginkgo` directly - -```sh -ginkgo run ./servicegraph/ -``` - -[ginkgo testing framework]: https://onsi.github.io/ginkgo/ diff --git a/testkit/go.mod b/testkit/go.mod deleted file mode 100644 index 429ff20..0000000 --- a/testkit/go.mod +++ /dev/null @@ -1,55 +0,0 @@ -module github.com/grafana/oats/testkit - -go 1.23 - -require ( - github.com/onsi/ginkgo/v2 v2.20.2 - github.com/onsi/gomega v1.34.1 - github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector v0.82.0 - github.com/open-telemetry/opentelemetry-collector-contrib/processor/servicegraphprocessor v0.82.0 - go.opentelemetry.io/collector/component v0.82.0 - go.opentelemetry.io/collector/confmap v0.82.0 - go.opentelemetry.io/collector/connector v0.82.0 - go.opentelemetry.io/collector/consumer v0.82.0 - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 - go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 - go.opentelemetry.io/otel/metric v1.16.0 - go.opentelemetry.io/otel/trace v1.16.0 - go.uber.org/zap v1.25.0 - gopkg.in/yaml.v3 v3.0.1 -) - -require ( - github.com/benbjohnson/clock v1.3.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/knadh/koanf v1.5.0 // indirect - github.com/knadh/koanf/v2 v2.0.1 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector v0.82.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.82.0 // indirect - go.opentelemetry.io/collector/exporter v0.82.0 // indirect - go.opentelemetry.io/collector/processor v0.82.0 // indirect - go.opentelemetry.io/collector/receiver v0.82.0 // indirect - go.opentelemetry.io/collector/semconv v0.82.0 // indirect - go.opentelemetry.io/otel v1.16.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.17.0 // indirect - golang.org/x/tools v0.24.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/grpc v1.57.0 // indirect - google.golang.org/protobuf v1.34.1 // indirect -) diff --git a/testkit/go.sum b/testkit/go.sum deleted file mode 100644 index 50230ca..0000000 --- a/testkit/go.sum +++ /dev/null @@ -1,591 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= -contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= -github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= -github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= -github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= -github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= -github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= -github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= -github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= -github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs= -github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs= -github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= -github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= -github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mostynb/go-grpc-compression v1.2.0 h1:KJzRFSYPXlcoYjG5/xLZB8tpuOyWF2UnlW4tAuaWnfI= -github.com/mostynb/go-grpc-compression v1.2.0/go.mod h1:oidYvYyefMmhcuvU8fLJ8FfZyTyVzJ6SkmD5fIKgRe8= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= -github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector v0.82.0 h1:Y9+jJXKTXCiWrHB9Jmxgo9bpsDRxV20SDSqQrXx149c= -github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector v0.82.0/go.mod h1:mYWo9KNvBriPbuYCIchfshaAF/qD62svP6tV3E0sO+8= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/servicegraphprocessor v0.82.0 h1:QdFxprQto8STwx8nDxLhV9Qg9xhOJ3efAXis38GZ1Q4= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/servicegraphprocessor v0.82.0/go.mod h1:OT8TsUe1uWJVaiYWn4soFPRi3uAe76Oi52QKxf0CDc8= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil/v3 v3.23.6 h1:5y46WPI9QBKBbK7EEccUPNXpJpNrvPuTD0O2zHEHT08= -github.com/shirou/gopsutil/v3 v3.23.6/go.mod h1:j7QX50DrXYggrpN30W0Mo+I4/8U2UUIQrnrhqUeWrAU= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= -github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= -github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= -github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= -go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/collector v0.82.0 h1:MaKqWT0R4GCdkZDhYWOQkLfoJj9V7GsMbk1gsAuogaw= -go.opentelemetry.io/collector v0.82.0/go.mod h1:PMmDJkZzC1xpcViHlwMMEVeAnRRl3HYy3nXgD8KJwG0= -go.opentelemetry.io/collector/component v0.82.0 h1:ID9nOGKBf5G0avhuYQlTzmwAyIMvh9B+tlckLE/4qw4= -go.opentelemetry.io/collector/component v0.82.0/go.mod h1:jSdGG4L1Ger6ob6lWpr8jmKC2qqC+XZ/gOgu7GUA5xs= -go.opentelemetry.io/collector/config/configauth v0.82.0 h1:H5xrWyPMotSqajiiH/bay8bpVsT4aq6Vih4OuArXv4Q= -go.opentelemetry.io/collector/config/configauth v0.82.0/go.mod h1:P0ukmBIUk+HP0O7yfUOKRmPmffneAQgmEL9/iTOo1CU= -go.opentelemetry.io/collector/config/configcompression v0.82.0 h1:M6a7eiHdBUB8mIioDhWugJfNm7Sw85cvv/OXyTDhtY0= -go.opentelemetry.io/collector/config/configcompression v0.82.0/go.mod h1:xhHm1sEH7BTECAJo1xn64NMxeIvZGKdVGdSKUUc+YuM= -go.opentelemetry.io/collector/config/configgrpc v0.82.0 h1:taZWDbtVBm0OOcgnfpVA1X43pmU2oNhj39B2uV3COQk= -go.opentelemetry.io/collector/config/configgrpc v0.82.0/go.mod h1:NHXHRI40Q7TT/d38DKT30B7DOrVUkj7anEFOD59R9o8= -go.opentelemetry.io/collector/config/confignet v0.82.0 h1:zN9JaFTn7Dth3u5ot6KZJcBZACTEzGqFWYyO5qAlYfo= -go.opentelemetry.io/collector/config/confignet v0.82.0/go.mod h1:unOg7BZvpt6T5xsf+LyeOQvUhD8ld/2AbfOsmUZ/bPM= -go.opentelemetry.io/collector/config/configopaque v0.82.0 h1:0Ma63QTr4AkODzEABZHtgiU5Dig8SItpHOuB28UnVSw= -go.opentelemetry.io/collector/config/configopaque v0.82.0/go.mod h1:pM1oy6gasukw3H6jAvc9Q9OtFaaY2IbfeuwCPAjOgXc= -go.opentelemetry.io/collector/config/configtelemetry v0.82.0 h1:Zln2K4S5gBDcOpBNIzM0cZS5P6cohEYstHngVvIbGBY= -go.opentelemetry.io/collector/config/configtelemetry v0.82.0/go.mod h1:KEYQRiYJdx38iZkvcLKBZWH9fK4NeafxBwGRrRKMgyA= -go.opentelemetry.io/collector/config/configtls v0.82.0 h1:eE/8muTszLlviOGLy5N08BaXLCcYqDW3mKIoKyDDa8o= -go.opentelemetry.io/collector/config/configtls v0.82.0/go.mod h1:unBTmL1bdpkp9mYEDz7N+Ln4yEwh7Ug74I1HgZMplCk= -go.opentelemetry.io/collector/config/internal v0.82.0 h1:JnnDARkXrC3OJDsMfQkBgfI0Np4s+18zvoDqZ4OH0+I= -go.opentelemetry.io/collector/config/internal v0.82.0/go.mod h1:RKcLV1gQxhgwx+6rlPYsvGMq1RZNne3UeOUZkHxJnIg= -go.opentelemetry.io/collector/confmap v0.82.0 h1:s1Rd8jz21DGlLJfED0Py9VaEq2qPWmWwWy5MriDCX+4= -go.opentelemetry.io/collector/confmap v0.82.0/go.mod h1:IS/PoUYHETtxV6+fJammTkCxxa4LEwK2u4Cx/bVCH/s= -go.opentelemetry.io/collector/connector v0.82.0 h1:sCzfcROg0IbmmwoAeLzVfcAs1ZpwlA+UzLzc3xRjOr4= -go.opentelemetry.io/collector/connector v0.82.0/go.mod h1:yXr1degja36+aAdY3qOv66jCXHs5QjiIeoerygLYC44= -go.opentelemetry.io/collector/consumer v0.82.0 h1:vZecylW6bpaphetSTjCLgwXLxSYQ6oe/kzwkx4iF5oE= -go.opentelemetry.io/collector/consumer v0.82.0/go.mod h1:qrhd0i0Gp0RkihcEXb+7Rb584Kal2NmGH1eA4Zg6puA= -go.opentelemetry.io/collector/exporter v0.82.0 h1:BWsx4rWfVwlV+qNuevSMm+2Cv6uGZYYZ9CEFqq0q+F4= -go.opentelemetry.io/collector/exporter v0.82.0/go.mod h1:e3VPpLYVNRaF+G2HuKw6A5hTBMYZ4tgRYYzMusfwFJE= -go.opentelemetry.io/collector/exporter/otlpexporter v0.82.0 h1:tYCEUQpfyuS/NgrWg9Ulps6f0ffPSCBRTBdK6sXnSaw= -go.opentelemetry.io/collector/exporter/otlpexporter v0.82.0/go.mod h1:CGeXJuRYxrzTtJUHlpLPHirzcmGq5qbcPff0ec+If14= -go.opentelemetry.io/collector/extension v0.82.0 h1:DH4tqrTOz0HmGDJ6FT/jRD2woQf3ugqC6QqSiQdH3wg= -go.opentelemetry.io/collector/extension v0.82.0/go.mod h1:n7d0XTh7fdyorZWTc+gLpJh78FS7GjRqIjUiW1xdhe0= -go.opentelemetry.io/collector/extension/auth v0.82.0 h1:iaxwFslRj6mfzs1wVzbnj+gDU2G98IeXW4tcrq78p5s= -go.opentelemetry.io/collector/extension/auth v0.82.0/go.mod h1:O1xBcb06pKD8g3FadLDvMa1xKZwPGdHQp4CI8vW3RCM= -go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014 h1:C9o0mbP0MyygqFnKueVQK/v9jef6zvuttmTGlKaqhgw= -go.opentelemetry.io/collector/featuregate v1.0.0-rcv0014/go.mod h1:0mE3mDLmUrOXVoNsuvj+7dV14h/9HFl/Fy9YTLoLObo= -go.opentelemetry.io/collector/pdata v1.0.0-rcv0014 h1:iT5qH0NLmkGeIdDtnBogYDx7L58t6CaWGL378DEo2QY= -go.opentelemetry.io/collector/pdata v1.0.0-rcv0014/go.mod h1:BRvDrx43kiSoUx3mr7SoA7h9B8+OY99mUK+CZSQFWW4= -go.opentelemetry.io/collector/processor v0.82.0 h1:DoqVrrnGYThu/h1sOr6E0hR1Fj5nQT4VT0ptFZcltRk= -go.opentelemetry.io/collector/processor v0.82.0/go.mod h1:B0MtfLWCYNBJ+PXf9k77M2Yn08MKItNB2vuvwhqrtt0= -go.opentelemetry.io/collector/receiver v0.82.0 h1:bc6jc8jmSgc0/C9zqTqqWOGJFVx0AJ53jiToSmQs2SE= -go.opentelemetry.io/collector/receiver v0.82.0/go.mod h1:Uh6BgcTmmrA1Bm/GpKGRY6WwQyPio4yEDsYkUo0A5Gk= -go.opentelemetry.io/collector/semconv v0.82.0 h1:WUeT2a+uZjI6kLvwcBaJnGvo7KSQ/9dIFRcxOQdXucc= -go.opentelemetry.io/collector/semconv v0.82.0/go.mod h1:TlYPtzvsXyHOgr5eATi43qEMqwSmIziivJB2uctKswo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.1-0.20230612162650-64be7e574a17 h1:mdcNStUIXngF/mH3xxAo4nbR4g65IXqLL1SvYMjz7JQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.1-0.20230612162650-64be7e574a17/go.mod h1:N2Nw/UmmvQn0yCnaUzvsWzTWIeffYIdFteg6mxqCWII= -go.opentelemetry.io/contrib/propagators/b3 v1.17.0 h1:ImOVvHnku8jijXqkwCSyYKRDt2YrnGXD4BbhcpfbfJo= -go.opentelemetry.io/contrib/propagators/b3 v1.17.0/go.mod h1:IkfUfMpKWmynvvE0264trz0sf32NRTZL4nuAN9AbWRc= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/bridge/opencensus v0.39.0 h1:YHivttTaDhbZIHuPlg1sWsy2P5gj57vzqPfkHItgbwQ= -go.opentelemetry.io/otel/bridge/opencensus v0.39.0/go.mod h1:vZ4537pNjFDXEx//WldAR6Ro2LC8wwmFC76njAXwNPE= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0 h1:f6BwB2OACc3FCbYVznctQ9V6KK7Vq6CjmYXJ7DeSs4E= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0/go.mod h1:UqL5mZ3qs6XYhDnZaW1Ps4upD+PX6LipH40AoeuIlwU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 h1:rm+Fizi7lTM2UefJ1TO347fSRcwmIsUAaZmYmIGBRAo= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0/go.mod h1:sWFbI3jJ+6JdjOVepA5blpv/TJ20Hw+26561iMbWcwU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0 h1:IZXpCEtI7BbX01DRQEWTGDkvjMB6hEhiEZXS+eg2YqY= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0/go.mod h1:xY111jIZtWb+pUUgT4UiiSonAaY2cD2Ts5zvuKLki3o= -go.opentelemetry.io/otel/exporters/prometheus v0.39.0 h1:whAaiHxOatgtKd+w0dOi//1KUxj3KoPINZdtDaDj3IA= -go.opentelemetry.io/otel/exporters/prometheus v0.39.0/go.mod h1:4jo5Q4CROlCpSPsXLhymi+LYrDXd2ObU5wbKayfZs7Y= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 h1:fl2WmyenEf6LYYlfHAtCUEDyGcpwJNqD4dHGO7PVm4w= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0/go.mod h1:csyQxQ0UHHKVA8KApS7eUO/klMO5sd/av5CNZNU4O6w= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 h1:+XWJd3jf75RXJq29mxbuXhCXFDG3S3R4vBUeSI2P7tE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0/go.mod h1:hqgzBPTf4yONMFgdZvL/bK42R/iinTyVQtiWihs3SZc= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI= -go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM= -gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 h1:9NWlQfY2ePejTmfwUH1OWwmznFa+0kKcHGPDvcPza9M= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/testkit/internal/harness/traces_to_metrics.go b/testkit/internal/harness/traces_to_metrics.go deleted file mode 100644 index 6b7456d..0000000 --- a/testkit/internal/harness/traces_to_metrics.go +++ /dev/null @@ -1,56 +0,0 @@ -package harness - -import ( - "context" - - "github.com/grafana/oats/testkit/internal/util" - "github.com/onsi/ginkgo/v2" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/connector" - "go.opentelemetry.io/collector/consumer/consumertest" - "go.opentelemetry.io/collector/pdata/pcommon" - "go.opentelemetry.io/collector/pdata/pmetric" - "go.opentelemetry.io/otel/metric/noop" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap/zaptest" -) - -// TracesToMetrics is a test harness for connectors that accept traces and emit metrics. -type TracesToMetrics struct { - connector.Traces - Metrics func() []pmetric.Metrics - Reset func() -} - -// NewTracesToMetrics constructs a new TracesToMetrics test harness. -func NewTracesToMetrics(t ginkgo.FullGinkgoTInterface, factory connector.Factory, config component.Config) (*TracesToMetrics, error) { - logger := zaptest.NewLogger(t) - - set := connector.CreateSettings{ - ID: component.NewIDWithName(component.DataTypeTraces, "traces_to_metrics_harness"), - TelemetrySettings: component.TelemetrySettings{ - Logger: logger, - TracerProvider: trace.NewNoopTracerProvider(), - MeterProvider: noop.NewMeterProvider(), - MetricsLevel: 0, - Resource: pcommon.Resource{}, - }, - BuildInfo: component.BuildInfo{}, - } - - if config == nil { - config = factory.CreateDefaultConfig() - } - sink := &consumertest.MetricsSink{} - c, err := factory.CreateTracesToMetrics(context.TODO(), set, config, sink) - if err != nil { - return nil, err - } - - // return the harness and start the connector - return &TracesToMetrics{ - Traces: c, - Metrics: sink.AllMetrics, - Reset: sink.Reset, - }, c.Start(context.TODO(), &util.NoopHost{}) -} diff --git a/testkit/internal/util/metrics.go b/testkit/internal/util/metrics.go deleted file mode 100644 index 806951a..0000000 --- a/testkit/internal/util/metrics.go +++ /dev/null @@ -1,13 +0,0 @@ -package util - -import "go.opentelemetry.io/collector/pdata/pmetric" - -// HasMetric returns true if a metric with matching name is present. -func HasMetric(metrics pmetric.Metrics, name string) bool { - m := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics() - found := false - for i := 0; i < m.Len() && !found; i += 1 { - found = m.At(i).Name() == name - } - return found -} diff --git a/testkit/internal/util/noop_host.go b/testkit/internal/util/noop_host.go deleted file mode 100644 index 5cc25b2..0000000 --- a/testkit/internal/util/noop_host.go +++ /dev/null @@ -1,21 +0,0 @@ -package util - -import "go.opentelemetry.io/collector/component" - -type NoopHost struct{} - -// GetExporters implements component.Host. -func (*NoopHost) GetExporters() map[component.Type]map[component.ID]component.Component { return nil } - -// GetExtensions implements component.Host. -func (*NoopHost) GetExtensions() map[component.ID]component.Component { return nil } - -// GetFactory implements component.Host. -func (*NoopHost) GetFactory(kind component.Kind, componentType component.Type) component.Factory { - return nil -} - -// ReportFatalError implements component.Host. -func (*NoopHost) ReportFatalError(err error) {} - -var _ component.Host = (*NoopHost)(nil) diff --git a/testkit/internal/util/traces.go b/testkit/internal/util/traces.go deleted file mode 100644 index 2a12547..0000000 --- a/testkit/internal/util/traces.go +++ /dev/null @@ -1,39 +0,0 @@ -package util - -import ( - "bufio" - "embed" - - "go.opentelemetry.io/collector/pdata/ptrace" -) - -// ReadTraces unmarshals trace data from the filesystem and returns the -// resulting []ptrace.Traces. The traceFS argument should represent an -// embedded data directory containing traces in JSON format under -// testdata/traces/*.json rooted in the test suite directory. The JSON files -// should include a single serialized ptrace.Trace per line. -func ReadTraces(traceFS *embed.FS, name string) ([]ptrace.Traces, error) { - // trace input for test - f, err := traceFS.Open("testdata/traces/" + name + ".json") - if err != nil { - return nil, err - } - defer f.Close() - - var traces []ptrace.Traces - scanner := bufio.NewScanner(f) - u := ptrace.JSONUnmarshaler{} - for scanner.Scan() { - t, err := u.UnmarshalTraces(scanner.Bytes()) - if err != nil { - return nil, err - } - traces = append(traces, t) - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return traces, nil -} diff --git a/testkit/servicegraph/metrics_test.go b/testkit/servicegraph/metrics_test.go deleted file mode 100644 index 0c33d02..0000000 --- a/testkit/servicegraph/metrics_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package servicegraph_test - -import ( - "context" - "embed" - "time" - - "github.com/grafana/oats/testkit/internal/harness" - "github.com/grafana/oats/testkit/internal/util" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "github.com/open-telemetry/opentelemetry-collector-contrib/connector/servicegraphconnector" - "github.com/open-telemetry/opentelemetry-collector-contrib/processor/servicegraphprocessor" - "go.opentelemetry.io/collector/confmap" - "go.opentelemetry.io/collector/featuregate" - "go.opentelemetry.io/collector/pdata/pcommon" - "go.opentelemetry.io/collector/pdata/pmetric" - "go.opentelemetry.io/collector/pdata/ptrace" - "gopkg.in/yaml.v3" -) - -const ( - labelClient = "client" - labelServer = "server" - - // https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/connector/servicegraphconnector#metrics - tracesServiceGraphRequestTotal = "traces_service_graph_request_total" - tracesServiceGraphRequestFailedTotal = "traces_service_graph_request_failed_total" - tracesServiceGraphRequestServerSeconds = "traces_service_graph_request_server_seconds" - tracesServiceGraphRequestClientSeconds = "traces_service_graph_request_client_seconds" - tracesServiceGraphUnpairedSpansTotal = "traces_service_graph_unpaired_spans_total" - tracesServiceGraphDroppedSpansTotal = "traces_service_graph_dropped_spans_total" -) - -//go:embed testdata/traces/*.json -var traceFS embed.FS - -//go:embed testdata/config_with_peer_attributes.yaml -var componentConfig []byte - -// This spec is designed to test the metrics generated by the servicegraph processor. -var _ = Describe("generating service graph metrics", func() { - var ( - inputStr string - metrics []pmetric.Metrics - ) - - Context("from trace: POST /api/orders", func() { - JustBeforeEach(func() { - // create servicegraph connector config - var data map[string]any - if err := yaml.Unmarshal(componentConfig, &data); err != nil { - Fail("error unmarshaling connector config yaml: " + err.Error()) - } - conf := confmap.NewFromStringMap(data) - config := servicegraphprocessor.Config{} - if err := conf.Unmarshal(&config); err != nil { - Fail("error unmarshaling connector config map: " + err.Error()) - } - - // enable servicegraph.processor.virtualNode feature gate - if err := featuregate.GlobalRegistry().Set("processor.servicegraph.virtualNode", true); err != nil { - Fail("error enabling processor.servicegraph.virtualNode feature gate: " + err.Error()) - } - - // create test harness - h, err := harness.NewTracesToMetrics(GinkgoT(), servicegraphconnector.NewFactory(), &config) - if err != nil { - Fail("error constructing test harness: " + err.Error()) - } - - // read trace input - traces, err := util.ReadTraces(&traceFS, inputStr) - if err != nil { - Fail("error reading trace testdata: " + err.Error()) - } - - // consume traces - ctx := context.Background() - for _, t := range traces { - err = h.ConsumeTraces(ctx, t) - if err != nil { - Fail("error consuming traces: " + err.Error()) - } - } - - // reset the metrics collected and test output after expiration loop - h.Reset() - time.Sleep(10 * time.Millisecond) - - // we need to run ConsumeTraces again to record virtualNodes after expiration loop - err = h.ConsumeTraces(ctx, ptrace.NewTraces()) - Expect(err).ToNot(HaveOccurred()) - - // gather metrics - metrics = h.Metrics() - Expect(metrics).ToNot(BeNil()) - - // shutdown - _ = h.Shutdown(ctx) - }) - - Describe("metrics are generated", func() { - BeforeEach(func() { - inputStr = "5b584103c6fc5ddf423cb2fb6552d0f0" - }) - It("should generate metrics", func() { - Expect(util.HasMetric(metrics[0], tracesServiceGraphRequestTotal)).To(BeTrue()) - Expect(util.HasMetric(metrics[0], tracesServiceGraphRequestServerSeconds)).To(BeTrue()) - Expect(util.HasMetric(metrics[0], tracesServiceGraphRequestClientSeconds)).To(BeTrue()) - Expect(util.HasMetric(metrics[0], tracesServiceGraphRequestFailedTotal)).To(BeTrue()) - - // these are not generated with this this input - Expect(util.HasMetric(metrics[0], tracesServiceGraphUnpairedSpansTotal)).To(BeFalse()) - Expect(util.HasMetric(metrics[0], tracesServiceGraphDroppedSpansTotal)).To(BeFalse()) - }) - }) - - When("client span to instrumented service", func() { - BeforeEach(func() { - inputStr = "5b584103c6fc5ddf423cb2fb6552d0f0" - }) - It("should create an edge from client=frontend to server=checkout", func() { - Expect(countEdges(metrics, tracesServiceGraphRequestTotal, "frontend", "checkout")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestTotal) - Expect(countEdges(metrics, tracesServiceGraphRequestServerSeconds, "frontend", "checkout")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestServerSeconds) - Expect(countEdges(metrics, tracesServiceGraphRequestClientSeconds, "frontend", "checkout")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestClientSeconds) - }) - It("should create an edge from client=frontend to server=fraud-detection", func() { - Expect(countEdges(metrics, tracesServiceGraphRequestTotal, "frontend", "fraud-detection")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestTotal) - Expect(countEdges(metrics, tracesServiceGraphRequestServerSeconds, "frontend", "fraud-detection")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestServerSeconds) - Expect(countEdges(metrics, tracesServiceGraphRequestClientSeconds, "frontend", "fraud-detection")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestClientSeconds) - }) - It("should create an edge from client=frontend to server=my_shopping_cart", func() { - Expect(countEdges(metrics, tracesServiceGraphRequestTotal, "frontend", "my_shopping_cart")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestTotal) - Expect(countEdges(metrics, tracesServiceGraphRequestServerSeconds, "frontend", "my_shopping_cart")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestServerSeconds) - Expect(countEdges(metrics, tracesServiceGraphRequestClientSeconds, "frontend", "my_shopping_cart")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestClientSeconds) - }) - }) - - When("client span to uninstrumented service", func() { - BeforeEach(func() { - inputStr = "5b584103c6fc5ddf423cb2fb6552d0f0" - }) - It("should create an edge from client=frontend to server=example.com", func() { - Expect(countEdges(metrics, tracesServiceGraphRequestTotal, "frontend", "example.com")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestTotal) - Expect(countEdges(metrics, tracesServiceGraphRequestServerSeconds, "frontend", "example.com")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestServerSeconds) - Expect(countEdges(metrics, tracesServiceGraphRequestClientSeconds, "frontend", "example.com")). - To(Equal(1), "metric has edge: "+tracesServiceGraphRequestClientSeconds) - }) - }) - }) -}) - -// countEdges counts the number of metrics that have client and server attributes with values that match the given input -func countEdges(metrics []pmetric.Metrics, name string, client string, server string) int { - edgeCount := 0 - for i := 0; i < len(metrics); i += 1 { - m := metrics[i].ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics() - for j := 0; j < m.Len(); j += 1 { - if m.At(j).Name() == name { - if hasEdge(m.At(j), client, server) { - edgeCount += 1 - } - } - } - } - return edgeCount -} - -// hasEdge returns true if the metric has client and server attributes with values that match the given input -func hasEdge(m pmetric.Metric, client string, server string) bool { - var attr pcommon.Map - switch m.Type().String() { - case pmetric.MetricTypeSum.String(): - attr = m.Sum().DataPoints().At(0).Attributes() - case pmetric.MetricTypeHistogram.String(): - attr = m.Histogram().DataPoints().At(0).Attributes() - default: - Expect(m.Type().String()).ToNot(Equal(m.Type().String()), "did not expect this metric type") - } - - if c, found := attr.Get(labelClient); found && c.Str() == client { - s, found := attr.Get(labelServer) - return found && s.Str() == server - } - return false -} diff --git a/testkit/servicegraph/servicegraph_suite_test.go b/testkit/servicegraph/servicegraph_suite_test.go deleted file mode 100644 index 1e4a20d..0000000 --- a/testkit/servicegraph/servicegraph_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package servicegraph_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestServicegraph(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Servicegraph Suite") -} diff --git a/testkit/servicegraph/testdata/config_with_peer_attributes.yaml b/testkit/servicegraph/testdata/config_with_peer_attributes.yaml deleted file mode 100644 index d989dd3..0000000 --- a/testkit/servicegraph/testdata/config_with_peer_attributes.yaml +++ /dev/null @@ -1,9 +0,0 @@ -latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 100ms, 250ms] -dimensions: [cluster, namespace] -store: - ttl: 1ms - max_items: 1000 -cache_loop: 1ms -store_expiration_loop: 1ms -virtual_node_peer_attributes: - - net.peer.name diff --git a/testkit/servicegraph/testdata/traces/5b584103c6fc5ddf423cb2fb6552d0f0.json b/testkit/servicegraph/testdata/traces/5b584103c6fc5ddf423cb2fb6552d0f0.json deleted file mode 100644 index ef05ff0..0000000 --- a/testkit/servicegraph/testdata/traces/5b584103c6fc5ddf423cb2fb6552d0f0.json +++ /dev/null @@ -1,4 +0,0 @@ -{"resourceSpans":[{"resource":{"attributes":[{"key":"deployment.environment","value":{"stringValue":"staging"}},{"key":"host.arch","value":{"stringValue":"x86_64"}},{"key":"host.name","value":{"stringValue":"Roberts-MBP-2.lan"}},{"key":"os.description","value":{"stringValue":"Mac OS X 13.4.1"}},{"key":"os.type","value":{"stringValue":"darwin"}},{"key":"process.command_args","value":{"arrayValue":{"values":[{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"},{"stringValue":"-javaagent:./../.otel/opentelemetry-javaagent-1.28.0.jar"},{"stringValue":"-Dserver.port=8081"},{"stringValue":"-Dotel.instrumentation.logback-appender.experimental-log-attributes=true"},{"stringValue":"-jar"},{"stringValue":"target/fraud-detection-1.1-SNAPSHOT.jar"}]}}},{"key":"process.executable.path","value":{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"}},{"key":"process.pid","value":{"intValue":"95155"}},{"key":"process.runtime.description","value":{"stringValue":"Homebrew OpenJDK 64-Bit Server VM 20.0.1"}},{"key":"process.runtime.name","value":{"stringValue":"OpenJDK Runtime Environment"}},{"key":"process.runtime.version","value":{"stringValue":"20.0.1"}},{"key":"service.name","value":{"stringValue":"fraud-detection"}},{"key":"service.namespace","value":{"stringValue":"fraud"}},{"key":"service.version","value":{"stringValue":"1.1-SNAPSHOT"}},{"key":"telemetry.auto.version","value":{"stringValue":"1.28.0"}},{"key":"telemetry.sdk.language","value":{"stringValue":"java"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.version","value":{"stringValue":"1.28.0"}}]},"scopeSpans":[{"scope":{"name":"io.opentelemetry.jdbc","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"7cd27ce93555c034","parentSpanId":"b26ae1dac17c3d43","name":"my_shopping_cart","kind":3,"startTimeUnixNano":"1691012744032781087","endTimeUnixNano":"1691012744033061020","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":""}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-9"}},{"key":"thread.id","value":{"intValue":"55"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"f7009b6e5676da80","parentSpanId":"b26ae1dac17c3d43","name":"SELECT my_shopping_cart","kind":3,"startTimeUnixNano":"1691012744033088464","endTimeUnixNano":"1691012744084055342","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select pg_sleep(?)"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-9"}},{"key":"thread.id","value":{"intValue":"55"}}],"status":{}}]}],"schemaUrl":"https://opentelemetry.io/schemas/1.20.0"}]} -{"resourceSpans":[{"resource":{"attributes":[{"key":"deployment.environment","value":{"stringValue":"staging"}},{"key":"host.arch","value":{"stringValue":"x86_64"}},{"key":"host.name","value":{"stringValue":"Roberts-MBP-2.lan"}},{"key":"os.description","value":{"stringValue":"Mac OS X 13.4.1"}},{"key":"os.type","value":{"stringValue":"darwin"}},{"key":"process.command_args","value":{"arrayValue":{"values":[{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"},{"stringValue":"-javaagent:./../.otel/opentelemetry-javaagent-1.28.0.jar"},{"stringValue":"-Dserver.port=8081"},{"stringValue":"-Dotel.instrumentation.logback-appender.experimental-log-attributes=true"},{"stringValue":"-jar"},{"stringValue":"target/fraud-detection-1.1-SNAPSHOT.jar"}]}}},{"key":"process.executable.path","value":{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"}},{"key":"process.pid","value":{"intValue":"95155"}},{"key":"process.runtime.description","value":{"stringValue":"Homebrew OpenJDK 64-Bit Server VM 20.0.1"}},{"key":"process.runtime.name","value":{"stringValue":"OpenJDK Runtime Environment"}},{"key":"process.runtime.version","value":{"stringValue":"20.0.1"}},{"key":"service.name","value":{"stringValue":"fraud-detection"}},{"key":"service.namespace","value":{"stringValue":"fraud"}},{"key":"service.version","value":{"stringValue":"1.1-SNAPSHOT"}},{"key":"telemetry.auto.version","value":{"stringValue":"1.28.0"}},{"key":"telemetry.sdk.language","value":{"stringValue":"java"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.version","value":{"stringValue":"1.28.0"}}]},"scopeSpans":[{"scope":{"name":"io.opentelemetry.tomcat-10.0","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"cd2f07a9ed49a547","parentSpanId":"57d6eb86f42241f3","name":"GET /fraud/checkOrder","kind":2,"startTimeUnixNano":"1691012744032508000","endTimeUnixNano":"1691012745093407561","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.response_content_length","value":{"intValue":"2"}},{"key":"http.route","value":{"stringValue":"/fraud/checkOrder"}},{"key":"net.host.port","value":{"intValue":"8081"}},{"key":"net.sock.host.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"net.sock.peer.port","value":{"intValue":"57658"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"55"}},{"key":"user_agent.original","value":{"stringValue":"Java/20.0.1"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"http.target","value":{"stringValue":"/fraud/checkOrder?orderPrice=300.0\u0026customerIpAddress=127.0.0.1\u0026shippingCountry=FR"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-9"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"7ae607ca5096bc68","parentSpanId":"7600d1e69dd28a8e","name":"GET /fraud/checkOrder","kind":2,"startTimeUnixNano":"1691012748193591000","endTimeUnixNano":"1691012748303726630","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.response_content_length","value":{"intValue":"2"}},{"key":"http.route","value":{"stringValue":"/fraud/checkOrder"}},{"key":"net.host.port","value":{"intValue":"8081"}},{"key":"net.sock.host.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"net.sock.peer.port","value":{"intValue":"57658"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"51"}},{"key":"user_agent.original","value":{"stringValue":"Java/20.0.1"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"http.target","value":{"stringValue":"/fraud/checkOrder?orderPrice=5.0\u0026customerIpAddress=127.0.0.1\u0026shippingCountry=FR"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-5"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.spring-webmvc-6.0","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"b26ae1dac17c3d43","parentSpanId":"cd2f07a9ed49a547","name":"FraudDetectionController.checkOrder","kind":1,"startTimeUnixNano":"1691012744032704488","endTimeUnixNano":"1691012745093287631","attributes":[{"key":"customer_ip_address","value":{"stringValue":"127.0.0.1"}},{"key":"order_price","value":{"doubleValue":300}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-9"}},{"key":"thread.id","value":{"intValue":"55"}},{"key":"shipping_country","value":{"stringValue":"FR"}},{"key":"fraud_score","value":{"intValue":"-4"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"83fa003e52abc846","parentSpanId":"7ae607ca5096bc68","name":"FraudDetectionController.checkOrder","kind":1,"startTimeUnixNano":"1691012748193849400","endTimeUnixNano":"1691012748303640335","attributes":[{"key":"customer_ip_address","value":{"stringValue":"127.0.0.1"}},{"key":"order_price","value":{"doubleValue":5}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-5"}},{"key":"thread.id","value":{"intValue":"51"}},{"key":"shipping_country","value":{"stringValue":"FR"}},{"key":"fraud_score","value":{"intValue":"-12"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.jdbc","version":"1.28.0-alpha"},"spans":[{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"3ad2910fea2a446c","parentSpanId":"83fa003e52abc846","name":"my_shopping_cart","kind":3,"startTimeUnixNano":"1691012748193922002","endTimeUnixNano":"1691012748194123728","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":""}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-5"}},{"key":"thread.id","value":{"intValue":"51"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"c6c57bfd14ff5caa","parentSpanId":"83fa003e52abc846","name":"SELECT my_shopping_cart","kind":3,"startTimeUnixNano":"1691012748194142183","endTimeUnixNano":"1691012748244778128","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select pg_sleep(?)"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8081-exec-5"}},{"key":"thread.id","value":{"intValue":"51"}}],"status":{}}]}],"schemaUrl":"https://opentelemetry.io/schemas/1.20.0"}]} -{"resourceSpans":[{"resource":{"attributes":[{"key":"deployment.environment","value":{"stringValue":"staging"}},{"key":"host.arch","value":{"stringValue":"x86_64"}},{"key":"host.name","value":{"stringValue":"Roberts-MBP-2.lan"}},{"key":"os.description","value":{"stringValue":"Mac OS X 13.4.1"}},{"key":"os.type","value":{"stringValue":"darwin"}},{"key":"process.command_args","value":{"arrayValue":{"values":[{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"},{"stringValue":"-javaagent:./../.otel/opentelemetry-javaagent-1.28.0.jar"},{"stringValue":"-Dotel.instrumentation.logback-appender.experimental-log-attributes=true"},{"stringValue":"-DshippingServiceUrl=http://localhost:8088/"},{"stringValue":"-jar"},{"stringValue":"target/checkout-1.1-SNAPSHOT.jar"}]}}},{"key":"process.executable.path","value":{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"}},{"key":"process.pid","value":{"intValue":"1731"}},{"key":"process.runtime.description","value":{"stringValue":"Homebrew OpenJDK 64-Bit Server VM 20.0.1"}},{"key":"process.runtime.name","value":{"stringValue":"OpenJDK Runtime Environment"}},{"key":"process.runtime.version","value":{"stringValue":"20.0.1"}},{"key":"service.name","value":{"stringValue":"checkout"}},{"key":"service.namespace","value":{"stringValue":"checkout"}},{"key":"service.version","value":{"stringValue":"1.0-SNAPSHOT"}},{"key":"telemetry.auto.version","value":{"stringValue":"1.28.0"}},{"key":"telemetry.sdk.language","value":{"stringValue":"java"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.version","value":{"stringValue":"1.28.0"}}]},"scopeSpans":[{"scope":{"name":"io.opentelemetry.grpc-1.6","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"90914a6951fa987a","parentSpanId":"2ded621925317e54","name":"com.mycompany.checkout.CheckoutService/PlaceOrder","kind":2,"startTimeUnixNano":"1691012745122837000","endTimeUnixNano":"1691012745185315692","attributes":[{"key":"rpc.grpc.status_code","value":{"intValue":"0"}},{"key":"rpc.method","value":{"stringValue":"PlaceOrder"}},{"key":"rpc.service","value":{"stringValue":"com.mycompany.checkout.CheckoutService"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.sock.peer.port","value":{"intValue":"53302"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"thread.id","value":{"intValue":"381"}},{"key":"rpc.system","value":{"stringValue":"grpc"}},{"key":"thread.name","value":{"stringValue":"grpc-default-executor-50"}},{"key":"net.host.port","value":{"intValue":"50051"}}],"events":[{"timeUnixNano":"1691012745122914359","name":"message","attributes":[{"key":"message.id","value":{"intValue":"1"}},{"key":"message.type","value":{"stringValue":"RECEIVED"}}]},{"timeUnixNano":"1691012745185299461","name":"message","attributes":[{"key":"message.id","value":{"intValue":"2"}},{"key":"message.type","value":{"stringValue":"SENT"}}]}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"5660ea064d587e48","parentSpanId":"9d42ff61c2a7c8ba","name":"com.mycompany.checkout.CheckoutService/PlaceOrder","kind":2,"startTimeUnixNano":"1691012748314719000","endTimeUnixNano":"1691012748374234545","attributes":[{"key":"rpc.grpc.status_code","value":{"intValue":"0"}},{"key":"rpc.method","value":{"stringValue":"PlaceOrder"}},{"key":"rpc.service","value":{"stringValue":"com.mycompany.checkout.CheckoutService"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.sock.peer.port","value":{"intValue":"53302"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"thread.id","value":{"intValue":"381"}},{"key":"rpc.system","value":{"stringValue":"grpc"}},{"key":"thread.name","value":{"stringValue":"grpc-default-executor-50"}},{"key":"net.host.port","value":{"intValue":"50051"}}],"events":[{"timeUnixNano":"1691012748314764619","name":"message","attributes":[{"key":"message.id","value":{"intValue":"1"}},{"key":"message.type","value":{"stringValue":"RECEIVED"}}]},{"timeUnixNano":"1691012748374205777","name":"message","attributes":[{"key":"message.id","value":{"intValue":"2"}},{"key":"message.type","value":{"stringValue":"SENT"}}]}],"status":{}}]},{"scope":{"name":"io.opentelemetry.java-http-client","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"d37a79c4f4bc769d","parentSpanId":"90914a6951fa987a","name":"POST","kind":3,"startTimeUnixNano":"1691012745184161415","endTimeUnixNano":"1691012745185125305","attributes":[{"key":"thread.id","value":{"intValue":"381"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"thread.name","value":{"stringValue":"grpc-default-executor-50"}},{"key":"http.method","value":{"stringValue":"POST"}},{"key":"net.peer.port","value":{"intValue":"8088"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.url","value":{"stringValue":"http://localhost:8088/shipOrder"}}],"events":[{"timeUnixNano":"1691012745185084382","name":"exception","attributes":[{"key":"exception.stacktrace","value":{"stringValue":"java.net.ConnectException\n\tat java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:896)\n\tat java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133)\n\tat com.mycompany.checkout.CheckoutServiceServer$CheckoutServiceImpl.placeOrder(CheckoutServiceServer.java:108)\n\tat com.mycompany.checkout.CheckoutServiceGrpc$MethodHandlers.invoke(CheckoutServiceGrpc.java:210)\n\tat io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:182)\n\tat io.grpc.PartialForwardingServerCallListener.onHalfClose(PartialForwardingServerCallListener.java:35)\n\tat io.grpc.ForwardingServerCallListener.onHalfClose(ForwardingServerCallListener.java:23)\n\tat io.grpc.ForwardingServerCallListener$SimpleForwardingServerCallListener.onHalfClose(ForwardingServerCallListener.java:40)\n\tat io.grpc.Contexts$ContextualizedServerCallListener.onHalfClose(Contexts.java:86)\n\tat io.opentelemetry.javaagent.shaded.instrumentation.grpc.v1_6.TracingServerInterceptor$TracingServerCall$TracingServerCallListener.onHalfClose(TracingServerInterceptor.java:139)\n\tat io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:346)\n\tat io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:860)\n\tat io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)\n\tat io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)\n\tat java.base/java.lang.Thread.run(Thread.java:1623)\nCaused by: java.net.ConnectException\n\tat java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1053)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:224)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:259)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$2(PlainHttpConnection.java:235)\n\tat java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)\n\tat java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)\n\tat java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)\n\tat java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773)\n\t... 3 more\nCaused by: java.nio.channels.ClosedChannelException\n\tat java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:202)\n\tat java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:786)\n\tat java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:874)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:208)\n\tat java.base/java.security.AccessController.doPrivileged(AccessController.java:571)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:210)\n\t... 9 more\n"}},{"key":"exception.type","value":{"stringValue":"java.net.ConnectException"}}]}],"status":{"code":2}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"074a28f3e6da7eba","parentSpanId":"5660ea064d587e48","name":"POST","kind":3,"startTimeUnixNano":"1691012748373115707","endTimeUnixNano":"1691012748374070204","attributes":[{"key":"thread.id","value":{"intValue":"381"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"thread.name","value":{"stringValue":"grpc-default-executor-50"}},{"key":"http.method","value":{"stringValue":"POST"}},{"key":"net.peer.port","value":{"intValue":"8088"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.url","value":{"stringValue":"http://localhost:8088/shipOrder"}}],"events":[{"timeUnixNano":"1691012748374045596","name":"exception","attributes":[{"key":"exception.stacktrace","value":{"stringValue":"java.net.ConnectException\n\tat java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:896)\n\tat java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133)\n\tat com.mycompany.checkout.CheckoutServiceServer$CheckoutServiceImpl.placeOrder(CheckoutServiceServer.java:108)\n\tat com.mycompany.checkout.CheckoutServiceGrpc$MethodHandlers.invoke(CheckoutServiceGrpc.java:210)\n\tat io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:182)\n\tat io.grpc.PartialForwardingServerCallListener.onHalfClose(PartialForwardingServerCallListener.java:35)\n\tat io.grpc.ForwardingServerCallListener.onHalfClose(ForwardingServerCallListener.java:23)\n\tat io.grpc.ForwardingServerCallListener$SimpleForwardingServerCallListener.onHalfClose(ForwardingServerCallListener.java:40)\n\tat io.grpc.Contexts$ContextualizedServerCallListener.onHalfClose(Contexts.java:86)\n\tat io.opentelemetry.javaagent.shaded.instrumentation.grpc.v1_6.TracingServerInterceptor$TracingServerCall$TracingServerCallListener.onHalfClose(TracingServerInterceptor.java:139)\n\tat io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:346)\n\tat io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:860)\n\tat io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)\n\tat io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)\n\tat java.base/java.lang.Thread.run(Thread.java:1623)\nCaused by: java.net.ConnectException\n\tat java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1053)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:224)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:259)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$2(PlainHttpConnection.java:235)\n\tat java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)\n\tat java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)\n\tat java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)\n\tat java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773)\n\t... 3 more\nCaused by: java.nio.channels.ClosedChannelException\n\tat java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:202)\n\tat java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:786)\n\tat java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:874)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:208)\n\tat java.base/java.security.AccessController.doPrivileged(AccessController.java:571)\n\tat java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:210)\n\t... 9 more\n"}},{"key":"exception.type","value":{"stringValue":"java.net.ConnectException"}}]}],"status":{"code":2}}]}],"schemaUrl":"https://opentelemetry.io/schemas/1.20.0"}]} -{"resourceSpans":[{"resource":{"attributes":[{"key":"cloud.account.id","value":{"stringValue":"mycompany-prod"}},{"key":"cloud.availability_zone","value":{"stringValue":"us-central1-a"}},{"key":"cloud.provider","value":{"stringValue":"gcp"}},{"key":"deployment.environment","value":{"stringValue":"staging"}},{"key":"host.arch","value":{"stringValue":"amd64"}},{"key":"host.id","value":{"stringValue":"5929043986934855635"}},{"key":"host.name","value":{"stringValue":"gke-dev-us-central-0-otel-n2s4-1-f04acab8-dxqq-1.mycompany-prod.internal"}},{"key":"k8s.cluster.name","value":{"stringValue":"prod-us-central-0"}},{"key":"k8s.namespace.name","value":{"stringValue":"ecommerce"}},{"key":"k8s.node.name","value":{"stringValue":"gke-dev-us-central-0-otel-n2s4-1-f04acab8-dxqq-1"}},{"key":"k8s.pod.name","value":{"stringValue":"ecommerce-frontend-5b7b9db9ff-sh828"}},{"key":"os.description","value":{"stringValue":"Mac OS X 13.4.1"}},{"key":"os.type","value":{"stringValue":"darwin"}},{"key":"process.command_args","value":{"arrayValue":{"values":[{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"},{"stringValue":"-javaagent:./../.otel/opentelemetry-javaagent-1.28.0.jar"},{"stringValue":"-Dotel.instrumentation.logback-appender.experimental-log-attributes=true"},{"stringValue":"-Dserver.port=8080"},{"stringValue":"-jar"},{"stringValue":"target/frontend-1.1-SNAPSHOT.jar"}]}}},{"key":"process.executable.path","value":{"stringValue":"/usr/local/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java"}},{"key":"process.pid","value":{"intValue":"40197"}},{"key":"process.runtime.description","value":{"stringValue":"Homebrew OpenJDK 64-Bit Server VM 20.0.1"}},{"key":"process.runtime.name","value":{"stringValue":"OpenJDK Runtime Environment"}},{"key":"process.runtime.version","value":{"stringValue":"20.0.1"}},{"key":"service.instance.id","value":{"stringValue":"instance-1"}},{"key":"service.name","value":{"stringValue":"frontend"}},{"key":"service.namespace","value":{"stringValue":"frontend"}},{"key":"service.version","value":{"stringValue":"1.0-SNAPSHOT"}},{"key":"telemetry.auto.version","value":{"stringValue":"1.28.0"}},{"key":"telemetry.sdk.language","value":{"stringValue":"java"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.version","value":{"stringValue":"1.28.0"}}]},"scopeSpans":[{"scope":{"name":"io.opentelemetry.lettuce-5.1","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"1e5660d3e6dd2017","parentSpanId":"882c055904b9f5b1","name":"GET","kind":3,"startTimeUnixNano":"1691012745118529189","endTimeUnixNano":"1691012745118738962","attributes":[{"key":"db.system","value":{"stringValue":"redis"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"db.statement","value":{"stringValue":"GET productCache::1"}},{"key":"net.sock.peer.name","value":{"stringValue":"localhost"}},{"key":"net.sock.peer.port","value":{"intValue":"6379"}},{"key":"thread.name","value":{"stringValue":"lettuce-nioEventLoop-4-1"}},{"key":"thread.id","value":{"intValue":"71"}}],"events":[{"timeUnixNano":"1691012745118541587","name":"redis.encode.start"},{"timeUnixNano":"1691012745118547300","name":"redis.encode.end"}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"56bb43be53b9cc18","parentSpanId":"882c055904b9f5b1","name":"GET","kind":3,"startTimeUnixNano":"1691012745118801746","endTimeUnixNano":"1691012745118977862","attributes":[{"key":"db.system","value":{"stringValue":"redis"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"db.statement","value":{"stringValue":"GET productCache::1"}},{"key":"net.sock.peer.name","value":{"stringValue":"localhost"}},{"key":"net.sock.peer.port","value":{"intValue":"6379"}},{"key":"thread.name","value":{"stringValue":"lettuce-nioEventLoop-4-1"}},{"key":"thread.id","value":{"intValue":"71"}}],"events":[{"timeUnixNano":"1691012745118806260","name":"redis.encode.start"},{"timeUnixNano":"1691012745118811096","name":"redis.encode.end"}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"ccaa34d01e267956","parentSpanId":"882c055904b9f5b1","name":"SET","kind":3,"startTimeUnixNano":"1691012745119873814","endTimeUnixNano":"1691012745120005124","attributes":[{"key":"db.system","value":{"stringValue":"redis"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"db.statement","value":{"stringValue":"SET productCache::1 ? ? ?"}},{"key":"net.sock.peer.name","value":{"stringValue":"localhost"}},{"key":"net.sock.peer.port","value":{"intValue":"6379"}},{"key":"thread.name","value":{"stringValue":"lettuce-nioEventLoop-4-1"}},{"key":"thread.id","value":{"intValue":"71"}}],"events":[{"timeUnixNano":"1691012745119885826","name":"redis.encode.start"},{"timeUnixNano":"1691012745119897291","name":"redis.encode.end"}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"a2393f954e75820c","parentSpanId":"b079f1efae3496f7","name":"GET","kind":3,"startTimeUnixNano":"1691012748311208912","endTimeUnixNano":"1691012748311360868","attributes":[{"key":"db.system","value":{"stringValue":"redis"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"db.statement","value":{"stringValue":"GET productCache::9"}},{"key":"net.sock.peer.name","value":{"stringValue":"localhost"}},{"key":"net.sock.peer.port","value":{"intValue":"6379"}},{"key":"thread.name","value":{"stringValue":"lettuce-nioEventLoop-4-1"}},{"key":"thread.id","value":{"intValue":"71"}}],"events":[{"timeUnixNano":"1691012748311250112","name":"redis.encode.start"},{"timeUnixNano":"1691012748311254997","name":"redis.encode.end"}],"status":{}}]},{"scope":{"name":"io.opentelemetry.spring-webmvc-6.0","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"09d454e9cf7d3359","parentSpanId":"ca4622c5f4b77bc0","name":"OrderController.create","kind":1,"startTimeUnixNano":"1691012744031889185","endTimeUnixNano":"1691012745185762104","attributes":[{"key":"order_price_range","value":{"stringValue":"large"}},{"key":"shipping_method","value":{"stringValue":"express"}},{"key":"payment_method","value":{"stringValue":"AMEX"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"customer_id","value":{"stringValue":"customer-45"}},{"key":"thread.id","value":{"intValue":"63"}},{"key":"shipping_country","value":{"stringValue":"FR"}}],"events":[{"timeUnixNano":"1691012744032107866","name":"order-creation","attributes":[{"key":"customer_id","value":{"stringValue":"customer-45"}},{"key":"order_price","value":{"doubleValue":300}},{"key":"payment_method","value":{"stringValue":"AMEX"}},{"key":"shipping_country","value":{"stringValue":"FR"}},{"key":"shipping_method","value":{"stringValue":"express"}}]}],"status":{}},{"traceId":"d74b95b30d50ba650cd45eb238ffa5b3","spanId":"ac6df0d67c7af19e","parentSpanId":"dfb19e54dd11425e","name":"ProductController.getProducts","kind":1,"startTimeUnixNano":"1691012746186965944","endTimeUnixNano":"1691012746188158125","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-3"}},{"key":"thread.id","value":{"intValue":"56"}}],"status":{}},{"traceId":"1b70978af8b570099f4912f9f95d9418","spanId":"b998e6e707df5a53","parentSpanId":"132662b9b74f06bb","name":"ParameterizableViewController.handleRequest","kind":1,"startTimeUnixNano":"1691012746188750334","endTimeUnixNano":"1691012746188753601","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-4"}},{"key":"thread.id","value":{"intValue":"57"}}],"status":{}},{"traceId":"1b70978af8b570099f4912f9f95d9418","spanId":"c16078afe1be1d1b","parentSpanId":"398fd45a209719a4","name":"ResourceHttpRequestHandler.handleRequest","kind":1,"startTimeUnixNano":"1691012746188862909","endTimeUnixNano":"1691012746190431759","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-4"}},{"key":"thread.id","value":{"intValue":"57"}}],"status":{}},{"traceId":"1b70978af8b570099f4912f9f95d9418","spanId":"398fd45a209719a4","parentSpanId":"132662b9b74f06bb","name":"Render forward:index.html","kind":1,"startTimeUnixNano":"1691012746188757080","endTimeUnixNano":"1691012746190450380","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-4"}},{"key":"thread.id","value":{"intValue":"57"}}],"status":{}},{"traceId":"2ec8c44b98317e2067cfea345808d3d1","spanId":"62424ad3c2f877ce","parentSpanId":"620c514c23c84f0d","name":"ProductController.getProducts","kind":1,"startTimeUnixNano":"1691012746190994817","endTimeUnixNano":"1691012746191924166","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-2"}},{"key":"thread.id","value":{"intValue":"55"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"53bda67833160f36","parentSpanId":"8e8c32455e20268f","name":"OrderController.create","kind":1,"startTimeUnixNano":"1691012748193140020","endTimeUnixNano":"1691012748374720803","attributes":[{"key":"order_price_range","value":{"stringValue":"small"}},{"key":"shipping_method","value":{"stringValue":"standard"}},{"key":"payment_method","value":{"stringValue":"VISA"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"customer_id","value":{"stringValue":"customer-13"}},{"key":"thread.id","value":{"intValue":"59"}},{"key":"shipping_country","value":{"stringValue":"FR"}}],"events":[{"timeUnixNano":"1691012748193273891","name":"order-creation","attributes":[{"key":"customer_id","value":{"stringValue":"customer-13"}},{"key":"order_price","value":{"doubleValue":5}},{"key":"payment_method","value":{"stringValue":"VISA"}},{"key":"shipping_country","value":{"stringValue":"FR"}},{"key":"shipping_method","value":{"stringValue":"standard"}}]}],"status":{}}]},{"scope":{"name":"io.opentelemetry.rabbitmq-2.7","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"f6a8e9caa720e3f7","parentSpanId":"09d454e9cf7d3359","name":"ecommerce-exchange publish","kind":4,"startTimeUnixNano":"1691012745122472372","endTimeUnixNano":"1691012745122507242","attributes":[{"key":"messaging.system","value":{"stringValue":"rabbitmq"}},{"key":"messaging.rabbitmq.destination.routing_key","value":{"stringValue":"queue.order"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"messaging.message.payload_size_bytes","value":{"intValue":"46"}},{"key":"messaging.destination.name","value":{"stringValue":"ecommerce-exchange"}},{"key":"net.sock.peer.port","value":{"intValue":"5672"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"2e1d1981ae5d9f61","parentSpanId":"53bda67833160f36","name":"ecommerce-exchange publish","kind":4,"startTimeUnixNano":"1691012748314367296","endTimeUnixNano":"1691012748314419233","attributes":[{"key":"messaging.system","value":{"stringValue":"rabbitmq"}},{"key":"messaging.rabbitmq.destination.routing_key","value":{"stringValue":"queue.order"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"messaging.message.payload_size_bytes","value":{"intValue":"46"}},{"key":"messaging.destination.name","value":{"stringValue":"ecommerce-exchange"}},{"key":"net.sock.peer.port","value":{"intValue":"5672"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.opentelemetry-instrumentation-annotations-1.16","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"882c055904b9f5b1","parentSpanId":"09d454e9cf7d3359","name":"ProductServiceImpl.getProduct","kind":1,"startTimeUnixNano":"1691012745118452840","endTimeUnixNano":"1691012745120028758","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.service.ProductServiceImpl"}},{"key":"productId","value":{"intValue":"1"}},{"key":"code.function","value":{"stringValue":"getProduct"}},{"key":"cache.miss","value":{"boolValue":false}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"b079f1efae3496f7","parentSpanId":"53bda67833160f36","name":"ProductServiceImpl.getProduct","kind":1,"startTimeUnixNano":"1691012748311115765","endTimeUnixNano":"1691012748311416671","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.service.ProductServiceImpl"}},{"key":"productId","value":{"intValue":"9"}},{"key":"code.function","value":{"stringValue":"getProduct"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.http-url-connection","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"57d6eb86f42241f3","parentSpanId":"09d454e9cf7d3359","name":"GET","kind":3,"startTimeUnixNano":"1691012744032239583","endTimeUnixNano":"1691012745093386273","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"net.peer.port","value":{"intValue":"8081"}},{"key":"http.response_content_length","value":{"intValue":"2"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.url","value":{"stringValue":"http://localhost:8081/fraud/checkOrder?orderPrice=300.0\u0026customerIpAddress=127.0.0.1\u0026shippingCountry=FR"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"e0bcf153c85d7899","parentSpanId":"09d454e9cf7d3359","name":"GET","kind":3,"startTimeUnixNano":"1691012745093518322","endTimeUnixNano":"1691012745116098260","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"net.peer.name","value":{"stringValue":"example.com"}},{"key":"http.response_content_length","value":{"intValue":"1256"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.url","value":{"stringValue":"https://example.com/"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"7600d1e69dd28a8e","parentSpanId":"53bda67833160f36","name":"GET","kind":3,"startTimeUnixNano":"1691012748193383667","endTimeUnixNano":"1691012748303751512","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"net.peer.port","value":{"intValue":"8081"}},{"key":"http.response_content_length","value":{"intValue":"2"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.url","value":{"stringValue":"http://localhost:8081/fraud/checkOrder?orderPrice=5.0\u0026customerIpAddress=127.0.0.1\u0026shippingCountry=FR"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"971bd3c39c480a0b","parentSpanId":"53bda67833160f36","name":"GET","kind":3,"startTimeUnixNano":"1691012748303850277","endTimeUnixNano":"1691012748309203593","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"net.peer.name","value":{"stringValue":"example.com"}},{"key":"http.response_content_length","value":{"intValue":"1256"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.url","value":{"stringValue":"https://example.com/"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.spring-data-1.8","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"158ffad0b607c63d","parentSpanId":"09d454e9cf7d3359","name":"OrderRepository.save","kind":1,"startTimeUnixNano":"1691012745116772713","endTimeUnixNano":"1691012745117792349","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.OrderRepository"}},{"key":"code.function","value":{"stringValue":"save"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"acf500b0c9ecc4c4","parentSpanId":"882c055904b9f5b1","name":"ProductRepository.doFindById","kind":1,"startTimeUnixNano":"1691012745119003973","endTimeUnixNano":"1691012745119626232","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.ProductRepository"}},{"key":"code.function","value":{"stringValue":"doFindByIdWithThrottle"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"74aab357df598cde","parentSpanId":"09d454e9cf7d3359","name":"OrderProductRepository.save","kind":1,"startTimeUnixNano":"1691012745120292885","endTimeUnixNano":"1691012745120636740","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.OrderProductRepository"}},{"key":"code.function","value":{"stringValue":"save"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"4e9d8e95f8329dd9","parentSpanId":"09d454e9cf7d3359","name":"OrderRepository.save","kind":1,"startTimeUnixNano":"1691012745121552773","endTimeUnixNano":"1691012745122302896","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.OrderRepository"}},{"key":"code.function","value":{"stringValue":"save"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"d74b95b30d50ba650cd45eb238ffa5b3","spanId":"0b0c2a006b6ecc86","parentSpanId":"ac6df0d67c7af19e","name":"ProductRepository.findAll","kind":1,"startTimeUnixNano":"1691012746187308783","endTimeUnixNano":"1691012746187836101","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.ProductRepository"}},{"key":"code.function","value":{"stringValue":"findAll"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-3"}},{"key":"thread.id","value":{"intValue":"56"}}],"status":{}},{"traceId":"2ec8c44b98317e2067cfea345808d3d1","spanId":"1faf1340400ae3a9","parentSpanId":"62424ad3c2f877ce","name":"ProductRepository.findAll","kind":1,"startTimeUnixNano":"1691012746191098461","endTimeUnixNano":"1691012746191570891","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.ProductRepository"}},{"key":"code.function","value":{"stringValue":"findAll"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-2"}},{"key":"thread.id","value":{"intValue":"55"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"245b147c9a10cf68","parentSpanId":"53bda67833160f36","name":"OrderRepository.save","kind":1,"startTimeUnixNano":"1691012748309570836","endTimeUnixNano":"1691012748310156584","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.OrderRepository"}},{"key":"code.function","value":{"stringValue":"save"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"9c36245cbf7cdc30","parentSpanId":"53bda67833160f36","name":"OrderProductRepository.save","kind":1,"startTimeUnixNano":"1691012748311554796","endTimeUnixNano":"1691012748312080399","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.OrderProductRepository"}},{"key":"code.function","value":{"stringValue":"save"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"ccda511d46e511b4","parentSpanId":"53bda67833160f36","name":"OrderRepository.save","kind":1,"startTimeUnixNano":"1691012748313472982","endTimeUnixNano":"1691012748314169184","attributes":[{"key":"code.namespace","value":{"stringValue":"com.mycompany.ecommerce.repository.OrderRepository"}},{"key":"code.function","value":{"stringValue":"save"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.hibernate-6.0","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"157b907ee0276803","parentSpanId":"158ffad0b607c63d","name":"Session.persist com.mycompany.ecommerce.model.Order","kind":1,"startTimeUnixNano":"1691012745116791492","endTimeUnixNano":"1691012745117767468","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"d193df8899966f15","parentSpanId":"09d454e9cf7d3359","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012745117803600","endTimeUnixNano":"1691012745118339972","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"0a46c57c6b710e6b","parentSpanId":"acf500b0c9ecc4c4","name":"Session.find com.mycompany.ecommerce.model.Product","kind":1,"startTimeUnixNano":"1691012745119034771","endTimeUnixNano":"1691012745119607896","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"29558eac395390bd","parentSpanId":"09d454e9cf7d3359","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012745120051058","endTimeUnixNano":"1691012745120205768","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"7e21fbc05591ce1c","parentSpanId":"74aab357df598cde","name":"Session.merge com.mycompany.ecommerce.model.OrderProduct","kind":1,"startTimeUnixNano":"1691012745120309149","endTimeUnixNano":"1691012745120624232","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"b16ed457ada99c5b","parentSpanId":"09d454e9cf7d3359","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012745120640660","endTimeUnixNano":"1691012745121458148","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"de90d3e9a5eed6e7","parentSpanId":"4e9d8e95f8329dd9","name":"Session.merge com.mycompany.ecommerce.model.Order","kind":1,"startTimeUnixNano":"1691012745121565866","endTimeUnixNano":"1691012745122290487","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"8c9cfa28c76df31e","parentSpanId":"09d454e9cf7d3359","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012745122307059","endTimeUnixNano":"1691012745122437515","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"d74b95b30d50ba650cd45eb238ffa5b3","spanId":"cc77081495c5b5db","parentSpanId":"0b0c2a006b6ecc86","name":"SELECT com.mycompany.ecommerce.model.Product","kind":1,"startTimeUnixNano":"1691012746187386671","endTimeUnixNano":"1691012746187812408","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-3"}},{"key":"thread.id","value":{"intValue":"56"}}],"status":{}},{"traceId":"d74b95b30d50ba650cd45eb238ffa5b3","spanId":"efe5901941280c2a","parentSpanId":"ac6df0d67c7af19e","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012746187851057","endTimeUnixNano":"1691012746187984275","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-3"}},{"key":"thread.id","value":{"intValue":"56"}}],"status":{}},{"traceId":"2ec8c44b98317e2067cfea345808d3d1","spanId":"a6669a6f6c947009","parentSpanId":"1faf1340400ae3a9","name":"SELECT com.mycompany.ecommerce.model.Product","kind":1,"startTimeUnixNano":"1691012746191158253","endTimeUnixNano":"1691012746191549131","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-2"}},{"key":"thread.id","value":{"intValue":"55"}}],"status":{}},{"traceId":"2ec8c44b98317e2067cfea345808d3d1","spanId":"d95993fa001a6d1f","parentSpanId":"62424ad3c2f877ce","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012746191588356","endTimeUnixNano":"1691012746191760003","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-2"}},{"key":"thread.id","value":{"intValue":"55"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"67e87dc46c24535f","parentSpanId":"245b147c9a10cf68","name":"Session.persist com.mycompany.ecommerce.model.Order","kind":1,"startTimeUnixNano":"1691012748309590028","endTimeUnixNano":"1691012748310137972","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"15485bb7c7581359","parentSpanId":"53bda67833160f36","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012748310163489","endTimeUnixNano":"1691012748311002888","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"1ef212c2c1e81bb8","parentSpanId":"53bda67833160f36","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012748311428152","endTimeUnixNano":"1691012748311434008","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"88cdfd71c78fb1c8","parentSpanId":"9c36245cbf7cdc30","name":"Session.merge com.mycompany.ecommerce.model.OrderProduct","kind":1,"startTimeUnixNano":"1691012748311573740","endTimeUnixNano":"1691012748312063001","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"4837ee06e298135d","parentSpanId":"53bda67833160f36","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012748312086185","endTimeUnixNano":"1691012748313343338","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"5c62bbb79b40748a","parentSpanId":"ccda511d46e511b4","name":"Session.merge com.mycompany.ecommerce.model.Order","kind":1,"startTimeUnixNano":"1691012748313490424","endTimeUnixNano":"1691012748314150340","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"0fa6afca617e4321","parentSpanId":"53bda67833160f36","name":"Transaction.commit","kind":1,"startTimeUnixNano":"1691012748314177224","endTimeUnixNano":"1691012748314312762","attributes":[{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.tomcat-10.0","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"ca4622c5f4b77bc0","parentSpanId":"","name":"POST /api/orders","kind":2,"startTimeUnixNano":"1691012744031702000","endTimeUnixNano":"1691012745185840517","attributes":[{"key":"http.status_code","value":{"intValue":"201"}},{"key":"http.route","value":{"stringValue":"/api/orders"}},{"key":"net.host.port","value":{"intValue":"8080"}},{"key":"net.sock.host.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"net.sock.peer.port","value":{"intValue":"58154"}},{"key":"http.method","value":{"stringValue":"POST"}},{"key":"thread.id","value":{"intValue":"63"}},{"key":"user_agent.original","value":{"stringValue":"k6/0.45.0 (https://k6.io/)"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"http.target","value":{"stringValue":"/api/orders"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"http.request_content_length","value":{"intValue":"198"}}],"status":{}},{"traceId":"d74b95b30d50ba650cd45eb238ffa5b3","spanId":"dfb19e54dd11425e","parentSpanId":"","name":"GET /api/products","kind":2,"startTimeUnixNano":"1691012746186792000","endTimeUnixNano":"1691012746188293199","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.route","value":{"stringValue":"/api/products"}},{"key":"net.host.port","value":{"intValue":"8080"}},{"key":"net.sock.host.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"net.sock.peer.port","value":{"intValue":"58154"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"56"}},{"key":"user_agent.original","value":{"stringValue":"k6/0.45.0 (https://k6.io/)"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"http.target","value":{"stringValue":"/api/products"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-3"}}],"status":{}},{"traceId":"1b70978af8b570099f4912f9f95d9418","spanId":"132662b9b74f06bb","parentSpanId":"","name":"GET /","kind":2,"startTimeUnixNano":"1691012746188601000","endTimeUnixNano":"1691012746190544228","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.response_content_length","value":{"intValue":"1954"}},{"key":"http.route","value":{"stringValue":"/"}},{"key":"net.host.port","value":{"intValue":"8080"}},{"key":"net.sock.host.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"net.sock.peer.port","value":{"intValue":"58154"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"57"}},{"key":"user_agent.original","value":{"stringValue":"k6/0.45.0 (https://k6.io/)"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"http.target","value":{"stringValue":"/"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-4"}}],"status":{}},{"traceId":"2ec8c44b98317e2067cfea345808d3d1","spanId":"620c514c23c84f0d","parentSpanId":"","name":"GET /api/products","kind":2,"startTimeUnixNano":"1691012746190841000","endTimeUnixNano":"1691012746192014792","attributes":[{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.route","value":{"stringValue":"/api/products"}},{"key":"net.host.port","value":{"intValue":"8080"}},{"key":"net.sock.host.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"net.sock.peer.port","value":{"intValue":"58154"}},{"key":"http.method","value":{"stringValue":"GET"}},{"key":"thread.id","value":{"intValue":"55"}},{"key":"user_agent.original","value":{"stringValue":"k6/0.45.0 (https://k6.io/)"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"http.target","value":{"stringValue":"/api/products"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-2"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"8e8c32455e20268f","parentSpanId":"","name":"POST /api/orders","kind":2,"startTimeUnixNano":"1691012748192966000","endTimeUnixNano":"1691012748374828122","attributes":[{"key":"http.status_code","value":{"intValue":"201"}},{"key":"http.route","value":{"stringValue":"/api/orders"}},{"key":"net.host.port","value":{"intValue":"8080"}},{"key":"net.sock.host.addr","value":{"stringValue":"127.0.0.1"}},{"key":"net.protocol.name","value":{"stringValue":"http"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.protocol.version","value":{"stringValue":"1.1"}},{"key":"net.sock.peer.port","value":{"intValue":"58154"}},{"key":"http.method","value":{"stringValue":"POST"}},{"key":"thread.id","value":{"intValue":"59"}},{"key":"user_agent.original","value":{"stringValue":"k6/0.45.0 (https://k6.io/)"}},{"key":"net.host.name","value":{"stringValue":"localhost"}},{"key":"http.target","value":{"stringValue":"/api/orders"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"http.request_content_length","value":{"intValue":"202"}}],"status":{}}]},{"scope":{"name":"io.opentelemetry.grpc-1.6","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"2ded621925317e54","parentSpanId":"09d454e9cf7d3359","name":"com.mycompany.checkout.CheckoutService/PlaceOrder","kind":3,"startTimeUnixNano":"1691012745122522462","endTimeUnixNano":"1691012745185480911","attributes":[{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"rpc.method","value":{"stringValue":"PlaceOrder"}},{"key":"net.peer.port","value":{"intValue":"50051"}},{"key":"rpc.service","value":{"stringValue":"com.mycompany.checkout.CheckoutService"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"rpc.grpc.status_code","value":{"intValue":"0"}},{"key":"rpc.system","value":{"stringValue":"grpc"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"events":[{"timeUnixNano":"1691012745122597237","name":"message","attributes":[{"key":"message.id","value":{"intValue":"1"}},{"key":"message.type","value":{"stringValue":"SENT"}}]},{"timeUnixNano":"1691012745185446739","name":"message","attributes":[{"key":"message.id","value":{"intValue":"2"}},{"key":"message.type","value":{"stringValue":"RECEIVED"}}]}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"9d42ff61c2a7c8ba","parentSpanId":"53bda67833160f36","name":"com.mycompany.checkout.CheckoutService/PlaceOrder","kind":3,"startTimeUnixNano":"1691012748314435092","endTimeUnixNano":"1691012748374399624","attributes":[{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"rpc.method","value":{"stringValue":"PlaceOrder"}},{"key":"net.peer.port","value":{"intValue":"50051"}},{"key":"rpc.service","value":{"stringValue":"com.mycompany.checkout.CheckoutService"}},{"key":"net.sock.peer.addr","value":{"stringValue":"127.0.0.1"}},{"key":"rpc.grpc.status_code","value":{"intValue":"0"}},{"key":"rpc.system","value":{"stringValue":"grpc"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"events":[{"timeUnixNano":"1691012748314526895","name":"message","attributes":[{"key":"message.id","value":{"intValue":"1"}},{"key":"message.type","value":{"stringValue":"SENT"}}]},{"timeUnixNano":"1691012748374375393","name":"message","attributes":[{"key":"message.id","value":{"intValue":"2"}},{"key":"message.type","value":{"stringValue":"RECEIVED"}}]}],"status":{}}]},{"scope":{"name":"io.opentelemetry.jdbc","version":"1.28.0-alpha"},"spans":[{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"fd8cfa15bcc78f7f","parentSpanId":"09d454e9cf7d3359","name":"my_shopping_cart","kind":3,"startTimeUnixNano":"1691012745116356859","endTimeUnixNano":"1691012745116669754","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":""}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"96a24a70bb9c2d23","parentSpanId":"157b907ee0276803","name":"INSERT my_shopping_cart.orders","kind":3,"startTimeUnixNano":"1691012745116876116","endTimeUnixNano":"1691012745117643593","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"insert into orders (date_created,status) values (?,?)"}},{"key":"db.sql.table","value":{"stringValue":"orders"}},{"key":"db.operation","value":{"stringValue":"INSERT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"a80f1a824462f277","parentSpanId":"0a46c57c6b710e6b","name":"SELECT my_shopping_cart.product","kind":3,"startTimeUnixNano":"1691012745119116180","endTimeUnixNano":"1691012745119581346","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select p1_0.id,p1_0.name,p1_0.picture_url,p1_0.price from product p1_0 where p1_0.id=?"}},{"key":"db.sql.table","value":{"stringValue":"product"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"051211db6cef2732","parentSpanId":"7e21fbc05591ce1c","name":"SELECT my_shopping_cart.order_product","kind":3,"startTimeUnixNano":"1691012745120341362","endTimeUnixNano":"1691012745120599327","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select o1_0.order_id,o1_0.product_id,o1_0.quantity from order_product o1_0 where (o1_0.order_id,o1_0.product_id) in ((?,?))"}},{"key":"db.sql.table","value":{"stringValue":"order_product"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"1f71fa6aab2c97c4","parentSpanId":"b16ed457ada99c5b","name":"INSERT my_shopping_cart.order_product","kind":3,"startTimeUnixNano":"1691012745120677210","endTimeUnixNano":"1691012745121011642","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"insert into order_product (quantity,order_id,product_id) values (?,?,?)"}},{"key":"db.sql.table","value":{"stringValue":"order_product"}},{"key":"db.operation","value":{"stringValue":"INSERT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"82094104718c4439","parentSpanId":"de90d3e9a5eed6e7","name":"SELECT my_shopping_cart.orders","kind":3,"startTimeUnixNano":"1691012745121589004","endTimeUnixNano":"1691012745121881314","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select o1_0.id,o1_0.date_created,o1_0.status from orders o1_0 where o1_0.id=?"}},{"key":"db.sql.table","value":{"stringValue":"orders"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"5b584103c6fc5ddf423cb2fb6552d0f0","spanId":"06083b72226abe47","parentSpanId":"de90d3e9a5eed6e7","name":"SELECT my_shopping_cart.order_product","kind":3,"startTimeUnixNano":"1691012745121965433","endTimeUnixNano":"1691012745122270438","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select o1_0.order_id,o1_0.product_id,o1_0.quantity from order_product o1_0 where (o1_0.order_id,o1_0.product_id) in ((?,?))"}},{"key":"db.sql.table","value":{"stringValue":"order_product"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-10"}},{"key":"thread.id","value":{"intValue":"63"}}],"status":{}},{"traceId":"d74b95b30d50ba650cd45eb238ffa5b3","spanId":"f5cc77dadbffda70","parentSpanId":"ac6df0d67c7af19e","name":"my_shopping_cart","kind":3,"startTimeUnixNano":"1691012746187006703","endTimeUnixNano":"1691012746187205507","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":""}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-3"}},{"key":"thread.id","value":{"intValue":"56"}}],"status":{}},{"traceId":"d74b95b30d50ba650cd45eb238ffa5b3","spanId":"b646d469b7786147","parentSpanId":"cc77081495c5b5db","name":"SELECT my_shopping_cart.product","kind":3,"startTimeUnixNano":"1691012746187470952","endTimeUnixNano":"1691012746187769086","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select p1_0.id,p1_0.name,p1_0.picture_url,p1_0.price from product p1_0"}},{"key":"db.sql.table","value":{"stringValue":"product"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-3"}},{"key":"thread.id","value":{"intValue":"56"}}],"status":{}},{"traceId":"2ec8c44b98317e2067cfea345808d3d1","spanId":"7b49992eef42620b","parentSpanId":"a6669a6f6c947009","name":"SELECT my_shopping_cart.product","kind":3,"startTimeUnixNano":"1691012746191237896","endTimeUnixNano":"1691012746191505774","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select p1_0.id,p1_0.name,p1_0.picture_url,p1_0.price from product p1_0"}},{"key":"db.sql.table","value":{"stringValue":"product"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-2"}},{"key":"thread.id","value":{"intValue":"55"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"1573cd75be7940c7","parentSpanId":"53bda67833160f36","name":"my_shopping_cart","kind":3,"startTimeUnixNano":"1691012748309276978","endTimeUnixNano":"1691012748309458854","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":""}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"682b0bc68efc0791","parentSpanId":"67e87dc46c24535f","name":"INSERT my_shopping_cart.orders","kind":3,"startTimeUnixNano":"1691012748309651345","endTimeUnixNano":"1691012748310038697","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"insert into orders (date_created,status) values (?,?)"}},{"key":"db.sql.table","value":{"stringValue":"orders"}},{"key":"db.operation","value":{"stringValue":"INSERT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"65cc1ac871c46a9b","parentSpanId":"88cdfd71c78fb1c8","name":"SELECT my_shopping_cart.order_product","kind":3,"startTimeUnixNano":"1691012748311633963","endTimeUnixNano":"1691012748312029105","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select o1_0.order_id,o1_0.product_id,o1_0.quantity from order_product o1_0 where (o1_0.order_id,o1_0.product_id) in ((?,?))"}},{"key":"db.sql.table","value":{"stringValue":"order_product"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"7ca646ee79b3409c","parentSpanId":"4837ee06e298135d","name":"INSERT my_shopping_cart.order_product","kind":3,"startTimeUnixNano":"1691012748312138288","endTimeUnixNano":"1691012748312953873","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"insert into order_product (quantity,order_id,product_id) values (?,?,?)"}},{"key":"db.sql.table","value":{"stringValue":"order_product"}},{"key":"db.operation","value":{"stringValue":"INSERT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"5253f9f6b11adeaa","parentSpanId":"5c62bbb79b40748a","name":"SELECT my_shopping_cart.orders","kind":3,"startTimeUnixNano":"1691012748313523078","endTimeUnixNano":"1691012748313798878","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select o1_0.id,o1_0.date_created,o1_0.status from orders o1_0 where o1_0.id=?"}},{"key":"db.sql.table","value":{"stringValue":"orders"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}},{"traceId":"93c85b395f590f14532e3391657f7007","spanId":"766c47aac86bed7b","parentSpanId":"5c62bbb79b40748a","name":"SELECT my_shopping_cart.order_product","kind":3,"startTimeUnixNano":"1691012748313894735","endTimeUnixNano":"1691012748314116144","attributes":[{"key":"db.user","value":{"stringValue":"my_shopping_cart"}},{"key":"db.connection_string","value":{"stringValue":"postgresql://localhost:5432"}},{"key":"net.peer.name","value":{"stringValue":"localhost"}},{"key":"db.system","value":{"stringValue":"postgresql"}},{"key":"net.peer.port","value":{"intValue":"5432"}},{"key":"db.statement","value":{"stringValue":"select o1_0.order_id,o1_0.product_id,o1_0.quantity from order_product o1_0 where (o1_0.order_id,o1_0.product_id) in ((?,?))"}},{"key":"db.sql.table","value":{"stringValue":"order_product"}},{"key":"db.operation","value":{"stringValue":"SELECT"}},{"key":"db.name","value":{"stringValue":"my_shopping_cart"}},{"key":"thread.name","value":{"stringValue":"http-nio-8080-exec-6"}},{"key":"thread.id","value":{"intValue":"59"}}],"status":{}}]}],"schemaUrl":"https://opentelemetry.io/schemas/1.20.0"}]}