-module(pharos@threshold_eval). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/pharos/threshold_eval.gleam"). -export([evaluate_probe/2, evaluate/2]). -export_type([verdict/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( " Evaluate a `Threshold` against a decoded `Measurement`.\n" "\n" " Returns a three-way verdict so callers can branch without reaching\n" " for nested `case` over the cartesian product of measurements and\n" " thresholds. Helper functions match every measurement variant\n" " exhaustively, so adding a new measurement kind surfaces as a\n" " compiler warning here.\n" ). -type verdict() :: not_applicable | healthy | breached. -file("src/pharos/threshold_eval.gleam", 177). -spec verdict(boolean()) -> verdict(). verdict(Is_breached) -> case Is_breached of true -> breached; false -> healthy end. -file("src/pharos/threshold_eval.gleam", 38). ?DOC( " Evaluate a probe `threshold` against a decoded probe `sample`, returning\n" " the same `Verdict` as `evaluate/2`. A `NotApplicable` verdict means the\n" " threshold's field is absent from this sample, so the caller should neither\n" " breach nor recover.\n" ). -spec evaluate_probe( gleam@dict:dict(binary(), float()), pharos@probe:probe_threshold() ) -> verdict(). evaluate_probe(Sample, Threshold) -> case gleam_stdlib:map_get(Sample, erlang:element(3, Threshold)) of {error, nil} -> not_applicable; {ok, Value} -> case erlang:element(4, Threshold) of {above, Limit} -> verdict(Value > Limit); {below, Limit@1} -> verdict(Value < Limit@1) end end. -file("src/pharos/threshold_eval.gleam", 157). ?DOC( " Evaluate a host-memory threshold. A host probe still reporting\n" " `Unimplemented` (e.g. the non-Linux `/proc/meminfo` fallback) is treated as\n" " `NotApplicable` so its placeholder zeros never produce breach/recover noise.\n" ). -spec check_host_memory( pharos@measurement:measurement(), fun((pharos@measurement:host_memory_stats()) -> boolean()) ) -> verdict(). check_host_memory(Measurement, Predicate) -> case Measurement of {host_memory, Host} -> case erlang:element(2, Host) of unimplemented -> not_applicable; implemented -> verdict(Predicate(Host)) end; {beam_memory, _} -> not_applicable; {beam_run_queues, _} -> not_applicable; {beam_system_counts, _} -> not_applicable; {beam_persistent_term, _} -> not_applicable; {process_info, _} -> not_applicable; {cluster_nodes, _} -> not_applicable; {host_disk, _} -> not_applicable end. -file("src/pharos/threshold_eval.gleam", 138). -spec check_persistent_term( pharos@measurement:measurement(), fun((pharos@measurement:persistent_term_stats()) -> boolean()) ) -> verdict(). check_persistent_term(Measurement, Predicate) -> case Measurement of {beam_persistent_term, Term} -> verdict(Predicate(Term)); {beam_memory, _} -> not_applicable; {beam_run_queues, _} -> not_applicable; {beam_system_counts, _} -> not_applicable; {process_info, _} -> not_applicable; {cluster_nodes, _} -> not_applicable; {host_memory, _} -> not_applicable; {host_disk, _} -> not_applicable end. -file("src/pharos/threshold_eval.gleam", 122). -spec check_system_counts( pharos@measurement:measurement(), fun((pharos@measurement:system_count_stats()) -> boolean()) ) -> verdict(). check_system_counts(Measurement, Predicate) -> case Measurement of {beam_system_counts, Counts} -> verdict(Predicate(Counts)); {beam_memory, _} -> not_applicable; {beam_run_queues, _} -> not_applicable; {beam_persistent_term, _} -> not_applicable; {process_info, _} -> not_applicable; {cluster_nodes, _} -> not_applicable; {host_memory, _} -> not_applicable; {host_disk, _} -> not_applicable end. -file("src/pharos/threshold_eval.gleam", 106). -spec check_run_queue( pharos@measurement:measurement(), fun((pharos@measurement:run_queue_stats()) -> boolean()) ) -> verdict(). check_run_queue(Measurement, Predicate) -> case Measurement of {beam_run_queues, Queue} -> verdict(Predicate(Queue)); {beam_memory, _} -> not_applicable; {beam_system_counts, _} -> not_applicable; {beam_persistent_term, _} -> not_applicable; {process_info, _} -> not_applicable; {cluster_nodes, _} -> not_applicable; {host_memory, _} -> not_applicable; {host_disk, _} -> not_applicable end. -file("src/pharos/threshold_eval.gleam", 90). -spec check_memory( pharos@measurement:measurement(), fun((pharos@measurement:beam_memory_stats()) -> boolean()) ) -> verdict(). check_memory(Measurement, Predicate) -> case Measurement of {beam_memory, Memory} -> verdict(Predicate(Memory)); {beam_run_queues, _} -> not_applicable; {beam_system_counts, _} -> not_applicable; {beam_persistent_term, _} -> not_applicable; {process_info, _} -> not_applicable; {cluster_nodes, _} -> not_applicable; {host_memory, _} -> not_applicable; {host_disk, _} -> not_applicable end. -file("src/pharos/threshold_eval.gleam", 53). ?DOC(" Evaluate `threshold` against `measurement` and return a `Verdict`.\n"). -spec evaluate(pharos@measurement:measurement(), pharos@config:threshold()) -> verdict(). evaluate(Measurement, Threshold) -> case Threshold of {total_memory, Limit} -> check_memory( Measurement, fun(Memory) -> erlang:element(3, Memory) > Limit end ); {process_memory, Limit@1} -> check_memory( Measurement, fun(Memory@1) -> erlang:element(4, Memory@1) > Limit@1 end ); {system_memory, Limit@2} -> check_memory( Measurement, fun(Memory@2) -> erlang:element(6, Memory@2) > Limit@2 end ); {binary_memory, Limit@3} -> check_memory( Measurement, fun(Memory@3) -> erlang:element(9, Memory@3) > Limit@3 end ); {ets_memory, Limit@4} -> check_memory( Measurement, fun(Memory@4) -> erlang:element(11, Memory@4) > Limit@4 end ); {total_run_queue, Limit@5} -> check_run_queue( Measurement, fun(Queue) -> erlang:element(2, Queue) > Limit@5 end ); {cpu_run_queue, Limit@6} -> check_run_queue( Measurement, fun(Queue@1) -> erlang:element(3, Queue@1) > Limit@6 end ); {process_count, Limit@7} -> check_system_counts( Measurement, fun(Counts) -> erlang:element(2, Counts) > Limit@7 end ); {atom_count, Limit@8} -> check_system_counts( Measurement, fun(Counts@1) -> erlang:element(3, Counts@1) > Limit@8 end ); {port_count, Limit@9} -> check_system_counts( Measurement, fun(Counts@2) -> erlang:element(4, Counts@2) > Limit@9 end ); {persistent_term_count, Limit@10} -> check_persistent_term( Measurement, fun(Term) -> erlang:element(2, Term) > Limit@10 end ); {persistent_term_memory, Limit@11} -> check_persistent_term( Measurement, fun(Term@1) -> erlang:element(4, Term@1) > Limit@11 end ); {host_memory_used, Limit@12} -> check_host_memory( Measurement, fun(Host) -> erlang:element(5, Host) > Limit@12 end ) end.