Packages
new_relic_agent
1.27.2
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/transaction/erlang_trace.ex
defmodule NewRelic.Transaction.ErlangTrace do
use GenServer, restart: :temporary
alias NewRelic.Transaction
# This GenServer watches Transaction processes for
# :trace messages that signal that a Transaction process has
# spwaned another linked process that we include in the Transaction
@moduledoc false
def start_link(_) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
@overload_queue_len 500
@overload_backoff 60 * 1000
def init(:ok) do
NewRelic.sample_process()
enable_trace_patterns()
overload = %{
queue_len: Application.get_env(:new_relic_agent, :overload_queue_len, @overload_queue_len),
backoff: Application.get_env(:new_relic_agent, :overload_backoff, @overload_backoff)
}
{:ok, %{overload: overload}}
end
# API
def trace() do
enable_trace_flags(:self)
end
def disable() do
GenServer.call(__MODULE__, :disable)
end
# Server
def handle_call(:disable, _from, state) do
{:stop, {:shutdown, :disable}, :ok, state}
end
# Trace messages
def handle_info(
{:trace_ts, source, :return_from, {:proc_lib, :spawn_link, _}, pid, timestamp},
state
) do
Transaction.Reporter.track_spawn(source, pid, NewRelic.Util.time_to_ms(timestamp))
overload_protection(state.overload)
{:noreply, state}
end
def handle_info(
{:trace_ts, source, :return_from, {:proc_lib, :start_link, _}, {:ok, pid}, timestamp},
state
) do
Transaction.Reporter.track_spawn(source, pid, NewRelic.Util.time_to_ms(timestamp))
overload_protection(state.overload)
{:noreply, state}
end
def handle_info(_msg, state) do
{:noreply, state}
end
# Helpers
# Trace function calls so we can install specific trace_patterns
# http://erlang.org/doc/man/erlang.html#trace-3
defp enable_trace_flags(:self) do
with tracer when is_pid(tracer) <- Process.whereis(__MODULE__) do
:erlang.trace(self(), true, [:call, :set_on_spawn, :timestamp, tracer: tracer])
end
rescue
ArgumentError -> :process_gone
end
def enable_trace_patterns do
# Use function tracers to notice when linked work has been kicked off
# http://erlang.org/doc/man/erlang.html#trace_3_trace_messages_return_from
# http://erlang.org/doc/apps/erts/match_spec.html
trace_proc_lib_spawn_link()
end
defp trace_proc_lib_spawn_link do
:erlang.trace_pattern({:proc_lib, :spawn_link, :_}, [{:_, [], [{:return_trace}]}], [])
:erlang.trace_pattern({:proc_lib, :start_link, :_}, [{:_, [], [{:return_trace}]}], [])
end
defp overload_protection(%{backoff: backoff} = overload) do
{:message_queue_len, len} = Process.info(self(), :message_queue_len)
cond do
len >= overload.queue_len ->
NewRelic.log(:error, "ErlangTrace overload: #{len} - shutting down for #{backoff} ms.")
NewRelic.Transaction.ErlangTraceManager.enable_erlang_trace(after: overload.backoff)
exit({:shutdown, :overload})
true ->
:all_good
end
end
end