Packages
new_relic_agent
1.16.3
1.40.3
1.40.2
1.40.1
1.40.0
1.39.0
1.38.0
1.37.0
1.36.0
1.35.0
1.34.0
1.33.0
1.32.0
1.31.1
1.31.0
1.30.0
1.29.0
1.28.0
1.27.8
1.27.7
1.27.6
1.27.5
1.27.4
1.27.3
1.27.2
1.27.1
1.27.0
1.26.0
1.25.3
1.25.2
1.25.1
1.25.0
1.24.5
1.24.4
1.24.3
1.24.2
1.24.1
1.24.0
1.24.0-rc.10
1.24.0-rc.9
1.24.0-rc.8
1.24.0-rc.7
1.23.6
1.23.5
1.23.4
1.23.3
1.23.2
1.23.1
1.23.0
1.23.0-rc.6
1.23.0-rc.5
1.23.0-rc.4
1.23.0-rc.3
1.23.0-rc.2
1.23.0-rc.1
1.22.6
1.22.5
1.22.4
1.22.3
1.22.2
1.22.1
1.22.0
1.21.2
1.21.1
1.21.0
1.21.0-rc.3
1.21.0-rc.1
1.20.0
1.20.0-rc.1
1.19.7
1.19.6
1.19.5
1.19.4
1.19.3
1.19.2
1.19.1
1.19.0
1.18.5
1.18.4
1.18.3
1.18.2
1.18.1
1.18.0
1.18.0-rc.5
1.18.0-rc.4
1.18.0-rc.2
1.18.0-rc.1
1.17.1
1.17.0
1.17.0-rc.4
1.17.0-rc.3
1.17.0-rc.2
1.17.0-rc.1
1.17.0-rc.0
1.16.7
1.16.6
1.16.5
1.16.4
1.16.3
1.16.2
1.16.1
1.16.0
1.16.0-rc.2
1.16.0-rc.1
1.16.0-rc.0
1.15.0
1.15.0-rc.3
1.15.0-rc.2
1.15.0-rc.1
1.14.0
1.13.1
1.13.0
1.12.0
1.11.0
1.10.2
1.10.1
1.10.0
1.9.12
1.9.11
1.9.10
1.9.9
1.9.8
1.9.7
1.9.6
1.9.5
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.0
1.7.0
1.6.2
1.6.1
1.6.0
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.0
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
New Relic's Open-Source Elixir Agent
Current section
Files
Jump to
Current section
Files
lib/new_relic/telemetry/ecto.ex
defmodule NewRelic.Telemetry.Ecto do
use GenServer
@moduledoc """
`NewRelic.Telemetry.Ecto` provides `Ecto` instrumentation via `telemetry`.
Repos are auto-discovered and instrumented. We automatically gather:
* Datastore metrics
* Transaction Trace segments
* Transaction datastore attributes
* Distributed Trace span events
You can opt-out of this instrumentation as a whole and specifically of
SQL query collection via configuration. See `NewRelic.Config` for details.
"""
def start_link(otp_app) do
enabled = NewRelic.Config.feature?(:ecto_instrumentation)
ecto_repos = Application.get_env(otp_app, :ecto_repos)
config = extract_config(otp_app, ecto_repos)
GenServer.start_link(__MODULE__, config: config, enabled: enabled)
end
def init(config: _, enabled: false), do: :ignore
def init(config: config, enabled: true) do
log(config)
:telemetry.attach_many(
config.handler_id,
config.events,
&NewRelic.Telemetry.Ecto.Handler.handle_event/4,
config
)
Process.flag(:trap_exit, true)
{:ok, config}
end
def terminate(_reason, %{handler_id: handler_id}) do
:telemetry.detach(handler_id)
end
defp extract_config(otp_app, ecto_repos) do
%{
otp_app: otp_app,
events: extract_events(otp_app, ecto_repos),
repo_configs: extract_repo_configs(otp_app, ecto_repos),
collect_sql?: NewRelic.Config.feature?(:sql_collection),
handler_id: {:new_relic_ecto, otp_app}
}
end
defp extract_events(otp_app, ecto_repos) do
Enum.map(ecto_repos, fn repo ->
ecto_telemetry_prefix(otp_app, repo) ++ [:query]
end)
end
defp extract_repo_configs(otp_app, ecto_repos) do
Enum.into(ecto_repos, %{}, fn repo ->
{repo, extract_repo_config(otp_app, repo)}
end)
end
defp extract_repo_config(otp_app, repo) do
Application.get_env(otp_app, repo)
|> Map.new()
|> case do
%{url: url} ->
uri = URI.parse(url)
%{
hostname: uri.host,
port: uri.port,
database: uri.path |> String.trim_leading("/")
}
config ->
config
end
end
defp ecto_telemetry_prefix(otp_app, repo) do
Application.get_env(otp_app, repo)
|> Keyword.get_lazy(:telemetry_prefix, fn ->
repo
|> Module.split()
|> Enum.map(&(&1 |> Macro.underscore() |> String.to_atom()))
end)
end
defp log(%{repo_configs: repo_configs}) do
for {repo, _config} <- repo_configs do
NewRelic.log(:info, "Detected Ecto Repo `#{inspect(repo)}`")
end
end
end