Packages
appsignal
2.4.1
2.17.4
2.17.3
2.17.2
2.17.1
2.17.0
2.16.0
2.15.11
2.15.10
2.15.9
2.15.8
2.15.7
2.15.6
2.15.5
2.15.4
2.15.3
2.15.2
2.15.1
2.15.0
2.14.1
2.14.0
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.12.3
2.12.2
2.12.1
2.12.0
2.11.0
2.10.2
2.10.1
2.10.0
2.9.2
2.9.1
2.9.0
2.8.3
2.8.2
2.8.1
2.8.0
2.7.13
2.7.12
2.7.11
2.7.10
2.7.9
2.7.8
2.7.7
2.7.6
2.7.5
2.7.4
2.7.3
2.7.2
2.7.1
2.7.0
2.7.0-beta.1
2.6.1
2.6.0
2.5.3
2.5.2
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.1
2.3.0
2.2.19
2.2.18
2.2.17
2.2.16
2.2.15
2.2.14
2.2.13
2.2.12
retired
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.15
2.1.14
2.1.13
2.1.12
2.1.11
2.1.10
2.1.9
2.1.8
2.1.7
2.1.7-beta.1
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.8
2.0.7
2.0.6
2.0.6-beta.1
2.0.5
retired
2.0.4
retired
2.0.3
retired
2.0.2
retired
2.0.1
retired
2.0.0
retired
2.0.0-beta.11
2.0.0-beta.10
2.0.0-beta.9
2.0.0-beta.8
2.0.0-beta.7
2.0.0-beta.6
2.0.0-beta.5
2.0.0-beta.4
2.0.0-beta.3
2.0.0-beta.2
2.0.0-beta.1
2.0.0-alpha.7
2.0.0-alpha.6
2.0.0-alpha.5
2.0.0-alpha.4
2.0.0-alpha.3
2.0.0-alpha.2
2.0.0-alpha.1
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.13.0-beta.2
1.13.0-beta.1
1.12.1
1.12.0
1.12.0-beta.3
1.12.0-beta.2
1.12.0-beta.1
1.11.8
1.11.7
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
1.11.0
1.11.0-beta.1
1.10.13
1.10.12
1.10.11
1.10.10
1.10.9
1.10.8
1.10.7
1.10.6
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.4
1.9.3
1.9.2
1.9.1
1.9.1-beta.1
1.9.0
1.9.0-beta.1
1.9.0-alpha.1
1.8.2
1.8.1
1.8.1-beta.2
1.8.1-beta.1
1.8.0
1.7.2
1.7.1
1.7.0
1.7.0-beta.2
1.7.0-beta.1
1.7.0-alpha.4
1.7.0-alpha.3
1.7.0-alpha.2
1.7.0-alpha.1
1.6.7
1.6.6
1.6.6-beta.2
1.6.6-beta.1
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-beta.1
1.6.0-alpha.1
1.5.1
1.5.0
1.5.0-beta.2
1.5.0-beta.1
1.4.11-beta.1
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-alpha.1
1.3.6
1.3.6-beta.1
1.3.5
1.3.4
1.3.4-beta.1
1.3.3
1.3.2
1.3.1
1.3.0
1.3.0-beta.3
1.3.0-beta.2
1.3.0-beta.1
1.2.3
1.2.2
1.2.1
1.2.0
1.1.1
1.1.0
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
1.0.0-rc.1
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.2
0.9.1
0.9.0
0.8.0
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
Collects error and performance data from your Elixir applications and sends it to AppSignal
Current section
Files
Jump to
Current section
Files
lib/appsignal/probes/erlang_probe.ex
defmodule Appsignal.Probes.ErlangProbe do
@moduledoc false
require Appsignal.Utils
@appsignal Appsignal.Utils.compile_env(:appsignal, :appsignal, Appsignal)
@inet Appsignal.Utils.compile_env(:appsignal, :inet, :inet)
def call(sample \\ nil) do
next_sample = sample_schedulers()
io_metrics()
scheduler_metrics()
process_metrics()
memory_metrics()
atom_metrics()
run_queue_lengths()
scheduler_utilization_metrics(sample, next_sample)
next_sample
end
defp io_metrics do
{{:input, input}, {:output, output}} = :erlang.statistics(:io)
set_gauge("erlang_io", Kernel.div(input, 1024), %{type: "input"})
set_gauge("erlang_io", Kernel.div(output, 1024), %{type: "output"})
end
defp scheduler_metrics do
set_gauge("erlang_schedulers", :erlang.system_info(:schedulers), %{type: "total"})
set_gauge(
"erlang_schedulers",
:erlang.system_info(:schedulers_online),
%{type: "online"}
)
end
defp process_metrics do
set_gauge("erlang_processes", :erlang.system_info(:process_limit), %{type: "limit"})
set_gauge("erlang_processes", :erlang.system_info(:process_count), %{type: "count"})
end
defp memory_metrics do
memory = :erlang.memory()
Enum.each(memory, fn {key, value} ->
set_gauge("erlang_memory", Kernel.div(value, 1024), %{type: to_string(key)})
end)
end
defp atom_metrics do
set_gauge("erlang_atoms", :erlang.system_info(:atom_limit), %{type: "limit"})
set_gauge("erlang_atoms", :erlang.system_info(:atom_count), %{type: "count"})
end
defp run_queue_lengths do
{otp_release, _} = Integer.parse(System.otp_release())
total =
if otp_release < 20 do
Enum.sum(:erlang.statistics(:run_queue_lengths))
else
:erlang.statistics(:total_run_queue_lengths_all)
end
cpu =
if otp_release < 20 do
# Before OTP 20.0 there were only normal run queues.
total
else
:erlang.statistics(:total_run_queue_lengths)
end
set_gauge("total_run_queue_lengths", total, %{type: "total"})
set_gauge("total_run_queue_lengths", cpu, %{type: "cpu"})
set_gauge("total_run_queue_lengths", total - cpu, %{type: "io"})
end
defp scheduler_utilization_metrics(nil, _), do: nil
defp scheduler_utilization_metrics(sample, next_sample) do
utilization = scheduler_utilization(sample, next_sample)
utilization
|> Enum.map(&Tuple.to_list/1)
|> Enum.filter(fn [type | _] -> type == :normal end)
|> Enum.each(fn [_, id, value, _] ->
set_gauge("erlang_scheduler_utilization", value * 100, %{type: "normal", id: "#{id}"})
end)
end
if Code.ensure_loaded?(:scheduler) do
defp sample_schedulers, do: :scheduler.sample()
defp scheduler_utilization(sample, next_sample) do
:scheduler.utilization(sample, next_sample)
end
else
defp sample_schedulers do
scheduler_wall_time = Enum.sort(:erlang.statistics(:scheduler_wall_time))
scheduler_count = :erlang.system_info(:schedulers)
Enum.take(scheduler_wall_time, scheduler_count)
end
defp scheduler_utilization(sample, next_sample) do
Enum.map(Enum.zip(sample, next_sample), fn {old, new} ->
{id, old_active, old_total} = old
{^id, new_active, new_total} = new
utilization = (new_active - old_active) / (new_total - old_total)
{:normal, id, utilization, nil}
end)
end
end
defp set_gauge(name, value, tags) do
@appsignal.set_gauge(
name,
value,
Map.merge(tags, %{hostname: hostname()})
)
end
defp hostname do
case Application.fetch_env(:appsignal, :config) do
{:ok, %{hostname: hostname}} ->
hostname
_ ->
{:ok, hostname} = @inet.gethostname()
List.to_string(hostname)
end
end
end