Packages
new_relic_agent
1.27.6
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/tracer/report.ex
defmodule NewRelic.Tracer.Report do
alias NewRelic.Transaction
# Helper functions that will report traced function events in their various forms
# - Transaction Trace segments
# - Distributed Trace Span events
# - Transaction attributes
# - Metrics
@moduledoc false
def call(
mfa,
trace_annotation,
pid,
edge,
timing
) do
{name, options} =
case trace_annotation do
{name, options} -> {name, options}
name -> {name, []}
end
category = Keyword.get(options, :category, :function)
report(
category,
options,
mfa,
name,
pid,
edge,
timing
)
end
defp report(
:external,
options,
{module, function, arguments},
name,
pid,
{id, parent_id},
{start_time, start_time_mono, end_time_mono, _child_duration_ms, reductions}
) do
duration_ms = duration_ms(start_time_mono, end_time_mono)
duration_s = duration_ms / 1000
arity = length(arguments)
args = inspect_args(arguments, Keyword.take(options, [:args]))
span_attrs = NewRelic.DistributedTrace.get_span_attrs()
function_name = function_name({module, function}, name)
function_arity_name = function_name({module, function, arity}, name)
case span_attrs do
%{url: url, component: component, method: method} ->
%{host: host} = URI.parse(url)
metric_name = "External/#{host}/#{component}/#{method}"
secondary_name = "#{host} - #{component}/#{method}"
Transaction.Reporter.add_trace_segment(%{
primary_name: metric_name,
secondary_name: secondary_name,
attributes: %{},
pid: pid,
id: id,
parent_id: parent_id,
start_time: start_time,
start_time_mono: start_time_mono,
end_time_mono: end_time_mono
})
NewRelic.report_span(
timestamp_ms: System.convert_time_unit(start_time, :native, :millisecond),
duration_s: duration_s,
name: metric_name,
edge: [span: id, parent: parent_id],
category: "http",
attributes:
Map.merge(span_attrs, %{
"tracer.function": function_arity_name,
"tracer.args": args,
"tracer.reductions": reductions
})
)
NewRelic.incr_attributes(
"external.#{host}.call_count": 1,
"external.#{host}.duration_ms": duration_ms
)
NewRelic.report_metric({:external, url, component, method}, duration_s: duration_s)
Transaction.Reporter.track_metric({
{:external, url, component, method},
duration_s: duration_s
})
_ ->
Transaction.Reporter.add_trace_segment(%{
module: module,
function: function,
arity: arity,
name: name,
args: args,
pid: pid,
id: id,
parent_id: parent_id,
start_time: start_time,
start_time_mono: start_time_mono,
end_time_mono: end_time_mono
})
NewRelic.report_span(
timestamp_ms: System.convert_time_unit(start_time, :native, :millisecond),
duration_s: duration_s,
name: function_arity_name,
edge: [span: id, parent: parent_id],
category: "http",
attributes:
Map.merge(span_attrs, %{
"tracer.args": args,
"tracer.reductions": reductions
})
)
NewRelic.incr_attributes(
"external.#{function_name}.call_count": 1,
"external.#{function_name}.duration_ms": duration_ms
)
NewRelic.report_metric({:external, function_name}, duration_s: duration_s)
Transaction.Reporter.track_metric({
{:external, function_name},
duration_s: duration_s
})
end
NewRelic.incr_attributes(
externalCallCount: 1,
externalDuration: duration_s,
external_call_count: 1,
external_duration_ms: duration_ms
)
Transaction.Reporter.track_metric({:external, duration_s})
end
defp report(
:function,
options,
{module, function, arguments},
name,
pid,
{id, parent_id},
{start_time, start_time_mono, end_time_mono, child_duration_ms, reductions}
) do
duration_ms = duration_ms(start_time_mono, end_time_mono)
duration_s = duration_ms / 1000
exclusive_time_s = duration_s - child_duration_ms / 1000
arity = length(arguments)
args = inspect_args(arguments, Keyword.take(options, [:args]))
function_name = function_name({module, function, arity}, name)
Transaction.Reporter.add_trace_segment(%{
module: module,
function: function,
arity: arity,
name: name,
args: args,
pid: pid,
id: id,
parent_id: parent_id,
start_time: start_time,
start_time_mono: start_time_mono,
end_time_mono: end_time_mono
})
NewRelic.report_span(
timestamp_ms: System.convert_time_unit(start_time, :native, :millisecond),
duration_s: duration_s,
name: function_name,
edge: [span: id, parent: parent_id],
category: "generic",
attributes:
Map.merge(NewRelic.DistributedTrace.get_span_attrs(), %{
"tracer.args": args,
"tracer.reductions": reductions
})
)
NewRelic.report_metric(
{:function, function_name},
duration_s: duration_s,
exclusive_time_s: exclusive_time_s
)
Transaction.Reporter.track_metric({
{:function, function_name},
duration_s: duration_s, exclusive_time_s: exclusive_time_s
})
end
defp inspect_args(_arguments, args: false) do
"[DISABLED]"
end
defp inspect_args(arguments, _) do
if NewRelic.Config.feature?(:function_argument_collection) do
inspect(arguments, charlists: :as_lists, limit: 7, printable_limit: 10)
else
"[DISABLED]"
end
end
defp duration_ms(start_time_mono, end_time_mono),
do: System.convert_time_unit(end_time_mono - start_time_mono, :native, :microsecond) / 1000
defp function_name({m, f}, f), do: "#{inspect(m)}.#{f}"
defp function_name({m, f}, i), do: "#{inspect(m)}.#{f}:#{i}"
defp function_name({m, f, a}, f), do: "#{inspect(m)}.#{f}/#{a}"
defp function_name({m, f, a}, i), do: "#{inspect(m)}.#{f}:#{i}/#{a}"
end