[opentelemetry_tesla] Conditionally override propagator (#176)
* Optionally disable trace propagation for Tesla While we always want spans being produced, trace progation is not desirable in all cases - namely, when calling external parties, as that may leak sensitive information, like one present on Baggage. This patch introduces a new option `:propagate`, that defaults to `true`. Some tweaks are made to existing propagation test, fixing how options are used. The approach here is closer to what we see in some middleware tests of Tesla itself. * change to propagator override * change propagator to it uses global default * mix format * improve docs --------- Co-authored-by: Andrew Rosa <dev@andrewhr.io>
This commit is contained in:
parent
6a5fc4c884
commit
901b571b07
|
@ -12,6 +12,9 @@ defmodule Tesla.Middleware.OpenTelemetry do
|
||||||
|
|
||||||
- `:span_name` - override span name. Can be a `String` for a static span name,
|
- `: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`
|
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`,
|
- `:mark_status_ok` - configures spans with a list of expected HTTP error codes to be marked as `ok`,
|
||||||
not as an error-containing spans
|
not as an error-containing spans
|
||||||
"""
|
"""
|
||||||
|
@ -29,7 +32,7 @@ defmodule Tesla.Middleware.OpenTelemetry do
|
||||||
OpenTelemetry.Tracer.with_span span_name, %{kind: :client} do
|
OpenTelemetry.Tracer.with_span span_name, %{kind: :client} do
|
||||||
env
|
env
|
||||||
|> maybe_put_additional_ok_statuses(opts[:mark_status_ok])
|
|> 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)
|
|> Tesla.run(next)
|
||||||
|> set_span_attributes()
|
|> set_span_attributes()
|
||||||
|> handle_result()
|
|> handle_result()
|
||||||
|
@ -51,6 +54,16 @@ defmodule Tesla.Middleware.OpenTelemetry do
|
||||||
end
|
end
|
||||||
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
|
defp maybe_put_additional_ok_statuses(env, [_ | _] = additional_ok_statuses) do
|
||||||
case env.opts[:additional_ok_statuses] do
|
case env.opts[:additional_ok_statuses] do
|
||||||
nil -> Tesla.put_opt(env, :additional_ok_statuses, additional_ok_statuses)
|
nil -> Tesla.put_opt(env, :additional_ok_statuses, additional_ok_statuses)
|
||||||
|
|
|
@ -491,27 +491,32 @@ defmodule Tesla.Middleware.OpenTelemetryTest do
|
||||||
assert response_size == byte_size(response)
|
assert response_size == byte_size(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Injects distributed tracing headers" do
|
describe "trace propagation" do
|
||||||
OpentelemetryTelemetry.start_telemetry_span(
|
test "injects distributed tracing headers by default" do
|
||||||
"tracer_id",
|
{:ok, env} = Tesla.get(client(), "/propagate-traces")
|
||||||
"my_label",
|
|
||||||
%{},
|
|
||||||
%{kind: :client}
|
|
||||||
)
|
|
||||||
|
|
||||||
assert {:ok,
|
assert traceparent = Tesla.get_header(env, "traceparent")
|
||||||
%Tesla.Env{
|
assert is_binary(traceparent)
|
||||||
headers: [
|
|
||||||
{"traceparent", traceparent}
|
|
||||||
]
|
|
||||||
}} =
|
|
||||||
Tesla.Middleware.OpenTelemetry.call(
|
|
||||||
_env = %Tesla.Env{url: ""},
|
|
||||||
_next = [],
|
|
||||||
_opts = []
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
defp endpoint_url(port), do: "http://localhost:#{port}/"
|
defp endpoint_url(port), do: "http://localhost:#{port}/"
|
||||||
|
|
Loading…
Reference in New Issue