Packages
new_relic_agent
1.14.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
# throw away first value
:cpu_sup.util()
NewRelic.sample_process()
if NewRelic.Config.enabled?(),
do: Process.send_after(self(), :report, NewRelic.Sampler.Reporter.random_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
def 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: safe_check(: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: safe_check(:scheduler, :sample, []),
cpu_count: :erlang.system_info(:logical_processors),
cpu_utilization: :cpu_sup.util()
}
end
def safe_check(m, f, a) do
# Some checks only available in OTP 21+
apply(m, f, a)
rescue
_ -> nil
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, nil, nil), do: nil
defp delta(:util, previous, current) do
[{:total, scheduler_utilization, _} | _] = :scheduler.utilization(previous, current)
scheduler_utilization
end
end