Current section

Files

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

src/caffeine_lang@codegen@honeycomb.erl

-module(caffeine_lang@codegen@honeycomb).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/codegen/honeycomb.gleam").
-export([terraform_settings/0, provider/0, variables/0, sanitize_honeycomb_tag_key/1, sanitize_honeycomb_tag_value/1, window_to_time_period/1, ir_to_terraform_resources/1, generate_resources/1, generate_terraform/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/caffeine_lang/codegen/honeycomb.gleam", 41).
?DOC(false).
-spec terraform_settings() -> terra_madre@terraform:terraform_settings().
terraform_settings() ->
caffeine_lang@codegen@generator_utils:build_terraform_settings(
<<"honeycombio"/utf8>>,
<<"honeycombio/honeycombio"/utf8>>,
<<"~> 0.31"/utf8>>
).
-file("src/caffeine_lang/codegen/honeycomb.gleam", 51).
?DOC(false).
-spec provider() -> terra_madre@terraform:provider().
provider() ->
caffeine_lang@codegen@generator_utils:build_provider(
<<"honeycombio"/utf8>>,
[{<<"api_key"/utf8>>,
terra_madre@hcl:ref(<<"var.honeycomb_api_key"/utf8>>)}]
).
-file("src/caffeine_lang/codegen/honeycomb.gleam", 60).
?DOC(false).
-spec variables() -> list(terra_madre@terraform:variable()).
variables() ->
[{variable,
<<"honeycomb_api_key"/utf8>>,
{some, {identifier, <<"string"/utf8>>}},
none,
{some, <<"Honeycomb API key"/utf8>>},
{some, true},
none,
[]},
{variable,
<<"honeycomb_dataset"/utf8>>,
{some, {identifier, <<"string"/utf8>>}},
none,
{some, <<"Honeycomb dataset slug"/utf8>>},
none,
none,
[]}].
-file("src/caffeine_lang/codegen/honeycomb.gleam", 247).
-spec is_lowercase_letter(binary()) -> boolean().
is_lowercase_letter(Char) ->
case Char of
<<"a"/utf8>> ->
true;
<<"b"/utf8>> ->
true;
<<"c"/utf8>> ->
true;
<<"d"/utf8>> ->
true;
<<"e"/utf8>> ->
true;
<<"f"/utf8>> ->
true;
<<"g"/utf8>> ->
true;
<<"h"/utf8>> ->
true;
<<"i"/utf8>> ->
true;
<<"j"/utf8>> ->
true;
<<"k"/utf8>> ->
true;
<<"l"/utf8>> ->
true;
<<"m"/utf8>> ->
true;
<<"n"/utf8>> ->
true;
<<"o"/utf8>> ->
true;
<<"p"/utf8>> ->
true;
<<"q"/utf8>> ->
true;
<<"r"/utf8>> ->
true;
<<"s"/utf8>> ->
true;
<<"t"/utf8>> ->
true;
<<"u"/utf8>> ->
true;
<<"v"/utf8>> ->
true;
<<"w"/utf8>> ->
true;
<<"x"/utf8>> ->
true;
<<"y"/utf8>> ->
true;
<<"z"/utf8>> ->
true;
_ ->
false
end.
-file("src/caffeine_lang/codegen/honeycomb.gleam", 203).
?DOC(false).
-spec sanitize_honeycomb_tag_key(binary()) -> binary().
sanitize_honeycomb_tag_key(Key) ->
_pipe = Key,
_pipe@1 = string:lowercase(_pipe),
_pipe@2 = gleam@string:to_graphemes(_pipe@1),
_pipe@3 = gleam@list:filter(_pipe@2, fun is_lowercase_letter/1),
_pipe@4 = erlang:list_to_binary(_pipe@3),
gleam@string:slice(_pipe@4, 0, 32).
-file("src/caffeine_lang/codegen/honeycomb.gleam", 290).
-spec is_digit(binary()) -> boolean().
is_digit(Char) ->
case Char of
<<"0"/utf8>> ->
true;
<<"1"/utf8>> ->
true;
<<"2"/utf8>> ->
true;
<<"3"/utf8>> ->
true;
<<"4"/utf8>> ->
true;
<<"5"/utf8>> ->
true;
<<"6"/utf8>> ->
true;
<<"7"/utf8>> ->
true;
<<"8"/utf8>> ->
true;
<<"9"/utf8>> ->
true;
_ ->
false
end.
-file("src/caffeine_lang/codegen/honeycomb.gleam", 279).
-spec is_valid_tag_value_char(binary()) -> boolean().
is_valid_tag_value_char(Char) ->
case Char of
<<"-"/utf8>> ->
true;
<<"/"/utf8>> ->
true;
_ ->
case is_lowercase_letter(Char) of
true ->
true;
false ->
is_digit(Char)
end
end.
-file("src/caffeine_lang/codegen/honeycomb.gleam", 216).
?DOC(false).
-spec sanitize_honeycomb_tag_value(binary()) -> binary().
sanitize_honeycomb_tag_value(Value) ->
Sanitized = begin
_pipe = Value,
_pipe@1 = string:lowercase(_pipe),
_pipe@2 = gleam@string:to_graphemes(_pipe@1),
_pipe@3 = gleam@list:map(_pipe@2, fun(Char) -> case Char of
<<" "/utf8>> ->
<<"-"/utf8>>;
<<"_"/utf8>> ->
<<"-"/utf8>>;
<<","/utf8>> ->
<<"-"/utf8>>;
_ ->
case is_valid_tag_value_char(Char) of
true ->
Char;
false ->
<<""/utf8>>
end
end end),
erlang:list_to_binary(_pipe@3)
end,
Sanitized@1 = case gleam@string:first(Sanitized) of
{ok, C} ->
case is_lowercase_letter(C) of
true ->
Sanitized;
false ->
<<"v"/utf8, Sanitized/binary>>
end;
_ ->
Sanitized
end,
_pipe@4 = Sanitized@1,
gleam@string:slice(_pipe@4, 0, 129).
-file("src/caffeine_lang/codegen/honeycomb.gleam", 300).
?DOC(
" Collapse tag pairs that share the same key by joining values with forward slashes.\n"
" The shared helper produces one pair per misc value, but Honeycomb needs a\n"
" single key-value entry per tag key. Preserves insertion order of first occurrence.\n"
).
-spec collapse_multi_value_tags(list({binary(), binary()})) -> list({binary(),
binary()}).
collapse_multi_value_tags(Pairs) ->
{Order, Merged} = begin
_pipe = Pairs,
gleam@list:fold(
_pipe,
{[], maps:new()},
fun(Acc, Pair) ->
{Keys, Seen} = Acc,
{Key, Value} = Pair,
case gleam_stdlib:map_get(Seen, Key) of
{ok, Existing} ->
{Keys,
gleam@dict:insert(
Seen,
Key,
<<<<Existing/binary, "/"/utf8>>/binary,
Value/binary>>
)};
{error, _} ->
{[Key | Keys], gleam@dict:insert(Seen, Key, Value)}
end
end
)
end,
_pipe@1 = Order,
_pipe@2 = lists:reverse(_pipe@1),
gleam@list:filter_map(
_pipe@2,
fun(Key@1) -> _pipe@3 = gleam_stdlib:map_get(Merged, Key@1),
gleam@result:map(_pipe@3, fun(Value@1) -> {Key@1, Value@1} end) end
).
-file("src/caffeine_lang/codegen/honeycomb.gleam", 328).
?DOC(false).
-spec window_to_time_period(integer()) -> integer().
window_to_time_period(Days) ->
Days.
-file("src/caffeine_lang/codegen/honeycomb.gleam", 164).
?DOC(
" Build tags as a map expression for Honeycomb.\n"
" Honeycomb tags: keys ^[a-z]{1,32}$, values ^[a-z][a-z0-9/-]{1,128}$.\n"
" Max 10 tags per resource.\n"
).
-spec build_tags(
caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved())
) -> terra_madre@hcl:expr().
build_tags(Ir) ->
System_tag_pairs = begin
_pipe = caffeine_lang@helpers:build_system_tag_pairs(
erlang:element(3, erlang:element(2, Ir)),
erlang:element(6, erlang:element(2, Ir)),
erlang:element(4, erlang:element(2, Ir)),
erlang:element(5, erlang:element(2, Ir)),
erlang:element(2, erlang:element(2, Ir)),
[],
erlang:element(7, erlang:element(2, Ir))
),
collapse_multi_value_tags(_pipe)
end,
User_tag_pairs = case caffeine_lang@linker@ir:get_slo_fields(
erlang:element(6, Ir)
) of
{some, Slo} ->
erlang:element(6, Slo);
none ->
[]
end,
All_tags = begin
_pipe@1 = lists:append(System_tag_pairs, User_tag_pairs),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Pair) ->
{{ident_key,
sanitize_honeycomb_tag_key(erlang:element(1, Pair))},
{string_literal,
sanitize_honeycomb_tag_value(erlang:element(2, Pair))}}
end
),
gleam@list:take(_pipe@2, 10)
end,
{map_expr, All_tags}.
-file("src/caffeine_lang/codegen/honeycomb.gleam", 86).
?DOC(false).
-spec ir_to_terraform_resources(
caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved())
) -> {ok, list(terra_madre@terraform:resource())} |
{error, caffeine_lang@errors:compilation_error()}.
ir_to_terraform_resources(Ir) ->
Resource_name = terra_madre@common:sanitize_terraform_identifier(
erlang:element(3, Ir)
),
gleam@result:'try'(
caffeine_lang@codegen@generator_utils:require_slo_fields(
Ir,
<<"honeycomb"/utf8>>
),
fun(Slo) ->
Threshold = erlang:element(2, Slo),
Window_in_days = erlang:element(4, Slo),
Indicators = erlang:element(3, Slo),
gleam@result:'try'(
caffeine_lang@codegen@generator_utils:require_evaluation(
Slo,
Ir,
<<"honeycomb"/utf8>>
),
fun(Evaluation_expr) ->
gleam@result:'try'(
caffeine_lang@codegen@generator_utils:resolve_cql_expression(
Evaluation_expr,
Indicators,
Ir,
<<"honeycomb"/utf8>>
),
fun(Sli_expression) ->
Time_period = window_to_time_period(Window_in_days),
Derived_column_alias = <<Resource_name/binary,
"_sli"/utf8>>,
Derived_column = {resource,
<<"honeycombio_derived_column"/utf8>>,
Derived_column_alias,
maps:from_list(
[{<<"alias"/utf8>>,
{string_literal,
Derived_column_alias}},
{<<"expression"/utf8>>,
{string_literal, Sli_expression}},
{<<"dataset"/utf8>>,
terra_madre@hcl:ref(
<<"var.honeycomb_dataset"/utf8>>
)}]
),
[],
terra_madre@hcl:empty_meta(),
none},
Slo_description = caffeine_lang@codegen@generator_utils:build_description(
Ir,
Slo
),
Slo_attributes = [{<<"name"/utf8>>,
{string_literal,
erlang:element(
2,
erlang:element(
2,
erlang:element(2, Ir)
)
)}},
{<<"description"/utf8>>,
{string_literal, Slo_description}},
{<<"dataset"/utf8>>,
terra_madre@hcl:ref(
<<"var.honeycomb_dataset"/utf8>>
)},
{<<"sli"/utf8>>,
terra_madre@hcl:ref(
<<<<"honeycombio_derived_column."/utf8,
Derived_column_alias/binary>>/binary,
".alias"/utf8>>
)},
{<<"target_percentage"/utf8>>,
{float_literal, Threshold}},
{<<"time_period"/utf8>>,
{int_literal, Time_period}},
{<<"tags"/utf8>>, build_tags(Ir)}],
Slo@1 = {resource,
<<"honeycombio_slo"/utf8>>,
Resource_name,
maps:from_list(Slo_attributes),
[],
terra_madre@hcl:empty_meta(),
none},
{ok, [Derived_column, Slo@1]}
end
)
end
)
end
).
-file("src/caffeine_lang/codegen/honeycomb.gleam", 30).
?DOC(false).
-spec generate_resources(
list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved()))
) -> {ok, {list(terra_madre@terraform:resource()), list(binary())}} |
{error, caffeine_lang@errors:compilation_error()}.
generate_resources(Irs) ->
caffeine_lang@codegen@generator_utils:generate_resources_multi(
Irs,
fun ir_to_terraform_resources/1
).
-file("src/caffeine_lang/codegen/honeycomb.gleam", 16).
?DOC(" Generate Terraform HCL from a list of Honeycomb IntermediateRepresentations.\n").
-spec generate_terraform(
list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved()))
) -> {ok, binary()} | {error, caffeine_lang@errors:compilation_error()}.
generate_terraform(Irs) ->
caffeine_lang@codegen@generator_utils:generate_terraform(
Irs,
terraform_settings(),
provider(),
variables(),
fun generate_resources/1
).