-module(pharos@config).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/pharos/config.gleam").
-export([new/0, with_statistics/2, with_thresholds/2, with_custom_statistics/2, with_custom_thresholds/2, with_alert_sinks/2, with_memory_unit/2, with_soak_period/2, with_cool_period/2, with_default_alert_level/2, with_metric_buffer_capacity/2, with_brain_stream/3, with_metric_spillover/2, with_poll_jitter/2, threshold_id/1]).
-export_type([threshold/0, alert_sink/0, brain_stream/0, config/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(
" User-facing configuration for `pharos.start_link`.\n"
"\n"
" Build a `Config` with `new/0` (sensible defaults), pipe through the\n"
" `with_*` setters to add statistics, thresholds, and tune the alert\n"
" timing knobs, then pass it to `pharos.start_link`.\n"
).
-type threshold() :: {total_memory, float()} |
{process_memory, float()} |
{system_memory, float()} |
{binary_memory, float()} |
{ets_memory, float()} |
{total_run_queue, integer()} |
{cpu_run_queue, integer()} |
{process_count, integer()} |
{atom_count, integer()} |
{port_count, integer()} |
{persistent_term_count, integer()} |
{persistent_term_memory, float()} |
{host_memory_used, float()} |
{host_disk_used, float()} |
{host_cpu_util, float()} |
{scheduler_utilization, float()} |
{windowed, threshold(), integer(), pharos@alert:window_mode()}.
-type alert_sink() :: {console, logging:log_level()} |
{webhook, binary()} |
{brain, binary(), binary()} |
{otlp, binary()}.
-type brain_stream() :: {brain_stream, binary(), binary()}.
-type config() :: {config,
list(pharos@statistic:statistic()),
list(threshold()),
list(pharos@probe:probe()),
list(pharos@probe:probe_threshold()),
list(alert_sink()),
pharos@measurement:memory_unit(),
integer(),
integer(),
pharos@alert:alert_level(),
integer(),
gleam@option:option(brain_stream()),
gleam@option:option(binary()),
gleam@option:option(float())}.
-file("src/pharos/config.gleam", 144).
?DOC(
" Sensible defaults: no statistics, no thresholds, log alerts at\n"
" `Warning`, scale memory in `Mb`, 30 s soak, 60 s cool, default alert\n"
" level `Warning`. Pipe through `with_*` setters to customise.\n"
).
-spec new() -> config().
new() ->
{config,
[],
[],
[],
[],
[{console, warning}],
mb,
30000,
60000,
warning,
10000,
none,
none,
none}.
-file("src/pharos/config.gleam", 163).
?DOC(" Set the statistics to poll. Replaces any previously configured list.\n").
-spec with_statistics(config(), list(pharos@statistic:statistic())) -> config().
with_statistics(Config, Statistics) ->
{config,
Statistics,
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 168).
?DOC(" Set the thresholds to evaluate. Replaces any previously configured list.\n").
-spec with_thresholds(config(), list(threshold())) -> config().
with_thresholds(Config, Thresholds) ->
{config,
erlang:element(2, Config),
Thresholds,
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 173).
?DOC(" Set the custom probes to poll. Replaces any previously configured list.\n").
-spec with_custom_statistics(config(), list(pharos@probe:probe())) -> config().
with_custom_statistics(Config, Probes) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
Probes,
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 178).
?DOC(" Set the custom probe thresholds. Replaces any previously configured list.\n").
-spec with_custom_thresholds(config(), list(pharos@probe:probe_threshold())) -> config().
with_custom_thresholds(Config, Thresholds) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
Thresholds,
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 186).
?DOC(" Set the alert sinks. Replaces any previously configured list.\n").
-spec with_alert_sinks(config(), list(alert_sink())) -> config().
with_alert_sinks(Config, Sinks) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
Sinks,
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 192).
?DOC(
" Set the memory unit used for threshold comparisons and decoded\n"
" measurements.\n"
).
-spec with_memory_unit(config(), pharos@measurement:memory_unit()) -> config().
with_memory_unit(Config, Unit) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
Unit,
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 198).
?DOC(
" Set the soak period (milliseconds a threshold must stay breached before\n"
" firing). Set to 0 to fire immediately.\n"
).
-spec with_soak_period(config(), integer()) -> config().
with_soak_period(Config, Milliseconds) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
Milliseconds,
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 204).
?DOC(
" Set the cool-down period (milliseconds recovery must hold before\n"
" resolving).\n"
).
-spec with_cool_period(config(), integer()) -> config().
with_cool_period(Config, Milliseconds) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
Milliseconds,
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 209).
?DOC(" Set the default alert level attached to firing alerts.\n").
-spec with_default_alert_level(config(), pharos@alert:alert_level()) -> config().
with_default_alert_level(Config, Level) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
Level,
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 214).
?DOC(" Set the hot-buffer capacity (number of recent metrics retained).\n").
-spec with_metric_buffer_capacity(config(), integer()) -> config().
with_metric_buffer_capacity(Config, Capacity) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
Capacity,
erlang:element(12, Config),
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 220).
?DOC(
" Stream buffered metrics to the registered process `name` on `node` (empty\n"
" `node` = local node). Enables the connection manager.\n"
).
-spec with_brain_stream(config(), binary(), binary()) -> config().
with_brain_stream(Config, Node, Name) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
{some, {brain_stream, Node, Name}},
erlang:element(13, Config),
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 227).
?DOC(
" Enable the Dets cold-tier spillover at `path`. Metrics spill to this file\n"
" when the Brain connection is lost and the hot buffer fills, and are replayed\n"
" (disk first) on reconnect. Only effective alongside `with_brain_stream`.\n"
).
-spec with_metric_spillover(config(), binary()) -> config().
with_metric_spillover(Config, Path) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
{some, Path},
erlang:element(14, Config)}.
-file("src/pharos/config.gleam", 235).
?DOC(
" Jitter polling by up to `ratio` of each statistic's interval (clamped to\n"
" `[0.0, 1.0]`). Each poller starts after a random delay in\n"
" `[0, interval * ratio)`, staggering traffic across a fleet so agents never\n"
" poll in lockstep.\n"
).
-spec with_poll_jitter(config(), float()) -> config().
with_poll_jitter(Config, Ratio) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
erlang:element(6, Config),
erlang:element(7, Config),
erlang:element(8, Config),
erlang:element(9, Config),
erlang:element(10, Config),
erlang:element(11, Config),
erlang:element(12, Config),
erlang:element(13, Config),
{some, gleam@float:clamp(Ratio, +0.0, 1.0)}}.
-file("src/pharos/config.gleam", 246).
?DOC(
" Stable string id derived from a threshold variant. Used to register\n"
" per-threshold alert managers under a deterministic name so they can be\n"
" looked up after a restart.\n"
).
-spec threshold_id(threshold()) -> binary().
threshold_id(Threshold) ->
case Threshold of
{total_memory, _} ->
<<"total_memory"/utf8>>;
{process_memory, _} ->
<<"process_memory"/utf8>>;
{system_memory, _} ->
<<"system_memory"/utf8>>;
{binary_memory, _} ->
<<"binary_memory"/utf8>>;
{ets_memory, _} ->
<<"ets_memory"/utf8>>;
{total_run_queue, _} ->
<<"total_run_queue"/utf8>>;
{cpu_run_queue, _} ->
<<"cpu_run_queue"/utf8>>;
{process_count, _} ->
<<"process_count"/utf8>>;
{atom_count, _} ->
<<"atom_count"/utf8>>;
{port_count, _} ->
<<"port_count"/utf8>>;
{persistent_term_count, _} ->
<<"persistent_term_count"/utf8>>;
{persistent_term_memory, _} ->
<<"persistent_term_memory"/utf8>>;
{host_memory_used, _} ->
<<"host_memory_used"/utf8>>;
{host_disk_used, _} ->
<<"host_disk_used"/utf8>>;
{host_cpu_util, _} ->
<<"host_cpu_util"/utf8>>;
{scheduler_utilization, _} ->
<<"scheduler_utilization"/utf8>>;
{windowed, Over, _, _} ->
<<"windowed_"/utf8, (threshold_id(Over))/binary>>
end.