Current section

Files

Jump to
themis src themis@internal@store.erl
Raw

src/themis@internal@store.erl

-module(themis@internal@store).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([new_metric/4, find_metric/2, match_metrics/1, init/0, clear/0, increment_record_by/3, increment_record/2, insert_record/3, match_records/1, find_record/2]).
-export_type([store_error/0, store/0]).
-type store_error() :: metric_name_already_exists |
insert_error |
{decode_errors, list(gleam@dynamic@decode:decode_error())} |
{old_decode_errors, list(gleam@dynamic:decode_error())} |
table_error |
invalid_increment |
single_result_expected |
invalid_type |
metric_not_found.
-type store() :: {store,
themis@internal@erlang@ets:table(),
themis@internal@erlang@ets:table()}.
-file("/git/Themis/src/themis/internal/store.gleam", 213).
-spec decode_metric(gleam@dynamic:dynamic_()) -> {ok,
{binary(), binary(), binary(), list(float())}} |
{error, list(gleam@dynamic@decode:decode_error())}.
decode_metric(Metric) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Metric,
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
fun(Field_1) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Metric,
gleam@dynamic@decode:at(
[1],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
fun(Field_2) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Metric,
gleam@dynamic@decode:at(
[2],
{decoder,
fun gleam@dynamic@decode:decode_string/1}
)
),
fun(Field_3) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Metric,
gleam@dynamic@decode:at(
[3],
gleam@dynamic@decode:list(
{decoder,
fun gleam@dynamic@decode:decode_float/1}
)
)
),
fun(Field_4) ->
{ok, {Field_1, Field_2, Field_3, Field_4}}
end
)
end
)
end
)
end
).
-file("/git/Themis/src/themis/internal/store.gleam", 226).
-spec decode_record(gleam@dynamic:dynamic_()) -> {ok,
{{binary(), list(binary())}, integer(), float(), binary()}} |
{error, list(gleam@dynamic@decode:decode_error())}.
decode_record(Record) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Record,
gleam@dynamic@decode:at(
[0, 0],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
fun(Field_1_1) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Record,
gleam@dynamic@decode:at(
[0, 1],
gleam@dynamic@decode:list(
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
)
),
fun(Field_1_2) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Record,
gleam@dynamic@decode:at(
[1],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
fun(Field_2) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Record,
gleam@dynamic@decode:at(
[2],
{decoder,
fun gleam@dynamic@decode:decode_float/1}
)
),
fun(Field_3) ->
gleam@result:'try'(
gleam@dynamic@decode:run(
Record,
gleam@dynamic@decode:at(
[3],
{decoder,
fun gleam@dynamic@decode:decode_string/1}
)
),
fun(Field_4) ->
{ok,
{{Field_1_1, Field_1_2},
Field_2,
Field_3,
Field_4}}
end
)
end
)
end
)
end
)
end
).
-file("/git/Themis/src/themis/internal/store.gleam", 246).
-spec parse_record(gleam@dynamic:dynamic_()) -> {ok,
{themis@internal@label:label_set(), themis@number:number_()}} |
{error, store_error()}.
parse_record(Record) ->
Record_result = begin
_pipe = decode_record(Record),
gleam@result:try_recover(
_pipe,
fun(E) -> {error, {decode_errors, E}} end
)
end,
gleam@result:'try'(
Record_result,
fun(Record@1) ->
{{_, Labels}, Int_value, Float_value, Flag} = Record@1,
_assert_subject = gleam@float:modulo(Float_value, 1.0),
{ok, Float_decimal} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"parse_record"/utf8>>,
line => 263})
end,
Numeric_value = case Float_decimal =:= +0.0 of
false ->
themis@number:decimal(
begin
_pipe@1 = Int_value,
_pipe@2 = erlang:float(_pipe@1),
gleam@float:add(_pipe@2, Float_value)
end
);
true ->
themis@number:integer(Int_value)
end,
Value = case Flag of
<<"-Inf"/utf8>> ->
themis@number:negative_infinity();
<<"+Inf"/utf8>> ->
themis@number:positive_infinity();
<<"NaN"/utf8>> ->
themis@number:not_a_number();
_ ->
Numeric_value
end,
Labels@1 = begin
_pipe@3 = Labels,
_pipe@4 = gleam@list:map(
_pipe@3,
fun(Label_string) ->
_assert_subject@1 = gleam@string:split_once(
Label_string,
<<":"/utf8>>
),
{ok, {Key, Value@1}} = case _assert_subject@1 of
{ok, {_, _}} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail@1,
module => <<"themis/internal/store"/utf8>>,
function => <<"parse_record"/utf8>>,
line => 277})
end,
{Key, Value@1}
end
),
maps:from_list(_pipe@4)
end,
_assert_subject@2 = themis@internal@label:from_dict(Labels@1),
{ok, Labels@2} = case _assert_subject@2 of
{ok, _} -> _assert_subject@2;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail@2,
module => <<"themis/internal/store"/utf8>>,
function => <<"parse_record"/utf8>>,
line => 281})
end,
_pipe@5 = {Labels@2, Value},
{ok, _pipe@5}
end
).
-file("/git/Themis/src/themis/internal/store.gleam", 53).
-spec new_metric(
themis@internal@metric:metric_name(),
binary(),
binary(),
list(float())
) -> {ok, nil} | {error, store_error()}.
new_metric(Name, Description, Kind, Buckets) ->
_pipe@2 = themis@internal@erlang@ets:insert_new_raw(
<<"themis_metrics"/utf8>>,
begin
_pipe@1 = {begin
_pipe = Name,
themis@internal@metric:name_to_string(_pipe)
end,
Description,
Kind,
Buckets},
gleam_stdlib:identity(_pipe@1)
end
),
gleam@result:replace_error(_pipe@2, metric_name_already_exists).
-file("/git/Themis/src/themis/internal/store.gleam", 69).
-spec find_metric(themis@internal@metric:metric_name(), binary()) -> {ok,
{binary(), binary(), list(float())}} |
{error, store_error()}.
find_metric(Name, Given_kind) ->
Name_string = themis@internal@metric:name_to_string(Name),
_assert_subject = themis@internal@erlang@ets:lookup(
<<"themis_metrics"/utf8>>,
Name_string
),
{ok, Metrics} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => (<<<<"could not find metric \""/utf8,
Name_string/binary>>/binary,
"\". should only return an error if the given table name string is not found as an atom. Are you sure you initialized the Themis store ?"/utf8>>),
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"find_metric"/utf8>>,
line => 76})
end,
gleam@result:'try'(
case begin
_pipe = Metrics,
gleam@list:map(_pipe, fun(Found) -> decode_metric(Found) end)
end of
[{ok, {_, Description, Kind, Buckets}}] ->
{ok, {Description, Kind, Buckets}};
[] ->
{error, metric_not_found};
_ ->
{error, table_error}
end,
fun(_use0) ->
{Description@1, Kind@1, Buckets@1} = _use0,
case Kind@1 =:= Given_kind of
false ->
{error, invalid_type};
true ->
{ok, {Description@1, Kind@1, Buckets@1}}
end
end
).
-file("/git/Themis/src/themis/internal/store.gleam", 97).
-spec match_metrics(binary()) -> {ok, list({binary(), binary(), list(float())})} |
{error, store_error()}.
match_metrics(Kind) ->
_assert_subject = themis@internal@erlang@ets:match_metric(
<<"themis_metrics"/utf8>>,
Kind
),
{ok, Metrics} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"should only return an error if the given table name string is not found as an atom. Are you sure you initialized the Themis store ?"/utf8>>,
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"match_metrics"/utf8>>,
line => 102})
end,
_pipe@2 = gleam@list:map(
Metrics,
fun(Found) ->
R = begin
_pipe = decode_metric(Found),
gleam@result:try_recover(
_pipe,
fun(E) -> {error, {decode_errors, E}} end
)
end,
gleam@result:'try'(
R,
fun(_use0) ->
{Name, Description, _, Buckets} = _use0,
_pipe@1 = {Name, Description, Buckets},
{ok, _pipe@1}
end
)
end
),
gleam@result:all(_pipe@2).
-file("/git/Themis/src/themis/internal/store.gleam", 40).
-spec init() -> gleam@erlang@atom:atom_().
init() ->
_ = themis@internal@erlang@ets:new(
{table_builder, set, public},
<<"themis_metrics"/utf8>>
),
_ = themis@internal@erlang@ets:new(
{table_builder, set, public},
<<"themis_records"/utf8>>
).
-file("/git/Themis/src/themis/internal/store.gleam", 48).
-spec clear() -> {ok, boolean()} |
{error, themis@internal@erlang@ets:table_error()}.
clear() ->
_ = themis@internal@erlang@ets:delete_table(<<"themis_metrics"/utf8>>),
_ = themis@internal@erlang@ets:delete_table(<<"themis_records"/utf8>>).
-file("/git/Themis/src/themis/internal/store.gleam", 117).
-spec increment_record_by(
themis@internal@metric:metric_name(),
themis@internal@label:label_set(),
themis@number:number_()
) -> {ok, nil} | {error, store_error()}.
increment_record_by(Name, Labels, Value) ->
case Value of
{dec, _} ->
_pipe = begin
Labels@1 = themis@internal@label:to_strings(Labels),
Name@1 = themis@internal@metric:name_to_string(Name),
_assert_subject = themis@internal@erlang@ets:counter_increment_by(
<<"themis_records"/utf8>>,
{Name@1, Labels@1},
Value
),
{ok, R} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"should only return an error if the given table name string is not found as an atom. Are you sure you initialized the Themis store ?"/utf8>>,
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"increment_record_by"/utf8>>,
line => 129})
end,
R
end,
{ok, _pipe};
{int, _} ->
_pipe = begin
Labels@1 = themis@internal@label:to_strings(Labels),
Name@1 = themis@internal@metric:name_to_string(Name),
_assert_subject = themis@internal@erlang@ets:counter_increment_by(
<<"themis_records"/utf8>>,
{Name@1, Labels@1},
Value
),
{ok, R} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"should only return an error if the given table name string is not found as an atom. Are you sure you initialized the Themis store ?"/utf8>>,
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"increment_record_by"/utf8>>,
line => 129})
end,
R
end,
{ok, _pipe};
na_n ->
{error, invalid_increment};
neg_inf ->
{error, invalid_increment};
pos_inf ->
{error, invalid_increment}
end.
-file("/git/Themis/src/themis/internal/store.gleam", 139).
-spec increment_record(
themis@internal@metric:metric_name(),
themis@internal@label:label_set()
) -> {ok, nil} | {error, store_error()}.
increment_record(Name, Labels) ->
increment_record_by(Name, Labels, themis@number:integer(1)).
-file("/git/Themis/src/themis/internal/store.gleam", 147).
-spec insert_record(
themis@internal@metric:metric_name(),
themis@internal@label:label_set(),
themis@number:number_()
) -> {ok, nil} | {error, store_error()}.
insert_record(Name, Labels, Value) ->
Labels@1 = themis@internal@label:to_strings(Labels),
{Int_value, Float_value, Flag_value} = case Value of
{dec, Val} ->
{0, Val, <<""/utf8>>};
{int, Val@1} ->
{Val@1, +0.0, <<""/utf8>>};
pos_inf ->
{0, +0.0, <<"+Inf"/utf8>>};
neg_inf ->
{0, +0.0, <<"-Inf"/utf8>>};
na_n ->
{0, +0.0, <<"NaN"/utf8>>}
end,
_assert_subject = themis@internal@erlang@ets:insert_raw(
<<"themis_records"/utf8>>,
{{begin
_pipe = Name,
themis@internal@metric:name_to_string(_pipe)
end,
Labels@1},
Int_value,
Float_value,
Flag_value}
),
{ok, R} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"should only return an error if the given table name string is not found as an atom. Are you sure you initialized the Themis store ?"/utf8>>,
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"insert_record"/utf8>>,
line => 162})
end,
case R of
false ->
{error, insert_error};
true ->
{ok, nil}
end.
-file("/git/Themis/src/themis/internal/store.gleam", 177).
-spec match_records(themis@internal@metric:metric_name()) -> {ok,
gleam@dict:dict(themis@internal@label:label_set(), themis@number:number_())} |
{error, store_error()}.
match_records(Name) ->
_assert_subject = themis@internal@erlang@ets:match_record(
<<"themis_records"/utf8>>,
begin
_pipe = Name,
themis@internal@metric:name_to_string(_pipe)
end
),
{ok, Records} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"should only return an error if the given table name string is not found as an atom. Are you sure you initialized the Themis store ?"/utf8>>,
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"match_records"/utf8>>,
line => 182})
end,
_pipe@1 = Records,
_pipe@2 = gleam@list:map(_pipe@1, fun parse_record/1),
_pipe@3 = gleam@result:all(_pipe@2),
gleam@result:map(_pipe@3, fun maps:from_list/1).
-file("/git/Themis/src/themis/internal/store.gleam", 192).
-spec find_record(
themis@internal@metric:metric_name(),
themis@internal@label:label_set()
) -> {ok, {themis@internal@label:label_set(), themis@number:number_()}} |
{error, store_error()}.
find_record(Name, Labels) ->
_assert_subject = themis@internal@erlang@ets:lookup(
<<"themis_records"/utf8>>,
{begin
_pipe = Name,
themis@internal@metric:name_to_string(_pipe)
end,
begin
_pipe@1 = Labels,
themis@internal@label:to_strings(_pipe@1)
end}
),
{ok, Entries} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"should only return an error if the given table name string is not found as an atom. Are you sure you initialized the Themis store ?"/utf8>>,
value => _assert_fail,
module => <<"themis/internal/store"/utf8>>,
function => <<"find_record"/utf8>>,
line => 199})
end,
_pipe@2 = case Entries of
[Entry] ->
{ok, Entry};
_ ->
{error, single_result_expected}
end,
gleam@result:'try'(_pipe@2, fun parse_record/1).