Current section

Files

Jump to
spectator src spectator@internal@components@dashboard_live.erl
Raw

src/spectator@internal@components@dashboard_live.erl

-module(spectator@internal@components@dashboard_live).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/spectator/internal/components/dashboard_live.gleam").
-export([app/0]).
-export_type([model/0, relative_memory_statistics/0, relative_system_limits/0, msg/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(false).
-opaque model() :: {model,
gleam@option:option(gleam@erlang@atom:atom_()),
list({binary(), binary()}),
gleam@option:option(gleam@erlang@process:subject(msg())),
integer(),
gleam@option:option(spectator@internal@api:memory_statistics()),
gleam@option:option(relative_memory_statistics()),
gleam@option:option(spectator@internal@api:system_info()),
gleam@option:option(relative_system_limits()),
binary(),
binary(),
binary()}.
-type relative_memory_statistics() :: {relative_memory_statistics,
float(),
float(),
float(),
float(),
float(),
float(),
integer()}.
-type relative_system_limits() :: {relative_system_limits,
float(),
float(),
float(),
float()}.
-opaque msg() :: refresh |
{created_subject, gleam@erlang@process:subject(msg())} |
{node_input_changed, binary()} |
{cookie_input_changed, binary()} |
{refresh_input_changed, binary()}.
-file("src/spectator/internal/components/dashboard_live.gleam", 104).
?DOC(false).
-spec get_relative_memory_stats(spectator@internal@api:memory_statistics()) -> relative_memory_statistics().
get_relative_memory_stats(Input) ->
Factor = case erlang:float(erlang:element(2, Input)) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> 100.0 / Gleam@denominator
end,
Processes = erlang:float(erlang:element(3, Input)) * Factor,
Code = erlang:float(erlang:element(9, Input)) * Factor,
Ets = erlang:float(erlang:element(10, Input)) * Factor,
Atom = erlang:float(erlang:element(6, Input)) * Factor,
Binary = erlang:float(erlang:element(8, Input)) * Factor,
Other = ((((100.0 - Processes) - Code) - Ets) - Atom) - Binary,
{relative_memory_statistics,
Processes,
Code,
Ets,
Atom,
Binary,
Other,
(((erlang:element(5, Input) - erlang:element(6, Input)) - erlang:element(
8,
Input
))
- erlang:element(9, Input))
- erlang:element(10, Input)}.
-file("src/spectator/internal/components/dashboard_live.gleam", 128).
?DOC(false).
-spec get_relative_system_limits(spectator@internal@api:system_info()) -> relative_system_limits().
get_relative_system_limits(Input) ->
Processes = (case erlang:float(erlang:element(15, Input)) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> erlang:float(erlang:element(14, Input)) / Gleam@denominator
end) * 100.0,
Ports = (case erlang:float(erlang:element(13, Input)) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@1 -> erlang:float(erlang:element(12, Input)) / Gleam@denominator@1
end) * 100.0,
Atoms = (case erlang:float(erlang:element(9, Input)) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@2 -> erlang:float(erlang:element(8, Input)) / Gleam@denominator@2
end) * 100.0,
Ets = (case erlang:float(erlang:element(11, Input)) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@3 -> erlang:float(erlang:element(10, Input)) / Gleam@denominator@3
end) * 100.0,
{relative_system_limits, Processes, Ports, Atoms, Ets}.
-file("src/spectator/internal/components/dashboard_live.gleam", 143).
?DOC(false).
-spec do_refresh(model()) -> model().
do_refresh(Model) ->
Memory_stats = begin
_pipe = spectator_ffi:get_memory_statistics(erlang:element(2, Model)),
gleam@option:from_result(_pipe)
end,
Memory_relative = case Memory_stats of
none ->
none;
{some, Stats} ->
{some, get_relative_memory_stats(Stats)}
end,
System_info = begin
_pipe@1 = spectator_ffi:get_system_info(erlang:element(2, Model)),
gleam@option:from_result(_pipe@1)
end,
System_limits = case System_info of
none ->
none;
{some, Info} ->
{some, get_relative_system_limits(Info)}
end,
{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
Memory_stats,
Memory_relative,
System_info,
System_limits,
erlang:element(10, Model),
erlang:element(11, Model),
erlang:element(12, Model)}.
-file("src/spectator/internal/components/dashboard_live.gleam", 61).
?DOC(false).
-spec init(list({binary(), binary()})) -> {model(), lustre@effect:effect(msg())}.
init(Params) ->
Node = spectator@internal@api:node_from_params(Params),
Node_input = case Node of
{some, N} ->
erlang:atom_to_binary(N);
none ->
<<""/utf8>>
end,
Refresh_interval = spectator@internal@common:get_refresh_interval(Params),
Cookie_input = begin
_pipe = spectator@internal@common:get_param(Params, <<"cookie"/utf8>>),
gleam@result:unwrap(_pipe, <<""/utf8>>)
end,
Initial_model = do_refresh(
{model,
Node,
spectator@internal@common:sanitize_params(Params),
none,
Refresh_interval,
none,
none,
none,
none,
Node_input,
Cookie_input,
erlang:integer_to_binary(Refresh_interval)}
),
{Initial_model,
spectator@internal@common:emit_after(
erlang:element(5, Initial_model),
refresh,
none,
fun(Field@0) -> {created_subject, Field@0} end
)}.
-file("src/spectator/internal/components/dashboard_live.gleam", 161).
?DOC(false).
-spec update(model(), msg()) -> {model(), lustre@effect:effect(msg())}.
update(Model, Msg) ->
case Msg of
{node_input_changed, N} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
N,
erlang:element(11, Model),
erlang:element(12, Model)},
lustre@effect:none()};
{cookie_input_changed, C} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model),
C,
erlang:element(12, Model)},
lustre@effect:none()};
{refresh_input_changed, R} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model),
erlang:element(11, Model),
R},
lustre@effect:none()};
refresh ->
{do_refresh(Model),
spectator@internal@common:emit_after(
erlang:element(5, Model),
refresh,
erlang:element(4, Model),
fun(Field@0) -> {created_subject, Field@0} end
)};
{created_subject, Subject} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
{some, Subject},
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model),
erlang:element(11, Model),
erlang:element(12, Model)},
lustre@effect:none()}
end.
-file("src/spectator/internal/components/dashboard_live.gleam", 285).
?DOC(false).
-spec limit_label(binary(), integer(), integer(), float()) -> lustre@vdom@vnode:element(any()).
limit_label(Label, Value, Limit, Percent) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"limit-item"/utf8>>)],
[lustre@element@html:text(
<<<<<<<<<<<<<<Label/binary, ": "/utf8>>/binary,
(erlang:integer_to_binary(Value))/binary>>/binary,
" / "/utf8>>/binary,
(erlang:integer_to_binary(Limit))/binary>>/binary,
" ("/utf8>>/binary,
(spectator@internal@common:format_percentage(Percent))/binary>>/binary,
")"/utf8>>
)]
).
-file("src/spectator/internal/components/dashboard_live.gleam", 300).
?DOC(false).
-spec info_item(binary(), binary()) -> lustre@vdom@vnode:element(any()).
info_item(Label, Value) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"info-item"/utf8>>)],
[lustre@element@html:'div'(
[lustre@attribute:class(<<"info-label"/utf8>>)],
[lustre@element@html:text(Label)]
),
lustre@element@html:'div'(
[lustre@attribute:class(<<"info-value"/utf8>>)],
[lustre@element@html:text(Value)]
)]
).
-file("src/spectator/internal/components/dashboard_live.gleam", 307).
?DOC(false).
-spec info_field(binary(), binary(), fun((binary()) -> AAMD)) -> lustre@vdom@vnode:element(AAMD).
info_field(Label, Default_value, Handler) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"info-item"/utf8>>)],
[lustre@element@html:label(
[lustre@attribute:class(<<"info-label"/utf8>>)],
[lustre@element@html:text(Label)]
),
lustre@element@html:input(
[lustre@event:on_input(Handler),
lustre@attribute:class(<<"info-value"/utf8>>),
lustre@attribute:placeholder(Default_value)]
)]
).
-file("src/spectator/internal/components/dashboard_live.gleam", 318).
?DOC(false).
-spec target_actions(model()) -> lustre@vdom@vnode:element(any()).
target_actions(Model) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"info-item"/utf8>>)],
[lustre@element@html:a(
[lustre@attribute:class(<<"button"/utf8>>),
lustre@attribute:href(<<"/dashboard"/utf8>>)],
[lustre@element@html:text(<<"Reset to Self"/utf8>>)]
),
lustre@element@html:a(
[lustre@attribute:class(<<"button"/utf8>>),
lustre@attribute:href(
<<"/dashboard"/utf8,
(begin
_pipe = [],
_pipe@1 = spectator@internal@common:add_param(
_pipe,
<<"node"/utf8>>,
erlang:element(10, Model)
),
_pipe@2 = spectator@internal@common:add_param(
_pipe@1,
<<"cookie"/utf8>>,
erlang:element(11, Model)
),
_pipe@3 = spectator@internal@common:add_param(
_pipe@2,
<<"refresh"/utf8>>,
erlang:element(12, Model)
),
spectator@internal@common:encode_params(_pipe@3)
end)/binary>>
)],
[lustre@element@html:text(<<"Inspect Target"/utf8>>)]
)]
).
-file("src/spectator/internal/components/dashboard_live.gleam", 340).
?DOC(false).
-spec split_section(
list(lustre@vdom@vnode:element(AANE)),
list(lustre@vdom@vnode:element(AANE))
) -> lustre@vdom@vnode:element(AANE).
split_section(Left, Right) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"split"/utf8>>)],
[lustre@element@html:'div'(
[lustre@attribute:class(<<"split-left"/utf8>>)],
Left
),
lustre@element@html:'div'(
[lustre@attribute:class(<<"split-right"/utf8>>)],
Right
)]
).
-file("src/spectator/internal/components/dashboard_live.gleam", 347).
?DOC(false).
-spec render_memory_section(
spectator@internal@api:memory_statistics(),
relative_memory_statistics()
) -> lustre@vdom@vnode:element(any()).
render_memory_section(Memory_stats, Memory_relative) ->
lustre@element@html:section(
[],
[lustre@element@html:h1(
[],
[lustre@element@html:text(<<"Memory Usage"/utf8>>)]
),
spectator@internal@views@charts:column_chart(
[{chart_segment,
<<"#EF5976"/utf8>>,
<<"Processes"/utf8>>,
erlang:element(2, Memory_relative)},
{chart_segment,
<<"#FDA870"/utf8>>,
<<"Code "/utf8>>,
erlang:element(3, Memory_relative)},
{chart_segment,
<<"#ECE27C"/utf8>>,
<<"ETS"/utf8>>,
erlang:element(4, Memory_relative)},
{chart_segment,
<<"#95EA8C"/utf8>>,
<<"Atoms"/utf8>>,
erlang:element(5, Memory_relative)},
{chart_segment,
<<"#91D0DA"/utf8>>,
<<"Binaries"/utf8>>,
erlang:element(6, Memory_relative)},
{chart_segment,
<<"#B498F6"/utf8>>,
<<"Other"/utf8>>,
erlang:element(7, Memory_relative)}]
),
lustre@element@html:'div'(
[lustre@attribute:class(<<"memory-breakdown"/utf8>>)],
[spectator@internal@views@charts:legend_item(
<<"Total"/utf8>>,
<<"var(--background)"/utf8>>,
spectator@internal@views@display:storage(
erlang:element(2, Memory_stats)
)
),
spectator@internal@views@charts:legend_item(
<<"Processes"/utf8>>,
<<"#EF5976"/utf8>>,
spectator@internal@views@display:storage(
erlang:element(3, Memory_stats)
)
),
spectator@internal@views@charts:legend_item(
<<"Code"/utf8>>,
<<"#FDA870"/utf8>>,
spectator@internal@views@display:storage(
erlang:element(9, Memory_stats)
)
),
spectator@internal@views@charts:legend_item(
<<"ETS"/utf8>>,
<<"#ECE27C"/utf8>>,
spectator@internal@views@display:storage(
erlang:element(10, Memory_stats)
)
),
spectator@internal@views@charts:legend_item(
<<"Atoms"/utf8>>,
<<"#95EA8C"/utf8>>,
spectator@internal@views@display:storage(
erlang:element(6, Memory_stats)
)
),
spectator@internal@views@charts:legend_item(
<<"Binaries"/utf8>>,
<<"#91D0DA"/utf8>>,
spectator@internal@views@display:storage(
erlang:element(8, Memory_stats)
)
),
spectator@internal@views@charts:legend_item(
<<"Other"/utf8>>,
<<"#B498F6"/utf8>>,
spectator@internal@views@display:storage(
erlang:element(8, Memory_relative)
)
)]
)]
).
-file("src/spectator/internal/components/dashboard_live.gleam", 186).
?DOC(false).
-spec view(model()) -> lustre@vdom@vnode:element(msg()).
view(Model) ->
_pipe = begin
gleam@option:then(
erlang:element(6, Model),
fun(Memory_stats) ->
gleam@option:then(
erlang:element(7, Model),
fun(Memory_relative) ->
gleam@option:then(
erlang:element(8, Model),
fun(System_info) ->
gleam@option:then(
erlang:element(9, Model),
fun(System_limits) ->
{some,
lustre@element@html:'div'(
[lustre@attribute:class(
<<"dashboard"/utf8>>
)],
[split_section(
[lustre@element@html:h1(
[],
[lustre@element@html:text(
<<"Inspect BEAM Nodes"/utf8>>
)]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"info-container"/utf8>>
)],
[info_field(
<<"Node"/utf8>>,
case erlang:element(
10,
Model
) of
<<""/utf8>> ->
<<"Enter node name..."/utf8>>;
N ->
N
end,
fun(Field@0) -> {node_input_changed, Field@0} end
),
info_field(
<<"Cookie"/utf8>>,
case erlang:element(
11,
Model
) of
<<""/utf8>> ->
<<"Enter cookie or leave empty"/utf8>>;
N@1 ->
N@1
end,
fun(Field@0) -> {cookie_input_changed, Field@0} end
),
info_field(
<<"Refresh Interval (ms)"/utf8>>,
erlang:element(
12,
Model
),
fun(Field@0) -> {refresh_input_changed, Field@0} end
),
target_actions(
Model
)]
),
lustre@element@html:h1(
[],
[lustre@element@html:text(
<<"System Information"/utf8>>
)]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"info-container"/utf8>>
)],
[info_item(
<<"Uptime"/utf8>>,
erlang:element(
2,
System_info
)
),
info_item(
<<"System Architecture"/utf8>>,
erlang:element(
3,
System_info
)
),
info_item(
<<"Runtime Version"/utf8>>,
erlang:element(
4,
System_info
)
),
info_item(
<<"OTP Release"/utf8>>,
erlang:element(
5,
System_info
)
),
info_item(
<<"Schedulers"/utf8>>,
<<<<(erlang:integer_to_binary(
erlang:element(
7,
System_info
)
))/binary,
" / "/utf8>>/binary,
(erlang:integer_to_binary(
erlang:element(
6,
System_info
)
))/binary>>
)]
)],
[lustre@element@html:h1(
[],
[lustre@element@html:text(
<<"System Limits"/utf8>>
)]
),
spectator@internal@views@charts:meter(
erlang:element(
2,
System_limits
)
),
limit_label(
<<"Processes"/utf8>>,
erlang:element(
14,
System_info
),
erlang:element(
15,
System_info
),
erlang:element(
2,
System_limits
)
),
spectator@internal@views@charts:meter(
erlang:element(
3,
System_limits
)
),
limit_label(
<<"Ports"/utf8>>,
erlang:element(
12,
System_info
),
erlang:element(
13,
System_info
),
erlang:element(
3,
System_limits
)
),
spectator@internal@views@charts:meter(
erlang:element(
4,
System_limits
)
),
limit_label(
<<"Atoms"/utf8>>,
erlang:element(
8,
System_info
),
erlang:element(
9,
System_info
),
erlang:element(
4,
System_limits
)
),
spectator@internal@views@charts:meter(
erlang:element(
5,
System_limits
)
),
limit_label(
<<"ETS"/utf8>>,
erlang:element(
10,
System_info
),
erlang:element(
11,
System_info
),
erlang:element(
5,
System_limits
)
)]
),
render_memory_section(
Memory_stats,
Memory_relative
)]
)}
end
)
end
)
end
)
end
)
end,
gleam@option:unwrap(
_pipe,
lustre@element@html:'div'(
[lustre@attribute:class(<<"component-error"/utf8>>)],
[lustre@element@html:text(<<"Could not fetch dashboard data"/utf8>>)]
)
).
-file("src/spectator/internal/components/dashboard_live.gleam", 19).
?DOC(false).
-spec app() -> lustre:app(list({binary(), binary()}), model(), msg()).
app() ->
lustre:application(fun init/1, fun update/2, fun view/1).