Last active
December 10, 2020 22:11
-
-
Save arnodirlam/e00e2e8a826afb85651c0d8b9f4a44ad to your computer and use it in GitHub Desktop.
AppSignal: Trace spawned Ecto processes (f.ex. preload with in_parallel: true)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.Application do | |
use Application | |
def start(_type, _args) do | |
MyApp.Appsignal.EctoParentSpan.attach() | |
children = [ | |
# ... | |
] | |
# ... | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.Appsignal.EctoParentSpan do | |
@moduledoc """ | |
Augments `Ecto` metrics tracked by `Appsignal.Ecto` with the pid of the parent process | |
in cases where processes are spawned for concurrency, f.ex. when using `preload` with | |
`in_parallel: true` (which is the default). | |
""" | |
@tracer Application.get_env(:appsignal, :appsignal_tracer, Appsignal.Tracer) | |
@monitor Application.get_env(:appsignal, :appsignal_monitor, Appsignal.Monitor) | |
@table :"$appsignal_registry" | |
def attach do | |
otp_app = | |
:appsignal | |
|> Application.get_env(:config, %{}) | |
|> Map.get(:otp_app, nil) | |
otp_app | |
|> repos() | |
|> Enum.each(&attach(otp_app, &1)) | |
end | |
def attach(otp_app, repo) do | |
event = telemetry_prefix(otp_app, repo) ++ [:query] | |
case :telemetry.attach({__MODULE__, event}, event, &handle_event/4, :ok) do | |
:ok -> | |
Logger.debug("#{__MODULE__} attached to #{inspect(event)}") | |
{:error, _} = error -> | |
Logger.warn("#{__MODULE__} not attached to #{inspect(event)}: #{inspect(error)}") | |
end | |
end | |
defp repos(otp_app) do | |
Application.get_env(:appsignal, :config, %{})[:ecto_repos] || | |
Application.get_env(otp_app, :ecto_repos) || | |
[] | |
end | |
defp telemetry_prefix(otp_app, repo) do | |
case otp_app | |
|> Application.get_env(repo, []) | |
|> Keyword.get(:telemetry_prefix) do | |
prefix when is_list(prefix) -> | |
prefix | |
_ -> | |
repo | |
|> Module.split() | |
|> Enum.map(&(&1 |> Macro.underscore() |> String.to_atom())) | |
end | |
end | |
def handle_event(_event, _measurements, %{options: %{appsignal_span: parent_span}}, _config) do | |
unless @tracer.current_span() do | |
:ets.insert(@table, {self(), parent_span}) | |
@monitor.add() | |
end | |
:ok | |
end | |
def handle_event(_event, _measurements, _metadata, _config), do: :ok | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.Repo do | |
use Ecto.Repo, | |
otp_app: :my_app, | |
adapter: Ecto.Adapters.Postgres | |
@tracer Application.get_env(:appsignal, :appsignal_tracer, Appsignal.Tracer) | |
def default_options(_operation) do | |
[telemetry_options: %{appsignal_span: @tracer.current_span()}] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment