defmodule Glific.Appsignal do
@moduledoc """
A simple interface that connect Oban job status to Appsignal
"""
@tracer Appsignal.Tracer
@span Appsignal.Span
@doc false
@spec handle_event(list(), any(), any(), any()) :: any()
def handle_event([:oban, action, event], measurement, meta, _)
when event in [:stop, :exception] do
time = :os.system_time()
span = record_event(action, measurement, meta, time)
if event == :exception && meta.attempt >= meta.max_attempts do
error = inspect(meta.error)
@span.add_error(span, meta.kind, error, meta.stacktrace)
end
@tracer.close_span(span, end_time: time)
end
def handle_event(_, _, _, _), do: nil
@spec record_event(atom(), any(), any(), integer()) :: any()
defp record_event(:job, measurement, meta, time) do
metadata = %{"id" => meta.id, "queue" => meta.queue, "attempt" => meta.attempt}
"oban_job"
|> @tracer.create_span(@tracer.current_span(), start_time: time - measurement.duration)
|> @span.set_name("Oban #{meta.worker}#perform")
|> @span.set_attribute("appsignal:category", "oban.worker")
|> @span.set_sample_data("meta.data", metadata)
|> @span.set_sample_data("meta.args", meta.args)
end
@ignore_plugins [
Elixir.Oban.Plugins.Stager,
Elixir.Oban.Pro.Plugins.DynamicLifeline,
Elixir.Oban.Plugins.Pruner,
Elixir.Oban.Plugins.Gossip,
Elixir.Oban.Plugins.Reindexer
]
# ignore some internal Oban plugins which execute quite often
defp record_event(:plugin, _m, %{plugin: plugin}, _t) when plugin in @ignore_plugins,
do: nil
defp record_event(:plugin, measurement, meta, time) do
metadata = %{"plugin" => meta.plugin}
"oban_plugin"
|> @tracer.create_span(@tracer.current_span(), start_time: time - measurement.duration)
|> @span.set_name("Oban #{meta.plugin}")
|> @span.set_attribute("appsignal:category", "oban.plugin")
|> @span.set_sample_data("meta.data", metadata)
end
defp record_event(_, _measurement, _meta, _time), do: nil
@doc """
Use to set namespace to current appsignal process from anywhere.
"""
@spec set_namespace(String.t()) :: any()
def set_namespace(namespace) do
Appsignal.Span.set_namespace(Appsignal.Tracer.root_span(), namespace)
end
end