-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 gleam@string:to_utf_codepoints(Char) of [Cp] -> Code = gleam_stdlib:identity(Cp), (Code >= 97) andalso (Code =< 122); _ -> 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", 264). -spec is_digit(binary()) -> boolean(). is_digit(Char) -> case gleam@string:to_utf_codepoints(Char) of [Cp] -> Code = gleam_stdlib:identity(Cp), (Code >= 48) andalso (Code =< 57); _ -> false end. -file("src/caffeine_lang/codegen/honeycomb.gleam", 257). -spec is_valid_tag_value_char(binary()) -> boolean(). is_valid_tag_value_char(Char) -> case Char of <<"-"/utf8>> -> true; <<"/"/utf8>> -> true; _ -> is_lowercase_letter(Char) orelse is_digit(Char) 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", 277). ?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, <<<>/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", 305). ?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 = <>, 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 ).