Current section
Files
Jump to
Current section
Files
src/langfuse_client@metrics.erl
-module(langfuse_client@metrics).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/langfuse_client/metrics.gleam").
-export([score_count_query/3, decode/1, list_score_counts/2]).
-export_type([score_view/0, score_count_row/0, score_count_query/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(
" `GET /api/public/v2/metrics` — server-side aggregations over Langfuse\n"
" score data. Build a query with `score_count_query` and pass it to\n"
" `list_score_counts(client, query)`.\n"
"\n"
" The Langfuse v2 metrics endpoint is BETA. This module exposes only\n"
" score-count queries grouped by `(name, dataType, source)`; broader\n"
" surface (other measures, views, dimensions) will follow the same\n"
" shape once the endpoint stabilises.\n"
).
-type score_view() :: scores_numeric | scores_categorical.
-type score_count_row() :: {score_count_row,
binary(),
binary(),
binary(),
integer()}.
-type score_count_query() :: {score_count_query,
score_view(),
binary(),
binary()}.
-file("src/langfuse_client/metrics.gleam", 43).
?DOC(
" Build a query for counts of scores grouped by `(name, data_type,\n"
" source)` in the given window.\n"
).
-spec score_count_query(score_view(), binary(), binary()) -> score_count_query().
score_count_query(View, From_timestamp, To_timestamp) ->
{score_count_query, View, From_timestamp, To_timestamp}.
-file("src/langfuse_client/metrics.gleam", 70).
?DOC(
" Parse a `GET /api/public/v2/metrics` response body for a score-count\n"
" query. Useful if you already have the raw body in hand (e.g. from a\n"
" cached/recorded response).\n"
).
-spec decode(binary()) -> {ok, list(score_count_row())} |
{error, gleam@json:decode_error()}.
decode(Body) ->
gleam@json:parse(Body, rows_decoder()).
-file("src/langfuse_client/metrics.gleam", 116).
-spec row_decoder() -> gleam@dynamic@decode:decoder(score_count_row()).
row_decoder() ->
gleam@dynamic@decode:field(
<<"name"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Name) ->
gleam@dynamic@decode:field(
<<"dataType"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Data_type) ->
gleam@dynamic@decode:field(
<<"source"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Source) ->
gleam@dynamic@decode:field(
<<"sum_count"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Sum_count_str) ->
Count = gleam@result:unwrap(
gleam_stdlib:parse_int(Sum_count_str),
0
),
gleam@dynamic@decode:success(
{score_count_row,
Name,
Data_type,
Source,
Count}
)
end
)
end
)
end
)
end
).
-file("src/langfuse_client/metrics.gleam", 111).
-spec rows_decoder() -> gleam@dynamic@decode:decoder(list(score_count_row())).
rows_decoder() ->
gleam@dynamic@decode:field(
<<"data"/utf8>>,
gleam@dynamic@decode:list(row_decoder()),
fun(Rows) -> gleam@dynamic@decode:success(Rows) end
).
-file("src/langfuse_client/metrics.gleam", 95).
-spec score_count_metrics() -> list(gleam@json:json()).
score_count_metrics() ->
[gleam@json:object(
[{<<"measure"/utf8>>, gleam@json:string(<<"count"/utf8>>)},
{<<"aggregation"/utf8>>, gleam@json:string(<<"sum"/utf8>>)}]
)].
-file("src/langfuse_client/metrics.gleam", 87).
-spec score_count_dimensions() -> list(gleam@json:json()).
score_count_dimensions() ->
[gleam@json:object([{<<"field"/utf8>>, gleam@json:string(<<"name"/utf8>>)}]),
gleam@json:object(
[{<<"field"/utf8>>, gleam@json:string(<<"dataType"/utf8>>)}]
),
gleam@json:object(
[{<<"field"/utf8>>, gleam@json:string(<<"source"/utf8>>)}]
)].
-file("src/langfuse_client/metrics.gleam", 104).
-spec view_string(score_view()) -> binary().
view_string(V) ->
case V of
scores_numeric ->
<<"scores-numeric"/utf8>>;
scores_categorical ->
<<"scores-categorical"/utf8>>
end.
-file("src/langfuse_client/metrics.gleam", 76).
-spec query_body(score_count_query()) -> binary().
query_body(Q) ->
_pipe = gleam@json:object(
[{<<"view"/utf8>>, gleam@json:string(view_string(erlang:element(2, Q)))},
{<<"fromTimestamp"/utf8>>, gleam@json:string(erlang:element(3, Q))},
{<<"toTimestamp"/utf8>>, gleam@json:string(erlang:element(4, Q))},
{<<"dimensions"/utf8>>,
gleam@json:preprocessed_array(score_count_dimensions())},
{<<"metrics"/utf8>>,
gleam@json:preprocessed_array(score_count_metrics())}]
),
gleam@json:to_string(_pipe).
-file("src/langfuse_client/metrics.gleam", 55).
?DOC(
" Aggregate score counts for the query. Returns one row per distinct\n"
" `(name, data_type, source)` combination present in the window.\n"
" Erlang-only — see `langfuse_client/client` module docs.\n"
).
-spec list_score_counts(langfuse_client@client:client(), score_count_query()) -> {ok,
list(score_count_row())} |
{error, langfuse_client@client:error()}.
list_score_counts(C, Q) ->
langfuse_client@client:send_get(
C,
<<"/api/public/v2/metrics"/utf8>>,
[{<<"query"/utf8>>, query_body(Q)}],
rows_decoder()
).