Current section
Files
Jump to
Current section
Files
src/themis@histogram.erl
-module(themis@histogram).-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).-export([new/3, observe/3, print/0]).-export_type([histogram_error/0]).-type histogram_error() :: {metric_error, themis@internal@metric:metric_error()} | {store_error, themis@internal@store:store_error()} | invalid_bucket_value | cannot_observe_na_n | {label_error, themis@internal@label:label_error()}.-file("/git/Themis/src/themis/histogram.gleam", 258).-spec group_histogram_records( gleam@dict:dict(themis@internal@label:label_set(), themis@number:number_()), gleam@dict:dict(themis@internal@label:label_set(), themis@number:number_()), gleam@dict:dict(themis@internal@label:label_set(), themis@number:number_())) -> gleam@dict:dict(themis@internal@label:label_set(), {gleam@dict:dict(binary(), themis@number:number_()), themis@number:number_(), themis@number:number_()}).group_histogram_records(Buckets, Sum, Count) -> _pipe = Buckets, maps:to_list(_pipe), gleam@list:fold( begin _pipe@1 = Buckets, maps:to_list(_pipe@1) end, maps:new(), fun(Result, Bucket_entry) -> {Bucket_labels, Bucket_value} = Bucket_entry, {Le_value, Bucket_labels@1} = begin _pipe@2 = themis@internal@label:to_dict(Bucket_labels), _pipe@3 = maps:to_list(_pipe@2), _pipe@4 = gleam@list:key_pop(_pipe@3, <<"le"/utf8>>), gleam@result:lazy_unwrap( _pipe@4, fun() -> erlang:error(#{gleam_error => panic, message => <<"could not find label `le` for bucket"/utf8>>, module => <<"themis/histogram"/utf8>>, function => <<"group_histogram_records"/utf8>>, line => 274}) end ) end, Labels = begin _pipe@5 = Bucket_labels@1, _pipe@6 = maps:from_list(_pipe@5), _pipe@7 = themis@internal@label:from_dict(_pipe@6), gleam@result:lazy_unwrap( _pipe@7, fun() -> erlang:error(#{gleam_error => panic, message => <<"failed to recombine bucket labels after extracting le label"/utf8>>, module => <<"themis/histogram"/utf8>>, function => <<"group_histogram_records"/utf8>>, line => 284}) end ) end, {Found_buckets, Found_sum, Found_count} = case gleam_stdlib:map_get( Result, Labels ) of {error, _} -> Record_sum_value = begin _pipe@8 = gleam_stdlib:map_get(Sum, Labels), gleam@result:lazy_unwrap( _pipe@8, fun() -> erlang:error(#{gleam_error => panic, message => <<"recombined bucket labels did not match any found sum record"/utf8>>, module => <<"themis/histogram"/utf8>>, function => <<"group_histogram_records"/utf8>>, line => 291}) end ) end, Record_count_value = begin _pipe@9 = gleam_stdlib:map_get(Count, Labels), gleam@result:lazy_unwrap( _pipe@9, fun() -> erlang:error(#{gleam_error => panic, message => <<"recombined bucket labels did not match any found count record"/utf8>>, module => <<"themis/histogram"/utf8>>, function => <<"group_histogram_records"/utf8>>, line => 296}) end ) end, {maps:new(), Record_sum_value, Record_count_value}; {ok, Record} -> Record end, New_buckets = gleam@dict:insert( Found_buckets, Le_value, Bucket_value ), gleam@dict:insert( Result, Labels, {New_buckets, Found_sum, Found_count} ) end ).-file("/git/Themis/src/themis/histogram.gleam", 306).-spec buckets_to_list_float(gleam@set:set(themis@number:number_())) -> {ok, list(float())} | {error, histogram_error()}.buckets_to_list_float(Buckets) -> _pipe@1 = begin gleam@list:map( begin _pipe = Buckets, gleam@set:to_list(_pipe) end, fun(Bucket) -> case Bucket of {dec, Val} -> {ok, Val}; {int, Val@1} -> {ok, erlang:float(Val@1)}; na_n -> {error, invalid_bucket_value}; pos_inf -> {error, invalid_bucket_value}; neg_inf -> {error, invalid_bucket_value} end end ) end, gleam@result:all(_pipe@1).-file("/git/Themis/src/themis/histogram.gleam", 320).-spec buckets_floats_to_numbers(list(float())) -> list(themis@number:number_()).buckets_floats_to_numbers(Buckets) -> _pipe@1 = gleam@list:map( Buckets, fun(Bucket) -> _assert_subject = gleam@float:modulo(Bucket, 1.0), {ok, Bucket_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/histogram"/utf8>>, function => <<"buckets_floats_to_numbers"/utf8>>, line => 322}) end, case Bucket_decimal =:= +0.0 of false -> themis@number:decimal(Bucket); true -> themis@number:integer( begin _pipe = Bucket, erlang:trunc(_pipe) end ) end end ), _pipe@2 = lists:append(_pipe@1, [themis@number:positive_infinity()]), _pipe@3 = gleam@list:sort(_pipe@2, fun themis@number:unsafe_compare/2), lists:reverse(_pipe@3).-file("/git/Themis/src/themis/histogram.gleam", 33).-spec new(binary(), binary(), gleam@set:set(themis@number:number_())) -> {ok, nil} | {error, histogram_error()}.new(Name, Description, Buckets) -> case themis@internal@metric:new_name(Name, [<<"histogram"/utf8>>]) of {error, E} -> {error, {metric_error, E}}; {ok, Metric_name} -> gleam@result:'try'( begin _pipe = Buckets, buckets_to_list_float(_pipe) end, fun(Buckets@1) -> case themis@internal@store:new_metric( Metric_name, Description, <<"histogram"/utf8>>, Buckets@1 ) of {error, E@1} -> {error, {store_error, E@1}}; {ok, _} -> {ok, nil} end end ) end.-file("/git/Themis/src/themis/histogram.gleam", 62).-spec observe( binary(), gleam@dict:dict(binary(), binary()), themis@number:number_()) -> {ok, nil} | {error, histogram_error()}.observe(Name, Labels, Value) -> gleam@bool:guard( Value =:= na_n, {error, cannot_observe_na_n}, fun() -> gleam@result:'try'( begin _pipe = themis@internal@metric:new_name( Name, [<<"histogram"/utf8>>] ), gleam@result:try_recover( _pipe, fun(E) -> {error, {metric_error, E}} end ) end, fun(Name@1) -> gleam@result:'try'( begin _pipe@1 = themis@internal@label:from_dict(Labels), gleam@result:map_error( _pipe@1, fun(E@1) -> {label_error, E@1} end ) end, fun(Labels@1) -> gleam@result:'try'( begin _pipe@2 = themis@internal@store:find_metric( Name@1, <<"histogram"/utf8>> ), gleam@result:map_error( _pipe@2, fun(E@2) -> {store_error, E@2} end ) end, fun(_use0) -> {_, _, Buckets} = _use0, Le_labels = buckets_floats_to_numbers( Buckets ), {Bucket_name, Count_name, Sum_name} = themis@internal@metric:make_histogram_metric_names( Name@1 ), _assert_subject = begin _pipe@3 = Labels@1, _pipe@4 = themis@internal@label:to_dict( _pipe@3 ), _pipe@5 = gleam@dict:insert( _pipe@4, <<"le"/utf8>>, <<"+Inf"/utf8>> ), themis@internal@label:from_dict(_pipe@5) end, {ok, Posinf_labels} = 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/histogram"/utf8>>, function => <<"observe"/utf8>>, line => 96} ) end, Must_initialize_records = begin _pipe@6 = themis@internal@store:find_record( Bucket_name, Posinf_labels ), gleam@result:is_error(_pipe@6) end, gleam@list:fold_until( Le_labels, nil, fun(_, Bucket) -> Value_belongs_to_bucket = themis@number:unsafe_compare( Value, Bucket ) /= gt, {Stop, By} = case {Value_belongs_to_bucket, Must_initialize_records} of {true, _} -> {false, themis@number:integer(1)}; {false, false} -> {true, themis@number:integer(1)}; {false, true} -> {false, themis@number:integer(0)} end, gleam@bool:guard( Stop, {stop, nil}, fun() -> Labels@3 = case begin _pipe@9 = gleam@dict:insert( begin _pipe@7 = Labels@1, themis@internal@label:to_dict( _pipe@7 ) end, <<"le"/utf8>>, begin _pipe@8 = Bucket, themis@number:print( _pipe@8 ) end ), themis@internal@label:from_dict( _pipe@9 ) end of {error, _} -> erlang:error( #{gleam_error => panic, message => <<"rebuilding labels after only adding the \"le\" label should work"/utf8>>, module => <<"themis/histogram"/utf8>>, function => <<"observe"/utf8>>, line => 120} ); {ok, Labels@2} -> Labels@2 end, case themis@internal@store:increment_record_by( Bucket_name, Labels@3, By ) of {error, E@3} -> erlang:error( #{gleam_error => panic, message => (<<<<<<"failed to increment a bucket record : \nName: "/utf8, (begin _pipe@10 = Bucket_name, themis@internal@metric:name_to_string( _pipe@10 ) end)/binary>>/binary, "\nError: "/utf8>>/binary, (gleam@string:inspect( E@3 ))/binary>>), module => <<"themis/histogram"/utf8>>, function => <<"observe"/utf8>>, line => 125} ); {ok, _} -> {continue, nil} end end ) end ), case themis@internal@store:increment_record( Count_name, Labels@1 ) of {error, E@4} -> erlang:error(#{gleam_error => panic, message => (<<<<<<"failed to increment a count record : \nName: "/utf8, (begin _pipe@11 = Count_name, themis@internal@metric:name_to_string( _pipe@11 ) end)/binary>>/binary, "\nError: "/utf8>>/binary, (gleam@string:inspect( E@4 ))/binary>>), module => <<"themis/histogram"/utf8>>, function => <<"observe"/utf8>>, line => 137}); {ok, _} -> nil end, case themis@internal@store:increment_record_by( Sum_name, Labels@1, Value ) of {error, E@5} -> erlang:error(#{gleam_error => panic, message => (<<<<<<"failed to increment a sum record : \nName: "/utf8, (begin _pipe@12 = Sum_name, themis@internal@metric:name_to_string( _pipe@12 ) end)/binary>>/binary, "\nError: "/utf8>>/binary, (gleam@string:inspect( E@5 ))/binary>>), module => <<"themis/histogram"/utf8>>, function => <<"observe"/utf8>>, line => 148}); {ok, _} -> nil end, {ok, nil} end ) end ) end ) end ).-file("/git/Themis/src/themis/histogram.gleam", 162).-spec print() -> {ok, binary()} | {error, histogram_error()}.print() -> gleam@result:'try'( begin _pipe = themis@internal@store:match_metrics(<<"histogram"/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, [<<"histogram"/utf8>>] ), gleam@result:try_recover( _pipe@1, fun(E@1) -> {error, {metric_error, E@1}} end ) end, fun(Name) -> {Buckets_name, Count_name, Sum_name} = themis@internal@metric:make_histogram_metric_names( Name ), gleam@result:'try'( begin _pipe@2 = themis@internal@store:match_records( Buckets_name ), gleam@result:try_recover( _pipe@2, fun(E@2) -> {error, {store_error, E@2}} end ) end, fun(Bucket_records) -> gleam@result:'try'( begin _pipe@3 = themis@internal@store:match_records( Sum_name ), gleam@result:try_recover( _pipe@3, fun(E@3) -> {error, {store_error, E@3}} end ) end, fun(Sum_records) -> gleam@result:'try'( begin _pipe@4 = themis@internal@store:match_records( Count_name ), gleam@result:try_recover( _pipe@4, fun(E@4) -> {error, {store_error, E@4}} end ) end, fun(Count_records) -> Records = group_histogram_records( Bucket_records, Sum_records, Count_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, "histogram\n"/utf8>>, Records_strings = begin gleam@list:fold( maps:to_list( Records ), [], fun( Lines, _use1@1 ) -> {Labels, {Buckets, Sum, Count}} = _use1@1, Sum_line = <<<<<<<<(begin _pipe@5 = Sum_name, themis@internal@metric:name_to_string( _pipe@5 ) end)/binary, (themis@internal@label:print( Labels ))/binary>>/binary, " "/utf8>>/binary, (themis@number:print( Sum ))/binary>>/binary, "\n"/utf8>>, Count_line = <<<<<<<<(begin _pipe@6 = Count_name, themis@internal@metric:name_to_string( _pipe@6 ) end)/binary, (themis@internal@label:print( Labels ))/binary>>/binary, " "/utf8>>/binary, (themis@number:print( Count ))/binary>>/binary, "\n"/utf8>>, Bucket_lines = begin gleam@list:map( maps:to_list( Buckets ), fun( _use0 ) -> {Bucket_label, Bucket_value} = _use0, Bucket_labels = begin _pipe@7 = themis@internal@label:add_label( Labels, <<"le"/utf8>>, Bucket_label ), gleam@result:lazy_unwrap( _pipe@7, fun( ) -> erlang:error( #{gleam_error => panic, message => (<<"bucket label should be `le` and should not throw an error"/utf8>>), module => <<"themis/histogram"/utf8>>, function => <<"print"/utf8>>, line => 221} ) end ) end, <<<<<<<<(begin _pipe@8 = Buckets_name, themis@internal@metric:name_to_string( _pipe@8 ) end)/binary, (themis@internal@label:print( Bucket_labels ))/binary>>/binary, " "/utf8>>/binary, (themis@number:print( Bucket_value ))/binary>>/binary, "\n"/utf8>> end ) end, _pipe@9 = [<<"\n"/utf8>>, Count_line, Sum_line | Bucket_lines], lists:append( _pipe@9, Lines ) end ) end, {ok, [<<"\n"/utf8>>, Type_string, Help_string | lists:append( Records_strings, Metrics_strings )]} end ) end ) end ) end ) end ) end, gleam@result:map( R, fun(Metrics_strings@1) -> _pipe@10 = Metrics_strings@1, _pipe@11 = gleam_stdlib:identity(_pipe@10), unicode:characters_to_binary(_pipe@11) end ) end ).