Skip to main content

src/pharos@statistic.erl

-module(pharos@statistic).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/pharos/statistic.gleam").
-export([default_interval_ms/1, poll/1, poll_every/2]).
-export_type([statistic_kind/0, statistic/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(
    " What pharos can poll, and how often.\n"
    "\n"
    " A `Statistic` pairs a `StatisticKind` (the *what*) with a per-statistic\n"
    " polling interval (the *how often*). Use `poll/1` to accept the kind's\n"
    " default interval, or `poll_every/2` to override it.\n"
    "\n"
    " Statistics group into these families:\n"
    "\n"
    " - **BEAM VM internals** - `BeamMemory`, `BeamRunQueues`, `BeamSystemCounts`,\n"
    "   `BeamPersistentTerm`. Built into `telemetry_poller`. `BeamScheduler`\n"
    "   (scheduler utilisation) and `BeamReductions` are custom emitters.\n"
    " - **Distributed Erlang topology** - `ClusterNodes`. Custom measurement\n"
    "   emitting `[pharos, cluster, nodes]`.\n"
    " - **Per-process introspection** - `ProcessInfo`. Built into `telemetry_poller`.\n"
    " - **Host (OS)** - `HostMemory` (`/proc/meminfo`, Linux), `HostDisk(path)`\n"
    "   and `HostCpu` (os_mon's `disksup`/`cpu_sup`), and `HostNetwork`\n"
    "   (`/proc/net/dev`). Host probes degrade to `status: unimplemented` when the\n"
    "   underlying source is unavailable.\n"
).

-type statistic_kind() :: beam_memory |
    beam_run_queues |
    beam_system_counts |
    beam_persistent_term |
    {process_info,
        gleam@erlang@atom:atom_(),
        list(gleam@erlang@atom:atom_()),
        list(gleam@erlang@atom:atom_())} |
    cluster_nodes |
    host_memory |
    {host_disk, binary()} |
    host_cpu |
    host_network |
    beam_scheduler |
    beam_reductions.

-type statistic() :: {statistic, statistic_kind(), integer()}.

-file("src/pharos/statistic.gleam", 78).
?DOC(
    " Default polling cadence for each kind. Tuned to match the cost and\n"
    " volatility of the underlying signal: cheap, fast-changing things\n"
    " (run queues) poll often; expensive or slow-changing things (cluster\n"
    " topology, disk) poll rarely.\n"
).
-spec default_interval_ms(statistic_kind()) -> integer().
default_interval_ms(Kind) ->
    case Kind of
        beam_memory ->
            5000;

        beam_run_queues ->
            1000;

        beam_system_counts ->
            5000;

        beam_persistent_term ->
            10000;

        {process_info, _, _, _} ->
            5000;

        cluster_nodes ->
            30000;

        host_memory ->
            10000;

        {host_disk, _} ->
            30000;

        host_cpu ->
            5000;

        host_network ->
            5000;

        beam_scheduler ->
            5000;

        beam_reductions ->
            5000
    end.

-file("src/pharos/statistic.gleam", 65).
?DOC(" Poll `kind` at its default cadence.\n").
-spec poll(statistic_kind()) -> statistic().
poll(Kind) ->
    {statistic, Kind, default_interval_ms(Kind)}.

-file("src/pharos/statistic.gleam", 70).
?DOC(" Poll `kind` every `interval_ms` milliseconds.\n").
-spec poll_every(statistic_kind(), integer()) -> statistic().
poll_every(Kind, Interval_ms) ->
    {statistic, Kind, Interval_ms}.