-module(themis@counter). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/themis/counter.gleam"). -export([print/0, new/2, increment_by/3, increment/2]). -export_type([counter_error/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. -type counter_error() :: {metric_error, themis@internal@metric:metric_error()} | {store_error, themis@internal@store:store_error()} | {invalid_increment, themis@number:number_()} | negative_increment | counter_name_should_end_with_total | {label_error, themis@internal@label:label_error()}. -file("src/themis/counter.gleam", 107). ?DOC( " Formats all counter metrics in the store \n" " as a Prometheus-compatible text string.\n" ). -spec print() -> {ok, binary()} | {error, counter_error()}. print() -> gleam@result:'try'( begin _pipe = themis@internal@store:match_metrics(<<"counter"/utf8>>), gleam@result:try_recover( _pipe, fun(E) -> {error, {store_error, E}} end ) end, fun(Metrics) -> R = begin gleam@list:try_fold( Metrics, [], fun(Metrics_strings, _use1) -> {Name_string, Description, _} = _use1, gleam@result:'try'( begin _pipe@1 = themis@internal@metric:new_name( Name_string, [] ), gleam@result:map_error( _pipe@1, fun(E@1) -> {metric_error, E@1} end ) end, fun(Name) -> gleam@result:'try'( begin _pipe@2 = themis@internal@store:match_records( Name ), gleam@result:map_error( _pipe@2, fun(E@2) -> {store_error, E@2} end ) end, fun(Counter_records) -> Help_string = <<<<<<<<"# HELP "/utf8, Name_string/binary>>/binary, " "/utf8>>/binary, Description/binary>>/binary, "\n"/utf8>>, Type_string = <<<<<<"# TYPE "/utf8, Name_string/binary>>/binary, " "/utf8>>/binary, "counter\n"/utf8>>, Records_strings = begin _pipe@3 = maps:to_list( Counter_records ), gleam@list:map( _pipe@3, fun(Record) -> {Labels, Value} = Record, <<<<<<<>/binary, " "/utf8>>/binary, (themis@number:print( Value ))/binary>>/binary, "\n"/utf8>> end ) end, {ok, [<<"\n"/utf8>>, Type_string, Help_string | lists:append( Records_strings, Metrics_strings )]} end ) end ) end ) end, gleam@result:map( R, fun(Metrics_strings@1) -> _pipe@4 = Metrics_strings@1, _pipe@5 = gleam_stdlib:identity(_pipe@4), unicode:characters_to_binary(_pipe@5) end ) end ). -file("src/themis/counter.gleam", 28). ?DOC( " Registers a new counter metric to the store.\n" " Counter metric names must end with `_total`.\n" " Will return an error if the metric name is invalid\n" " or already used by another metric.\n" ). -spec new(binary(), binary()) -> {ok, nil} | {error, counter_error()}. new(Name, Description) -> gleam@bool:guard( not gleam_stdlib:string_ends_with(Name, <<"total"/utf8>>), {error, counter_name_should_end_with_total}, fun() -> gleam@result:'try'( begin _pipe = themis@internal@metric:new_name( Name, [<<"counter"/utf8>>] ), gleam@result:try_recover( _pipe, fun(E) -> {error, {metric_error, E}} end ) end, fun(Name@1) -> Buckets = [], gleam@result:try_recover( themis@internal@store:new_metric( Name@1, Description, <<"counter"/utf8>>, Buckets ), fun(Store_error) -> {error, {store_error, Store_error}} end ) end ) end ). -file("src/themis/counter.gleam", 56). ?DOC( " Increments a counter metric for the given metric name.\n" " Will return an error if the name is invalid, not a registered metric\n" " or not of the correct metric type.\n" " Will return an error if any of the labels have an invalid key.\n" " Will return an error if the value is NaN, PosInf or NegInf.\n" ). -spec increment_by( binary(), gleam@dict:dict(binary(), binary()), themis@number:number_() ) -> {ok, nil} | {error, counter_error()}. increment_by(Name, Labels, Value) -> gleam@bool:guard( not gleam_stdlib:string_ends_with(Name, <<"total"/utf8>>), {error, counter_name_should_end_with_total}, fun() -> gleam@bool:guard( ((Value =:= na_n) orelse (Value =:= pos_inf)) orelse (Value =:= neg_inf), {error, {invalid_increment, Value}}, fun() -> gleam@bool:guard( themis@number:unsafe_compare( Value, themis@number:integer(0) ) =:= lt, {error, negative_increment}, fun() -> gleam@result:'try'( begin _pipe = themis@internal@metric:new_name( Name, [<<"counter"/utf8>>] ), gleam@result:map_error( _pipe, fun(E) -> {metric_error, E} end ) end, fun(Name@1) -> gleam@result:'try'( begin _pipe@1 = themis@internal@store:find_metric( Name@1, <<"counter"/utf8>> ), gleam@result:map_error( _pipe@1, fun(E@1) -> {store_error, E@1} end ) end, fun(_) -> gleam@result:'try'( begin _pipe@2 = themis@internal@label:from_dict( Labels ), gleam@result:map_error( _pipe@2, fun(E@2) -> {label_error, E@2} end ) end, fun(Labels@1) -> gleam@result:map_error( themis@internal@store:increment_record_by( Name@1, Labels@1, Value ), fun(Store_error) -> {store_error, Store_error} end ) end ) end ) end ) end ) end ) end ). -file("src/themis/counter.gleam", 97). ?DOC( " Increments a counter metric for the given metric name.\n" " Will return an error if the name is invalid, not a registered metric\n" " or not of the correct metric type.\n" " Will return an error if any of the labels have an invalid key.\n" ). -spec increment(binary(), gleam@dict:dict(binary(), binary())) -> {ok, nil} | {error, counter_error()}. increment(Name, Labels) -> increment_by(Name, Labels, themis@number:integer(1)).