Packages
appsignal
2.15.3
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
def call(sample \\ nil) do
next_sample = sample_schedulers()
sample
|> metrics(next_sample)
|> Enum.each(fn {key, value, tags} ->
Appsignal.set_gauge(key, value, tags)
end)
next_sample
end
def metrics(sample, next_sample) do
metrics =
io_metrics() ++
scheduler_metrics() ++
process_metrics() ++
memory_metrics() ++
atom_metrics() ++
run_queue_lengths() ++
scheduler_utilization_metrics(sample, next_sample)
Enum.map(metrics, fn {key, value, tags} ->
{key, value, Map.merge(tags, %{hostname: Appsignal.Utils.Hostname.hostname()})}
end)
end
defp io_metrics do
{{:input, input}, {:output, output}} = :erlang.statistics(:io)
[
{"erlang_io", Kernel.div(input, 1024), %{type: "input"}},
{"erlang_io", Kernel.div(output, 1024), %{type: "output"}}
]
end
defp scheduler_metrics do
[
{"erlang_schedulers", :erlang.system_info(:schedulers), %{type: "total"}},
{"erlang_schedulers", :erlang.system_info(:schedulers_online), %{type: "online"}}
]
end
defp process_metrics do
[
{"erlang_processes", :erlang.system_info(:process_limit), %{type: "limit"}},
{"erlang_processes", :erlang.system_info(:process_count), %{type: "count"}}
]
end
defp memory_metrics do
memory = :erlang.memory()
Enum.map(memory, fn {key, value} ->
{"erlang_memory", Kernel.div(value, 1024), %{type: to_string(key)}}
end)
end
defp atom_metrics do
[
{"erlang_atoms", :erlang.system_info(:atom_limit), %{type: "limit"}},
{"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
[
{"total_run_queue_lengths", total, %{type: "total"}},
{"total_run_queue_lengths", cpu, %{type: "cpu"}},
{"total_run_queue_lengths", total - cpu, %{type: "io"}}
]
end
defp scheduler_utilization_metrics(nil, _), do: []
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.map(fn [_, id, value, _] ->
{"erlang_scheduler_utilization", value * 100, %{type: "normal", id: "#{id}"}}
end)
end
if Code.ensure_loaded?(:scheduler) do
def sample_schedulers, do: :scheduler.sample()
defp scheduler_utilization(sample, next_sample) do
:scheduler.utilization(sample, next_sample)
end
else
def 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
end