[Tesla middleware] `non_error_statuses` option (#154)
* [Tesla middleware] `non_error_statuses` option * :mark_status_ok option instead of :non_error_statuses --------- Co-authored-by: Tristan Sloughter <t@crashfast.com>
This commit is contained in:
parent
19a44fbd68
commit
1230271580
|
@ -12,7 +12,8 @@ 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`
|
||||||
|
- `:mark_status_ok` - configures spans with a list of expected HTTP error codes to be marked as `ok`,
|
||||||
|
not as an error-containing spans
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias OpenTelemetry.SemanticConventions.Trace
|
alias OpenTelemetry.SemanticConventions.Trace
|
||||||
|
@ -27,6 +28,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])
|
||||||
|> Tesla.put_headers(:otel_propagator_text_map.inject([]))
|
|> Tesla.put_headers(:otel_propagator_text_map.inject([]))
|
||||||
|> Tesla.run(next)
|
|> Tesla.run(next)
|
||||||
|> set_span_attributes()
|
|> set_span_attributes()
|
||||||
|
@ -49,6 +51,15 @@ defmodule Tesla.Middleware.OpenTelemetry do
|
||||||
end
|
end
|
||||||
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)
|
||||||
|
_ -> env
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_put_additional_ok_statuses(env, _additional_ok_statuses), do: env
|
||||||
|
|
||||||
defp set_span_attributes({_, %Tesla.Env{} = env} = result) do
|
defp set_span_attributes({_, %Tesla.Env{} = env} = result) do
|
||||||
OpenTelemetry.Tracer.set_attributes(build_attrs(env))
|
OpenTelemetry.Tracer.set_attributes(build_attrs(env))
|
||||||
|
|
||||||
|
@ -59,8 +70,13 @@ defmodule Tesla.Middleware.OpenTelemetry do
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_result({:ok, %Tesla.Env{status: status} = env}) when status >= 400 do
|
defp handle_result({:ok, %Tesla.Env{status: status, opts: opts} = env}) when status >= 400 do
|
||||||
OpenTelemetry.Tracer.set_status(OpenTelemetry.status(:error, ""))
|
span_status =
|
||||||
|
if status in Keyword.get(opts, :additional_ok_statuses, []), do: :ok, else: :error
|
||||||
|
|
||||||
|
span_status
|
||||||
|
|> OpenTelemetry.status("")
|
||||||
|
|> OpenTelemetry.Tracer.set_status()
|
||||||
|
|
||||||
{:ok, env}
|
{:ok, env}
|
||||||
end
|
end
|
||||||
|
|
|
@ -289,6 +289,64 @@ defmodule Tesla.Middleware.OpenTelemetryTest do
|
||||||
assert_receive {:span, span(status: {:status, :error, ""})}
|
assert_receive {:span, span(status: {:status, :error, ""})}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "Marks Span status as :error if error status is within `mark_status_ok` opt list",
|
||||||
|
%{bypass: bypass} do
|
||||||
|
defmodule TestClient do
|
||||||
|
def get(client) do
|
||||||
|
Tesla.get(client, "/users/")
|
||||||
|
end
|
||||||
|
|
||||||
|
def client(url) do
|
||||||
|
middleware = [
|
||||||
|
{Tesla.Middleware.BaseUrl, url},
|
||||||
|
{Tesla.Middleware.OpenTelemetry, mark_status_ok: [404]}
|
||||||
|
]
|
||||||
|
|
||||||
|
Tesla.client(middleware)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Bypass.expect_once(bypass, "GET", "/users", fn conn ->
|
||||||
|
Plug.Conn.resp(conn, 404, "")
|
||||||
|
end)
|
||||||
|
|
||||||
|
bypass.port
|
||||||
|
|> endpoint_url()
|
||||||
|
|> TestClient.client()
|
||||||
|
|> TestClient.get()
|
||||||
|
|
||||||
|
assert_receive {:span, span(status: {:status, :ok, ""})}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Marks Span status as :ok unless error status is within `mark_status_ok` opt list",
|
||||||
|
%{bypass: bypass} do
|
||||||
|
defmodule TestClient do
|
||||||
|
def get(client) do
|
||||||
|
Tesla.get(client, "/users/")
|
||||||
|
end
|
||||||
|
|
||||||
|
def client(url) do
|
||||||
|
middleware = [
|
||||||
|
{Tesla.Middleware.BaseUrl, url},
|
||||||
|
{Tesla.Middleware.OpenTelemetry, mark_status_ok: []}
|
||||||
|
]
|
||||||
|
|
||||||
|
Tesla.client(middleware)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Bypass.expect_once(bypass, "GET", "/users", fn conn ->
|
||||||
|
Plug.Conn.resp(conn, 404, "")
|
||||||
|
end)
|
||||||
|
|
||||||
|
bypass.port
|
||||||
|
|> endpoint_url()
|
||||||
|
|> TestClient.client()
|
||||||
|
|> TestClient.get()
|
||||||
|
|
||||||
|
assert_receive {:span, span(status: {:status, :error, ""})}
|
||||||
|
end
|
||||||
|
|
||||||
test "Appends query string parameters to http.url attribute", %{bypass: bypass} do
|
test "Appends query string parameters to http.url attribute", %{bypass: bypass} do
|
||||||
defmodule TestClient do
|
defmodule TestClient do
|
||||||
def get(client, id) do
|
def get(client, id) do
|
||||||
|
|
Loading…
Reference in New Issue