-module(lightspeed@ops@slo_autopilot).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/ops/slo_autopilot.gleam").
-export([sample/5, thresholds/4, default_thresholds/0, new/1, active_controls/1, rollback/6, apply/6, recommended_controls/2, classify/2, evaluate/4, runtime_thresholds/1, audit_entries/1, reversible/1, status_label/1, control_label/1, decision_label/1, sample_label/1, thresholds_label/1, audit_label/1, audit_metric/1, valid/1, signature/1]).
-export_type([burn_rate_sample/0, thresholds/0, status/0, control/0, decision/0, audit_entry/0, runtime/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(" SLO burn-rate and mitigation-control contracts for M30.\n").
-type burn_rate_sample() :: {burn_rate_sample,
binary(),
binary(),
integer(),
integer(),
binary()}.
-type thresholds() :: {thresholds, integer(), integer(), integer(), integer()}.
-type status() :: healthy | warning | critical.
-type control() :: {shed_events, integer()} |
pause_background_jobs |
{isolate_hotspot_tenant, binary()} |
enter_read_only_mode.
-type decision() :: applied | rolled_back | {noop, binary()}.
-type audit_entry() :: {audit_entry,
binary(),
control(),
decision(),
binary(),
integer(),
status()}.
-opaque runtime() :: {runtime,
thresholds(),
list(control()),
list(audit_entry())}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 72).
?DOC(" Build one burn-rate sample.\n").
-spec sample(binary(), binary(), integer(), integer(), binary()) -> burn_rate_sample().
sample(
Service,
Slo_name,
Short_window_milli,
Long_window_milli,
Hotspot_tenant_id
) ->
{burn_rate_sample,
Service,
Slo_name,
Short_window_milli,
Long_window_milli,
Hotspot_tenant_id}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 89).
?DOC(" Build one threshold profile.\n").
-spec thresholds(integer(), integer(), integer(), integer()) -> thresholds().
thresholds(
Warn_short_milli,
Warn_long_milli,
Critical_short_milli,
Critical_long_milli
) ->
{thresholds,
Warn_short_milli,
Warn_long_milli,
Critical_short_milli,
Critical_long_milli}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 104).
?DOC(" Default M30 threshold profile.\n").
-spec default_thresholds() -> thresholds().
default_thresholds() ->
{thresholds, 1000, 700, 2000, 1500}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 114).
?DOC(" Build one autopilot runtime.\n").
-spec new(thresholds()) -> runtime().
new(Thresholds) ->
{runtime, Thresholds, [], []}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 249).
?DOC(" Active controls in stable order.\n").
-spec active_controls(runtime()) -> list(control()).
active_controls(Runtime) ->
lists:reverse(erlang:element(3, Runtime)).
-file("src/lightspeed/ops/slo_autopilot.gleam", 455).
-spec record_audit(runtime(), audit_entry()) -> runtime().
record_audit(Runtime, Entry) ->
{runtime,
erlang:element(2, Runtime),
erlang:element(3, Runtime),
[Entry | erlang:element(4, Runtime)]}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 484).
-spec remove_control(list(control()), control()) -> list(control()).
remove_control(Controls, Target) ->
case Controls of
[] ->
[];
[Control | Rest] ->
case Control =:= Target of
true ->
Rest;
false ->
[Control | remove_control(Rest, Target)]
end
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 473).
-spec has_control(list(control()), control()) -> boolean().
has_control(Controls, Target) ->
case Controls of
[] ->
false;
[Control | Rest] ->
case Control =:= Target of
true ->
true;
false ->
has_control(Rest, Target)
end
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 203).
?DOC(" Roll back one control with an audit trail entry.\n").
-spec rollback(runtime(), control(), binary(), binary(), integer(), status()) -> runtime().
rollback(Runtime, Control, Actor_id, Reason, At_ms, Status) ->
case has_control(erlang:element(3, Runtime), Control) of
true ->
_pipe = {runtime,
erlang:element(2, Runtime),
remove_control(erlang:element(3, Runtime), Control),
erlang:element(4, Runtime)},
record_audit(
_pipe,
{audit_entry,
Actor_id,
Control,
rolled_back,
Reason,
At_ms,
Status}
);
false ->
record_audit(
Runtime,
{audit_entry,
Actor_id,
Control,
{noop, <<"not_active"/utf8>>},
Reason,
At_ms,
Status}
)
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 422).
-spec rollback_loop(
list(control()),
runtime(),
list(control()),
binary(),
integer(),
status()
) -> runtime().
rollback_loop(Current, Runtime, Desired, Actor_id, Now_ms, Status) ->
case Current of
[] ->
Runtime;
[Control | Rest] ->
case has_control(Desired, Control) of
true ->
rollback_loop(
Rest,
Runtime,
Desired,
Actor_id,
Now_ms,
Status
);
false ->
rollback_loop(
Rest,
rollback(
Runtime,
Control,
Actor_id,
<<"auto_reconcile"/utf8>>,
Now_ms,
Status
),
Desired,
Actor_id,
Now_ms,
Status
)
end
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 405).
-spec rollback_extra_controls(
runtime(),
list(control()),
binary(),
integer(),
status()
) -> runtime().
rollback_extra_controls(Runtime, Desired, Actor_id, Now_ms, Status) ->
rollback_loop(
active_controls(Runtime),
Runtime,
Desired,
Actor_id,
Now_ms,
Status
).
-file("src/lightspeed/ops/slo_autopilot.gleam", 165).
?DOC(" Apply one control with an audit trail entry.\n").
-spec apply(runtime(), control(), binary(), binary(), integer(), status()) -> runtime().
apply(Runtime, Control, Actor_id, Reason, At_ms, Status) ->
case has_control(erlang:element(3, Runtime), Control) of
true ->
record_audit(
Runtime,
{audit_entry,
Actor_id,
Control,
{noop, <<"already_active"/utf8>>},
Reason,
At_ms,
Status}
);
false ->
_pipe = {runtime,
erlang:element(2, Runtime),
[Control | erlang:element(3, Runtime)],
erlang:element(4, Runtime)},
record_audit(
_pipe,
{audit_entry, Actor_id, Control, applied, Reason, At_ms, Status}
)
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 385).
-spec apply_missing_controls(
runtime(),
list(control()),
binary(),
integer(),
status()
) -> runtime().
apply_missing_controls(Runtime, Desired, Actor_id, Now_ms, Status) ->
case Desired of
[] ->
Runtime;
[Control | Rest] ->
apply_missing_controls(
apply(
Runtime,
Control,
Actor_id,
<<"auto_reconcile"/utf8>>,
Now_ms,
Status
),
Rest,
Actor_id,
Now_ms,
Status
)
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 373).
-spec reconcile_controls(
runtime(),
list(control()),
binary(),
integer(),
status()
) -> runtime().
reconcile_controls(Runtime, Desired, Actor_id, Now_ms, Status) ->
Applied = apply_missing_controls(Runtime, Desired, Actor_id, Now_ms, Status),
rollback_extra_controls(Applied, Desired, Actor_id, Now_ms, Status).
-file("src/lightspeed/ops/slo_autopilot.gleam", 459).
-spec hotspot_control(binary()) -> list(control()).
hotspot_control(Tenant_id) ->
case Tenant_id of
<<""/utf8>> ->
[];
_ ->
[{isolate_hotspot_tenant, Tenant_id}]
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 526).
-spec append(list(control()), list(control())) -> list(control()).
append(Left, Right) ->
case Left of
[] ->
Right;
[Entry | Rest] ->
[Entry | append(Rest, Right)]
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 149).
?DOC(" Desired controls for one sample/status pair.\n").
-spec recommended_controls(burn_rate_sample(), status()) -> list(control()).
recommended_controls(Sample, Status) ->
case Status of
healthy ->
[];
warning ->
_pipe = [{shed_events, 15}, pause_background_jobs],
append(_pipe, hotspot_control(erlang:element(6, Sample)));
critical ->
_pipe@1 = [{shed_events, 40},
pause_background_jobs,
enter_read_only_mode],
append(_pipe@1, hotspot_control(erlang:element(6, Sample)))
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 131).
?DOC(" Classify one burn-rate sample against thresholds.\n").
-spec classify(burn_rate_sample(), thresholds()) -> status().
classify(Sample, Thresholds) ->
case (erlang:element(4, Sample) >= erlang:element(4, Thresholds)) orelse (erlang:element(
5,
Sample
)
>= erlang:element(5, Thresholds)) of
true ->
critical;
false ->
case (erlang:element(4, Sample) >= erlang:element(2, Thresholds))
orelse (erlang:element(5, Sample) >= erlang:element(3, Thresholds)) of
true ->
warning;
false ->
healthy
end
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 119).
?DOC(" Evaluate one sample and reconcile active controls.\n").
-spec evaluate(runtime(), burn_rate_sample(), binary(), integer()) -> {runtime(),
status()}.
evaluate(Runtime, Sample, Actor_id, Now_ms) ->
Status = classify(Sample, erlang:element(2, Runtime)),
Desired = recommended_controls(Sample, Status),
{reconcile_controls(Runtime, Desired, Actor_id, Now_ms, Status), Status}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 244).
?DOC(" Threshold accessor.\n").
-spec runtime_thresholds(runtime()) -> thresholds().
runtime_thresholds(Runtime) ->
erlang:element(2, Runtime).
-file("src/lightspeed/ops/slo_autopilot.gleam", 254).
?DOC(" Audit entries in stable order.\n").
-spec audit_entries(runtime()) -> list(audit_entry()).
audit_entries(Runtime) ->
lists:reverse(erlang:element(4, Runtime)).
-file("src/lightspeed/ops/slo_autopilot.gleam", 259).
?DOC(" Return `True` when one control can be rolled back.\n").
-spec reversible(control()) -> boolean().
reversible(Control) ->
case Control of
{shed_events, _} ->
true;
pause_background_jobs ->
true;
{isolate_hotspot_tenant, _} ->
true;
enter_read_only_mode ->
true
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 269).
?DOC(" Stable status label.\n").
-spec status_label(status()) -> binary().
status_label(Status) ->
case Status of
healthy ->
<<"healthy"/utf8>>;
warning ->
<<"warning"/utf8>>;
critical ->
<<"critical"/utf8>>
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 278).
?DOC(" Stable control label.\n").
-spec control_label(control()) -> binary().
control_label(Control) ->
case Control of
{shed_events, Percent} ->
<<"shed_events:"/utf8, (erlang:integer_to_binary(Percent))/binary>>;
pause_background_jobs ->
<<"pause_background_jobs"/utf8>>;
{isolate_hotspot_tenant, Tenant_id} ->
<<"isolate_tenant:"/utf8, Tenant_id/binary>>;
enter_read_only_mode ->
<<"enter_read_only_mode"/utf8>>
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 288).
?DOC(" Stable decision label.\n").
-spec decision_label(decision()) -> binary().
decision_label(Decision) ->
case Decision of
applied ->
<<"applied"/utf8>>;
rolled_back ->
<<"rolled_back"/utf8>>;
{noop, Reason} ->
<<"noop:"/utf8, Reason/binary>>
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 466).
-spec hotspot_label(binary()) -> binary().
hotspot_label(Tenant_id) ->
case Tenant_id of
<<""/utf8>> ->
<<"none"/utf8>>;
_ ->
Tenant_id
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 297).
?DOC(" Stable sample label.\n").
-spec sample_label(burn_rate_sample()) -> binary().
sample_label(Sample) ->
<<<<<<<<<<<<<<<<<<"service="/utf8, (erlang:element(2, Sample))/binary>>/binary,
"|slo="/utf8>>/binary,
(erlang:element(3, Sample))/binary>>/binary,
"|short="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(4, Sample)))/binary>>/binary,
"|long="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(5, Sample)))/binary>>/binary,
"|hotspot_tenant="/utf8>>/binary,
(hotspot_label(erlang:element(6, Sample)))/binary>>.
-file("src/lightspeed/ops/slo_autopilot.gleam", 311).
?DOC(" Stable threshold label.\n").
-spec thresholds_label(thresholds()) -> binary().
thresholds_label(Thresholds) ->
<<<<<<<<<<<<<<"warn_short="/utf8,
(erlang:integer_to_binary(
erlang:element(2, Thresholds)
))/binary>>/binary,
",warn_long="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, Thresholds)))/binary>>/binary,
",critical_short="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(4, Thresholds)))/binary>>/binary,
",critical_long="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(5, Thresholds)))/binary>>.
-file("src/lightspeed/ops/slo_autopilot.gleam", 323).
?DOC(" Stable audit-entry label.\n").
-spec audit_label(audit_entry()) -> binary().
audit_label(Entry) ->
<<<<<<<<<<<<<<<<<<<<<<"actor="/utf8, (erlang:element(2, Entry))/binary>>/binary,
"|control="/utf8>>/binary,
(control_label(erlang:element(3, Entry)))/binary>>/binary,
"|decision="/utf8>>/binary,
(decision_label(erlang:element(4, Entry)))/binary>>/binary,
"|reason="/utf8>>/binary,
(erlang:element(5, Entry))/binary>>/binary,
"|status="/utf8>>/binary,
(status_label(erlang:element(7, Entry)))/binary>>/binary,
"|at_ms="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(6, Entry)))/binary>>.
-file("src/lightspeed/ops/slo_autopilot.gleam", 339).
?DOC(" Convert one audit entry into a metric point.\n").
-spec audit_metric(audit_entry()) -> lightspeed@ops@telemetry:metric().
audit_metric(Entry) ->
{counter,
<<"lightspeed.slo.autopilot_control_total"/utf8>>,
1,
[{tag, <<"actor_id"/utf8>>, erlang:element(2, Entry)},
{tag, <<"control"/utf8>>, control_label(erlang:element(3, Entry))},
{tag, <<"decision"/utf8>>, decision_label(erlang:element(4, Entry))},
{tag, <<"status"/utf8>>, status_label(erlang:element(7, Entry))}]}.
-file("src/lightspeed/ops/slo_autopilot.gleam", 508).
-spec audits_reversible(list(audit_entry())) -> boolean().
audits_reversible(Entries) ->
case Entries of
[] ->
true;
[Entry | Rest] ->
reversible(erlang:element(3, Entry)) andalso audits_reversible(Rest)
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 515).
-spec contains(list(binary()), binary()) -> boolean().
contains(Values, Target) ->
case Values of
[] ->
false;
[Value | Rest] ->
case Value =:= Target of
true ->
true;
false ->
contains(Rest, Target)
end
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 495).
-spec unique_controls(list(control()), list(binary())) -> boolean().
unique_controls(Controls, Seen) ->
case Controls of
[] ->
true;
[Control | Rest] ->
Label = control_label(Control),
case contains(Seen, Label) of
true ->
false;
false ->
unique_controls(Rest, [Label | Seen])
end
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 353).
?DOC(" Runtime invariants.\n").
-spec valid(runtime()) -> boolean().
valid(Runtime) ->
Thresholds = erlang:element(2, Runtime),
(((((erlang:element(2, Thresholds) > 0) andalso (erlang:element(
3,
Thresholds
)
> 0))
andalso (erlang:element(4, Thresholds) >= erlang:element(2, Thresholds)))
andalso (erlang:element(5, Thresholds) >= erlang:element(3, Thresholds)))
andalso unique_controls(active_controls(Runtime), []))
andalso audits_reversible(audit_entries(Runtime)).
-file("src/lightspeed/ops/slo_autopilot.gleam", 533).
-spec join_with(binary(), list(binary())) -> binary().
join_with(Separator, Values) ->
case Values of
[] ->
<<""/utf8>>;
[Value] ->
Value;
[Value@1 | Rest] ->
<<<<Value@1/binary, Separator/binary>>/binary,
(join_with(Separator, Rest))/binary>>
end.
-file("src/lightspeed/ops/slo_autopilot.gleam", 364).
?DOC(" Stable runtime signature for deterministic fixtures.\n").
-spec signature(runtime()) -> binary().
signature(Runtime) ->
<<<<<<<<<<"thresholds="/utf8,
(thresholds_label(erlang:element(2, Runtime)))/binary>>/binary,
"|active="/utf8>>/binary,
(join_with(
<<","/utf8>>,
gleam@list:map(
active_controls(Runtime),
fun control_label/1
)
))/binary>>/binary,
"|audit="/utf8>>/binary,
(erlang:integer_to_binary(erlang:length(erlang:element(4, Runtime))))/binary>>.