diff --git a/BUILD b/BUILD index 432594f4..699b78cc 100644 --- a/BUILD +++ b/BUILD @@ -10,6 +10,7 @@ EXAMPLE_TESTS = [ "cache", "cors", "csrf", + "dash0", "double-proxy", # "dynamic-config-cp", "dynamic-config-fs", @@ -56,6 +57,7 @@ filegroup( exclude = [ "cache/ci-responses.yaml", "cache/responses.yaml", + "dash0/otel-collector-config.yaml", "dynamic-config-fs/**/*", "jaeger-native-tracing/*", "opentelemetry/otel-collector-config.yaml", diff --git a/dash0/Dockerfile-opentelemetry b/dash0/Dockerfile-opentelemetry new file mode 100644 index 00000000..9ed9cdc3 --- /dev/null +++ b/dash0/Dockerfile-opentelemetry @@ -0,0 +1,11 @@ +FROM alpine:3.23@sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62 AS otelc_curl +RUN apk --update add curl + +FROM otel/opentelemetry-collector:0.151.0@sha256:49a12827519134ed72881a64247ea43fbf4bdac50cfa41ceb495fc1c684451e2 + +COPY --from=otelc_curl / / + +COPY ./otel-collector-config.yaml /etc/otel-collector-config.yaml +USER 0 +RUN chmod o+r /etc/otel-collector-config.yaml +USER nobody diff --git a/dash0/README.md b/dash0/README.md new file mode 100644 index 00000000..f5e0b3a7 --- /dev/null +++ b/dash0/README.md @@ -0,0 +1,2 @@ +To learn about this sandbox and for instructions on how to run it please head over +to the [envoy docs](https://www.envoyproxy.io/docs/envoy/latest/start/sandboxes/dash0) diff --git a/dash0/_static/dash0-ui-trace.png b/dash0/_static/dash0-ui-trace.png new file mode 100644 index 00000000..c037c13c Binary files /dev/null and b/dash0/_static/dash0-ui-trace.png differ diff --git a/dash0/_static/dash0-ui-traces.png b/dash0/_static/dash0-ui-traces.png new file mode 100644 index 00000000..c91ec748 Binary files /dev/null and b/dash0/_static/dash0-ui-traces.png differ diff --git a/dash0/docker-compose.yaml b/dash0/docker-compose.yaml new file mode 100644 index 00000000..365ac33b --- /dev/null +++ b/dash0/docker-compose.yaml @@ -0,0 +1,35 @@ +services: + envoy: + build: + context: . + dockerfile: ../shared/envoy/Dockerfile + depends_on: + dash0-collector: + condition: service_healthy + service-1: + condition: service_healthy + ports: + - "${PORT_PROXY:-10000}:10000" + + service-1: + build: + context: ../shared/python + target: aiohttp-tracing-service + environment: + - SERVICE_NAME=1 + + dash0-collector: + build: + context: . + dockerfile: Dockerfile-opentelemetry + environment: + - DASH0_AUTH_TOKEN=${DASH0_AUTH_TOKEN:-} + - DASH0_DATASET=${DASH0_DATASET:-default} + - DASH0_ENDPOINT=${DASH0_ENDPOINT:-ingress.eu-west-1.aws.dash0.com:4317} + command: ["--config=/etc/otel-collector-config.yaml"] + healthcheck: + test: ["CMD-SHELL", "curl -sf http://localhost:13133 || exit 1"] + interval: 1s + timeout: 120s + retries: 120 + start_period: 5s diff --git a/dash0/envoy.yaml b/dash0/envoy.yaml new file mode 100644 index 00000000..e47d72df --- /dev/null +++ b/dash0/envoy.yaml @@ -0,0 +1,74 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 10000 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress_http + tracing: + provider: + name: envoy.tracers.opentelemetry + typed_config: + "@type": type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig + grpc_service: + envoy_grpc: + cluster_name: dash0_collector + timeout: 0.250s + service_name: envoy-dash0-demo + route_config: + name: local_route + virtual_hosts: + - name: backend + domains: + - "*" + routes: + - match: + prefix: "/" + route: + cluster: service_cluster1 + decorator: + operation: routeToService1 + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + + clusters: + - name: service_cluster1 + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: service_cluster1 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: service-1 + port_value: 8080 + + - name: dash0_collector + connect_timeout: 1s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + load_assignment: + cluster_name: dash0_collector + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: dash0-collector + port_value: 4317 diff --git a/dash0/example.rst b/dash0/example.rst new file mode 100644 index 00000000..2634637e --- /dev/null +++ b/dash0/example.rst @@ -0,0 +1,107 @@ +.. _install_sandboxes_dash0: + +Dash0 tracing +============= + +.. sidebar:: Requirements + + .. include:: _include/docker-env-setup-link.rst + + :ref:`curl ` + Used to make HTTP requests. + + +.. note:: + + Before proceeding, please ensure you have a Dash0 account set up. + + If you don't already have one, you can `sign up for Dash0 here `_. + + +The Dash0 tracing sandbox demonstrates Envoy's :ref:`request tracing ` +capabilities using `Dash0 `_ as the tracing backend. + +In this example, a backend service is provided: + +- ``service-1`` + +An `OpenTelemetry Collector `_ is also provided, which +receives spans from Envoy and forwards them to your Dash0 organization over OTLP. + +The ``envoy`` service is exposed on port ``10000`` and the request flow is as follows: + + User -> ``envoy`` -> ``service-1`` + +The Envoy proxy is configured (:download:`envoy.yaml <_include/dash0/envoy.yaml>`) to generate a +span for each request and export it, over gRPC, to a cluster named ``dash0_collector`` pointing at +the local collector. The collector (:download:`otel-collector-config.yaml +<_include/dash0/otel-collector-config.yaml>`) in turn exports those spans to Dash0's OTLP ingress +endpoint, with your auth token and target dataset carried in the ``Authorization`` and +``Dash0-Dataset`` headers. + +Each span records the latency of the upstream call as well as information needed to correlate +the span with other related spans (e.g., the trace ID). + +Step 1: Get a Dash0 auth token and OTLP endpoint +************************************************* + +From your Dash0 organization settings, create an auth token and note the OTLP gRPC ingress +endpoint for your organization's region (for example ``ingress.eu-west-1.aws.dash0.com:4317``). + +Step 2: Build the sandbox +************************** + +Change to the ``dash0`` directory, and start the containers, with the following commands: + +.. code-block:: console + + $ pwd + examples/dash0 + $ export DASH0_AUTH_TOKEN= + $ export DASH0_DATASET= + $ export DASH0_ENDPOINT= + $ docker compose pull + $ docker compose up --build -d + $ docker compose ps + + Name Command State Ports + ----------------------------------------------------------------------------------------------------------- + dash0-dash0-collector-1 "/otelcol --config=…" running (healthy) + dash0-envoy-1 "/docker-entrypoint.…" running 0.0.0.0:10000->10000/tcp + dash0-service-1-1 "python3 /code/servi…" running (healthy) + +Step 3: Make a request to ``service-1`` +**************************************** + +Now send a request to ``service-1``, by calling http://localhost:10000/trace/1. + +.. code-block:: console + + $ curl localhost:10000/trace/1 + Hello from behind Envoy (service 1)! + +Step 4: View the trace in Dash0 +********************************* + +Log in to your Dash0 organization and navigate to the Traces view. + +You should see a trace for the ``envoy-dash0-demo`` service, named after the +``tracing.provider.typed_config.service_name`` value set in ``envoy.yaml``. + +.. image:: /start/sandboxes/_include/dash0/_static/dash0-ui-traces.png + +Click into it to see the span recorded for the proxied request, including its latency and +metadata such as ``http.response.status_code`` and ``component``. + +.. image:: /start/sandboxes/_include/dash0/_static/dash0-ui-trace.png + +.. seealso:: + + :ref:`Request tracing ` + Learn more about using Envoy's request tracing. + + `Dash0 `_ + Dash0 website. + + `OpenTelemetry tracing `_ + OpenTelemetry tracing sandbox. diff --git a/dash0/otel-collector-config.yaml b/dash0/otel-collector-config.yaml new file mode 100644 index 00000000..67b91396 --- /dev/null +++ b/dash0/otel-collector-config.yaml @@ -0,0 +1,35 @@ +extensions: + health_check: + +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + +processors: + batch: + memory_limiter: + # 75% of maximum memory up to 4G + limit_mib: 1536 + # 25% of limit up to 2G + spike_limit_mib: 512 + check_interval: 5s + +exporters: + debug: + verbosity: detailed + otlp/dash0: + endpoint: ${env:DASH0_ENDPOINT} + headers: + Authorization: "Bearer ${env:DASH0_AUTH_TOKEN}" + Dash0-Dataset: "${env:DASH0_DATASET}" + +service: + pipelines: + traces: + receivers: [otlp] + processors: [memory_limiter, batch] + exporters: [debug, otlp/dash0] + + extensions: [health_check] diff --git a/dash0/verify.sh b/dash0/verify.sh new file mode 100755 index 00000000..7850ff03 --- /dev/null +++ b/dash0/verify.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e + +export NAME=dash0 +export PORT_PROXY="${DASH0_PORT_PROXY:-10800}" + +# shellcheck source=verify-common.sh +. "$(dirname "${BASH_SOURCE[0]}")/../verify-common.sh" + +run_log "Make a request to service-1" +responds_with \ + "Hello from behind Envoy (service 1)!" \ + "http://localhost:${PORT_PROXY}/trace/1"