Current section

Files

Jump to
caffeine_lang src caffeine_lang@codegen@relay.erl
Raw

src/caffeine_lang@codegen@relay.erl

-module(caffeine_lang@codegen@relay).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/codegen/relay.gleam").
-export([generate_langfuse_to_datadog/1]).
-export_type([relay_file/0, scorer_data_type/0, scorer/0, langfuse_datadog_relay/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(
" Codegen for the Relay artifact.\n"
"\n"
" A relay is a GitHub Action that pulls metrics from a source vendor and\n"
" pushes them to a destination vendor. The compiler emits a self-contained\n"
" set of files that a target repository drops in to start relaying.\n"
"\n"
" Today the only supported pairing is Langfuse → Datadog, producing four\n"
" files:\n"
" - `.github/workflows/<name>.yml` — workflow that runs the runner on a\n"
" schedule, manages a cursor in a repo Variable, and dispatches manually.\n"
" - `relay/gleam.toml` — runner project manifest.\n"
" - `relay/src/relay.gleam` — runner that queries Langfuse v2 metrics\n"
" for `[from, to)` and submits one Datadog metric per scorer.\n"
" - `relay/src/manifest.gleam` — static declaration of which metrics the\n"
" relay emits. The runner imports it for its scorer allowlist; later\n"
" language tooling will import it to type-check measurement references.\n"
"\n"
" File contents come from templates under `priv/templates/relay/<pairing>/`.\n"
" Each template is a real `.yml` / `.toml` / `.gleam` file with\n"
" `{{PLACEHOLDER}}` tokens — so editors and reviewers get the right syntax\n"
" highlighting and the diffs read naturally.\n"
).
-type relay_file() :: {relay_file, binary(), binary()}.
-type scorer_data_type() :: numeric | boolean | categorical.
-type scorer() :: {scorer, binary(), scorer_data_type()}.
-type langfuse_datadog_relay() :: {langfuse_datadog_relay,
binary(),
binary(),
binary(),
list(scorer())}.
-file("src/caffeine_lang/codegen/relay.gleam", 146).
-spec data_type_string(scorer_data_type()) -> binary().
data_type_string(Dt) ->
case Dt of
numeric ->
<<"numeric"/utf8>>;
boolean ->
<<"boolean"/utf8>>;
categorical ->
<<"categorical"/utf8>>
end.
-file("src/caffeine_lang/codegen/relay.gleam", 131).
-spec render_scorer_entry(scorer(), binary()) -> binary().
render_scorer_entry(Scorer, Metric_prefix) ->
Data_type_str = data_type_string(erlang:element(3, Scorer)),
Value_metric = case erlang:element(3, Scorer) of
categorical ->
<<"option.None"/utf8>>;
numeric ->
<<<<"option.Some(\""/utf8, Metric_prefix/binary>>/binary,
".value\")"/utf8>>;
boolean ->
<<<<"option.Some(\""/utf8, Metric_prefix/binary>>/binary,
".value\")"/utf8>>
end,
<<<<<<<<<<<<<<<<<<<<<<<<<<" ScorerInfo(\n"/utf8, " name: \""/utf8>>/binary,
(erlang:element(2, Scorer))/binary>>/binary,
"\",\n"/utf8>>/binary,
" data_type: \""/utf8>>/binary,
Data_type_str/binary>>/binary,
"\",\n"/utf8>>/binary,
" count_metric: \""/utf8>>/binary,
Metric_prefix/binary>>/binary,
".count\",\n"/utf8>>/binary,
" value_metric: "/utf8>>/binary,
Value_metric/binary>>/binary,
",\n"/utf8>>/binary,
" ),\n"/utf8>>.
-file("src/caffeine_lang/codegen/relay.gleam", 125).
-spec scorer_entries(langfuse_datadog_relay()) -> binary().
scorer_entries(Relay) ->
_pipe = erlang:element(5, Relay),
_pipe@1 = gleam@list:map(
_pipe,
fun(_capture) ->
render_scorer_entry(_capture, erlang:element(3, Relay))
end
),
erlang:list_to_binary(_pipe@1).
-file("src/caffeine_lang/codegen/relay.gleam", 119).
-spec cursor_var_name(langfuse_datadog_relay()) -> binary().
cursor_var_name(Relay) ->
<<"RELAY_CURSOR_"/utf8,
(string:uppercase(erlang:element(2, Relay)))/binary>>.
-file("src/caffeine_lang/codegen/relay.gleam", 109).
-spec substitutions(langfuse_datadog_relay()) -> list({binary(), binary()}).
substitutions(Relay) ->
[{<<"{{RELAY_NAME}}"/utf8>>, erlang:element(2, Relay)},
{<<"{{METRIC_PREFIX}}"/utf8>>, erlang:element(3, Relay)},
{<<"{{SCHEDULE_CRON}}"/utf8>>, erlang:element(4, Relay)},
{<<"{{CURSOR_VAR}}"/utf8>>, cursor_var_name(Relay)},
{<<"{{SCORER_ENTRIES}}"/utf8>>, scorer_entries(Relay)}].
-file("src/caffeine_lang/codegen/relay.gleam", 101).
?DOC(
" Read a template from `priv/templates/relay/langfuse_to_datadog/` and\n"
" substitute the relay's fields into the `{{PLACEHOLDER}}` tokens. A\n"
" missing template file means the package was shipped broken — assert so\n"
" it fails loudly.\n"
).
-spec render(langfuse_datadog_relay(), binary()) -> binary().
render(Relay, Template_name) ->
Template@1 = case simplifile:read(
<<"priv/templates/relay/langfuse_to_datadog/"/utf8,
Template_name/binary>>
) of
{ok, Template} -> Template;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"caffeine_lang/codegen/relay"/utf8>>,
function => <<"render"/utf8>>,
line => 102,
value => _assert_fail,
start => 4166,
'end' => 4238,
pattern_start => 4177,
pattern_end => 4189})
end,
gleam@list:fold(
substitutions(Relay),
Template@1,
fun(Acc, Sub) ->
{Placeholder, Value} = Sub,
gleam@string:replace(Acc, Placeholder, Value)
end
).
-file("src/caffeine_lang/codegen/relay.gleam", 75).
?DOC(" Generate the file set for a Langfuse → Datadog relay.\n").
-spec generate_langfuse_to_datadog(langfuse_datadog_relay()) -> list(relay_file()).
generate_langfuse_to_datadog(Relay) ->
[{relay_file,
<<<<".github/workflows/"/utf8, (erlang:element(2, Relay))/binary>>/binary,
".yml"/utf8>>,
render(Relay, <<"workflow.yml"/utf8>>)},
{relay_file,
<<"relay/gleam.toml"/utf8>>,
render(Relay, <<"gleam.toml"/utf8>>)},
{relay_file,
<<"relay/src/relay.gleam"/utf8>>,
render(Relay, <<"runner.gleam"/utf8>>)},
{relay_file,
<<"relay/src/manifest.gleam"/utf8>>,
render(Relay, <<"manifest.gleam"/utf8>>)}].