defmodule Tesla.Middleware.OpenTelemetry do require OpenTelemetry.Tracer @behaviour Tesla.Middleware def call(env, next, _options) do %URI{path: path} = URI.parse(env.url) OpenTelemetry.Tracer.with_span path, %{kind: :client} do env |> Tesla.put_headers(:otel_propagator_text_map.inject([])) |> Tesla.run(next) |> case do {:ok, env} -> OpenTelemetry.Tracer.set_attributes(build_attrs(env)) {:ok, env} {:error, _} = e -> e |> IO.inspect(label: "------>") IO.puts("---------> HAAAAAAAAAAA") # TODO: update span's status to with appropriate error code and message e end end end defp build_attrs(%Tesla.Env{ method: method, url: url, status: status_code, headers: headers, query: query }) do url = Tesla.build_url(url, query) uri = URI.parse(url) attrs = %{ "http.method": http_method(method), "http.url": url, "http.target": uri.path, "http.host": uri.host, "http.scheme": uri.scheme, "http.status_code": status_code } maybe_append_content_length(attrs, headers) end defp maybe_append_content_length(attrs, headers) do case Enum.find(headers, fn {k, _v} -> k == "content-length" end) do nil -> attrs {_key, content_length} -> Map.put(attrs, :"http.response_content_length", content_length) end end defp http_method(method) do method |> Atom.to_string() |> String.upcase() end end