Packages
new_relic_agent
1.15.0
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/reporter.ex
defmodule NewRelic.Transaction.Reporter do
use GenServer
alias NewRelic.Util.AttrStore
alias NewRelic.Transaction
# This GenServer collects and reports Transaction related data
# - Transaction Events
# - Transaction Metrics
# - Span Events
# - Transaction Errors
# - Transaction Traces
# - Custom Attributes
@moduledoc false
# Customer Exposed API
def add_attributes(attrs) when is_list(attrs) do
if tracking?(self()) do
AttrStore.add(__MODULE__, self(), NewRelic.Util.deep_flatten(attrs))
end
end
def incr_attributes(attrs) do
if tracking?(self()) do
AttrStore.incr(__MODULE__, self(), attrs)
end
end
def set_transaction_name(custom_name) do
if tracking?(self()) do
AttrStore.add(__MODULE__, self(), custom_name: custom_name)
end
end
# Internal Agent API
#
def start() do
Transaction.Monitor.add(self())
AttrStore.track(__MODULE__, self())
add_attributes(
pid: inspect(self()),
start_time: System.system_time(),
start_time_mono: System.monotonic_time()
)
end
def start_other_transaction(category, name) do
unless tracking?(self()) do
start()
AttrStore.add(__MODULE__, self(), other_transaction_name: "#{category}/#{name}")
end
end
def ignore_transaction() do
if tracking?(self()) do
AttrStore.untrack(__MODULE__, self())
AttrStore.purge(__MODULE__, self())
ensure_purge(self())
end
end
def fail(%{kind: kind, reason: reason, stack: stack} = error) do
if tracking?(self()) do
if NewRelic.Config.feature?(:error_collector) do
add_attributes(
error: true,
transaction_error: {:error, error},
error_kind: kind,
error_reason: inspect(reason),
error_stack: inspect(stack)
)
else
add_attributes(error: true)
end
end
end
def add_trace_segment(segment) do
if tracking?(self()) do
AttrStore.add(__MODULE__, self(), trace_function_segments: {:list, segment})
end
end
def track_metric(metric) do
if tracking?(self()) do
AttrStore.add(__MODULE__, self(), transaction_metrics: {:list, metric})
end
end
def set_transaction_error(pid, error) do
if tracking?(pid) do
AttrStore.add(__MODULE__, pid, transaction_error: {:error, error})
end
end
def complete(pid \\ self()) do
if tracking?(pid) do
AttrStore.add(__MODULE__, pid, end_time_mono: System.monotonic_time())
AttrStore.untrack(__MODULE__, pid)
Task.Supervisor.start_child(NewRelic.Transaction.TaskSupervisor, fn ->
AttrStore.collect(__MODULE__, pid)
|> Transaction.Complete.run(pid)
end)
end
end
# Internal Transaction.Monitor API
#
def track_spawn(original, pid, timestamp) do
if tracking?(original) do
AttrStore.link(
__MODULE__,
original,
pid,
trace_process_spawns: {:list, {pid, timestamp, original}},
trace_process_names: {:list, {pid, NewRelic.Util.process_name(pid)}}
)
AttrStore.incr(__MODULE__, original, process_spawns: 1)
end
end
def track_exit(pid, timestamp) do
if tracking?(pid) do
AttrStore.add(__MODULE__, pid, trace_process_exits: {:list, {pid, timestamp}})
end
end
def ensure_purge(pid) do
Process.send_after(
__MODULE__,
{:purge, AttrStore.find_root(__MODULE__, pid)},
Application.get_env(:new_relic_agent, :tx_pid_expire, 2_000)
)
end
# GenServer
#
def start_link do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def init(:ok) do
NewRelic.sample_process()
AttrStore.new(__MODULE__)
{:ok, %{timers: %{}}}
end
def handle_info({:purge, pid}, state) do
AttrStore.purge(__MODULE__, pid)
{:noreply, %{state | timers: Map.drop(state.timers, [pid])}}
end
# Helpers
#
def tracking?(pid), do: AttrStore.tracking?(__MODULE__, pid)
def root(pid), do: AttrStore.find_root(__MODULE__, pid)
end