diff --git a/instrumentation/opentelemetry_tesla/lib/middleware/opentelemetry_tesla_middleware.ex b/instrumentation/opentelemetry_tesla/lib/middleware/opentelemetry_tesla_middleware.ex index be5d969..17086a4 100644 --- a/instrumentation/opentelemetry_tesla/lib/middleware/opentelemetry_tesla_middleware.ex +++ b/instrumentation/opentelemetry_tesla/lib/middleware/opentelemetry_tesla_middleware.ex @@ -12,6 +12,9 @@ defmodule Tesla.Middleware.OpenTelemetry do - `:span_name` - override span name. Can be a `String` for a static span name, or a function that takes the `Tesla.Env` and returns a `String` + - `:propagator` - configures trace headers propagators. Setting it to `:none` disables propagation. + Any module that implements `:otel_propagator_text_map` can be used. + Defaults to calling `:otel_propagator_text_map.get_text_map_injector/0` - `:mark_status_ok` - configures spans with a list of expected HTTP error codes to be marked as `ok`, not as an error-containing spans """ @@ -29,7 +32,7 @@ defmodule Tesla.Middleware.OpenTelemetry do OpenTelemetry.Tracer.with_span span_name, %{kind: :client} do env |> maybe_put_additional_ok_statuses(opts[:mark_status_ok]) - |> Tesla.put_headers(:otel_propagator_text_map.inject([])) + |> maybe_propagate(Keyword.get(opts, :propagator, :opentelemetry.get_text_map_injector())) |> Tesla.run(next) |> set_span_attributes() |> handle_result() @@ -51,6 +54,16 @@ defmodule Tesla.Middleware.OpenTelemetry do end end + defp maybe_propagate(env, :none), do: env + + defp maybe_propagate(env, propagator) do + :otel_propagator_text_map.inject( + propagator, + env, + fn key, value, env -> Tesla.put_header(env, key, value) end + ) + end + defp maybe_put_additional_ok_statuses(env, [_ | _] = additional_ok_statuses) do case env.opts[:additional_ok_statuses] do nil -> Tesla.put_opt(env, :additional_ok_statuses, additional_ok_statuses) diff --git a/instrumentation/opentelemetry_tesla/test/middleware/opentelemetry_tesla_middleware_test.exs b/instrumentation/opentelemetry_tesla/test/middleware/opentelemetry_tesla_middleware_test.exs index 5cfc300..5363043 100644 --- a/instrumentation/opentelemetry_tesla/test/middleware/opentelemetry_tesla_middleware_test.exs +++ b/instrumentation/opentelemetry_tesla/test/middleware/opentelemetry_tesla_middleware_test.exs @@ -491,27 +491,32 @@ defmodule Tesla.Middleware.OpenTelemetryTest do assert response_size == byte_size(response) end - test "Injects distributed tracing headers" do - OpentelemetryTelemetry.start_telemetry_span( - "tracer_id", - "my_label", - %{}, - %{kind: :client} - ) + describe "trace propagation" do + test "injects distributed tracing headers by default" do + {:ok, env} = Tesla.get(client(), "/propagate-traces") - assert {:ok, - %Tesla.Env{ - headers: [ - {"traceparent", traceparent} - ] - }} = - Tesla.Middleware.OpenTelemetry.call( - _env = %Tesla.Env{url: ""}, - _next = [], - _opts = [] - ) + assert traceparent = Tesla.get_header(env, "traceparent") + assert is_binary(traceparent) - assert is_binary(traceparent) + assert_receive {:span, span(name: _name, attributes: attributes)} + assert %{"http.target": "/propagate-traces"} = :otel_attributes.map(attributes) + end + + test "optionally disable propagation but keep span report" do + {:ok, env} = Tesla.get(client(propagator: :none), "/propagate-traces") + + refute Tesla.get_header(env, "traceparent") + + assert_receive {:span, span(name: _name, attributes: attributes)} + assert %{"http.target": "/propagate-traces"} = :otel_attributes.map(attributes) + end + end + + defp client(opts \\ []) do + [ + {Tesla.Middleware.OpenTelemetry, opts} + ] + |> Tesla.client(fn env -> {:ok, env} end) end defp endpoint_url(port), do: "http://localhost:#{port}/"