Packages
new_relic_agent
1.33.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/sampler/beam.ex
defmodule NewRelic.Sampler.Beam do
use GenServer
@kb 1024
@mb 1024 * 1024
# Takes samples of the state of the BEAM at an interval
@moduledoc false
def start_link(_) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def init(:ok) do
:erlang.system_flag(:scheduler_wall_time, true)
# throw away first value
NewRelic.OsMon.util()
:erlang.statistics(:scheduler_wall_time)
NewRelic.sample_process()
if NewRelic.Config.enabled?(),
do: Process.send_after(self(), :report, NewRelic.Sampler.Reporter.random_sample_offset())
{:ok, %{previous: take_sample()}}
end
def handle_info(:report, state) do
current_sample = record_sample(state)
Process.send_after(self(), :report, NewRelic.Sampler.Reporter.sample_cycle())
{:noreply, %{state | previous: current_sample}}
end
def handle_call(:report, _from, state) do
current_sample = record_sample(state)
{:reply, :ok, %{state | previous: current_sample}}
end
defp record_sample(state) do
{current_sample, stats} = collect(state.previous)
NewRelic.report_sample(:BeamStat, stats)
NewRelic.report_metric(:memory, mb: stats[:memory_total_mb])
NewRelic.report_metric(:cpu, utilization: stats[:cpu_utilization])
current_sample
end
defp collect(previous) do
current_sample = take_sample()
stats = Map.merge(current_sample, delta(previous, current_sample))
{current_sample, stats}
end
defp take_sample do
{gcs, _, _} = :erlang.statistics(:garbage_collection)
{reductions, _} = :erlang.statistics(:reductions)
{{:input, bytes_in}, {:output, bytes_out}} = :erlang.statistics(:io)
memory = :erlang.memory()
%{
garbage_collections: gcs,
input_kb: bytes_in / @kb,
output_kb: bytes_out / @kb,
reductions: reductions,
run_queue: :erlang.statistics(:total_run_queue_lengths),
memory_total_mb: memory[:total] / @mb,
memory_procs_mb: memory[:processes_used] / @mb,
memory_ets_mb: memory[:ets] / @mb,
memory_atom_mb: memory[:atom_used] / @mb,
memory_binary_mb: memory[:binary] / @mb,
memory_code_mb: memory[:code] / @mb,
atom_count: :erlang.system_info(:atom_count),
ets_count: :erlang.system_info(:ets_count),
port_count: :erlang.system_info(:port_count),
process_count: :erlang.system_info(:process_count),
atom_limit: :erlang.system_info(:atom_limit),
ets_limit: :erlang.system_info(:ets_limit),
port_limit: :erlang.system_info(:port_limit),
process_limit: :erlang.system_info(:process_limit),
schedulers: :erlang.system_info(:schedulers),
scheduler_utilization: :erlang.statistics(:scheduler_wall_time) |> Enum.sort(),
cpu_count: :erlang.system_info(:logical_processors),
cpu_utilization: NewRelic.OsMon.util()
}
end
defp delta(previous, current) do
%{
garbage_collections: current.garbage_collections - previous.garbage_collections,
input_kb: current.input_kb - previous.input_kb,
output_kb: current.output_kb - previous.output_kb,
reductions: current.reductions - previous.reductions,
scheduler_utilization: delta(:util, previous.scheduler_utilization, current.scheduler_utilization)
}
end
defp delta(:util, previous, current) do
{_, {active, total}} =
Enum.zip(previous, current)
|> Enum.map_reduce({0, 0}, fn
{{n, a0, t0}, {n, a1, t1}}, {acc_a, acc_t} ->
{{n, a1 - a0, t1 - t0}, {acc_a + (a1 - a0), acc_t + (t1 - t0)}}
end)
safe_div(active, total)
end
defp safe_div(a, b) do
a / b
rescue
ArithmeticError -> 0.0
end
end