defmodule Spandex.Plug.EndTrace do
@moduledoc """
Finishes a trace, setting status and error based on the HTTP status.
"""
@behaviour Plug
alias Spandex.Plug.Utils
@init_opts Optimal.schema(
opts: [
tracer: :atom,
tracer_opts: :keyword
],
defaults: [
tracer_opts: []
],
required: [:tracer],
describe: [
tracer: "The tracing module to be used to start the trace.",
tracer_opts: "Any opts to be passed to the tracer when starting or continuing the trace."
]
)
@doc """
Accepts and validates opts for the plug, and underlying tracer.
#{Optimal.Doc.document(@init_opts)}
"""
@spec init(opts :: Keyword.t()) :: Keyword.t()
def init(opts) do
Optimal.validate!(opts, @init_opts)
end
@spec call(conn :: Plug.Conn.t(), _opts :: Keyword.t()) :: Plug.Conn.t()
def call(conn, opts) do
tracer = opts[:tracer]
tracer_opts = opts[:tracer_opts]
opts =
if conn.status in 200..399 do
Keyword.merge([http: [status_code: conn.status]], tracer_opts)
else
Keyword.merge(
[http: [status_code: conn.status], error: [error?: true]],
tracer_opts
)
end
if Utils.trace?(conn) do
tracer.update_top_span(opts)
tracer.finish_trace(tracer_opts)
end
conn
end
end