-module(caffeine_lang@codegen@newrelic). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/caffeine_lang/codegen/newrelic.gleam"). -export([terraform_settings/0, provider/0, variables/0, parse_nrql_indicator/1, window_to_rolling_count/1, ir_to_terraform_resource/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/newrelic.gleam", 41). ?DOC(false). -spec terraform_settings() -> terra_madre@terraform:terraform_settings(). terraform_settings() -> {terraform_settings, none, maps:from_list( [{<<"newrelic"/utf8>>, {provider_requirement, <<"newrelic/newrelic"/utf8>>, {some, <<"~> 3.0"/utf8>>}}}] ), none, none}. -file("src/caffeine_lang/codegen/newrelic.gleam", 60). ?DOC(false). -spec provider() -> terra_madre@terraform:provider(). provider() -> {provider, <<"newrelic"/utf8>>, none, maps:from_list( [{<<"account_id"/utf8>>, terra_madre@hcl:ref(<<"var.newrelic_account_id"/utf8>>)}, {<<"api_key"/utf8>>, terra_madre@hcl:ref(<<"var.newrelic_api_key"/utf8>>)}, {<<"region"/utf8>>, terra_madre@hcl:ref(<<"var.newrelic_region"/utf8>>)}] ), []}. -file("src/caffeine_lang/codegen/newrelic.gleam", 75). ?DOC(false). -spec variables() -> list(terra_madre@terraform:variable()). variables() -> [{variable, <<"newrelic_account_id"/utf8>>, {some, {identifier, <<"number"/utf8>>}}, none, {some, <<"New Relic account ID"/utf8>>}, none, none, []}, {variable, <<"newrelic_api_key"/utf8>>, {some, {identifier, <<"string"/utf8>>}}, none, {some, <<"New Relic API key"/utf8>>}, {some, true}, none, []}, {variable, <<"newrelic_region"/utf8>>, {some, {identifier, <<"string"/utf8>>}}, {some, {string_literal, <<"US"/utf8>>}}, {some, <<"New Relic region"/utf8>>}, none, none, []}, {variable, <<"newrelic_entity_guid"/utf8>>, {some, {identifier, <<"string"/utf8>>}}, none, {some, <<"New Relic entity GUID"/utf8>>}, none, none, []}]. -file("src/caffeine_lang/codegen/newrelic.gleam", 274). ?DOC( " Extract good and valid indicator names from the evaluation expression.\n" " Expects a \"numerator / denominator\" pattern where numerator = good, denominator = valid.\n" ). -spec extract_good_valid_names(binary(), list(binary()), binary()) -> {ok, {binary(), binary()}} | {error, caffeine_lang@errors:compilation_error()}. extract_good_valid_names(Evaluation_expr, Indicator_names, Identifier) -> case gleam@string:split(Evaluation_expr, <<" / "/utf8>>) of [Good, Valid] -> Good_trimmed = gleam@string:trim(Good), Valid_trimmed = gleam@string:trim(Valid), case gleam@list:contains(Indicator_names, Good_trimmed) andalso gleam@list:contains( Indicator_names, Valid_trimmed ) of true -> {ok, {Good_trimmed, Valid_trimmed}}; false -> {error, {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<"expectation '"/utf8, Identifier/binary>>/binary, "' - evaluation references indicators not found in indicator map"/utf8>>, caffeine_lang@errors:empty_context()}} end; _ -> {error, {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<"expectation '"/utf8, Identifier/binary>>/binary, "' - evaluation must be in 'good / valid' format for New Relic"/utf8>>, caffeine_lang@errors:empty_context()}} end. -file("src/caffeine_lang/codegen/newrelic.gleam", 312). ?DOC(false). -spec parse_nrql_indicator(binary()) -> {binary(), gleam@option:option(binary())}. parse_nrql_indicator(Indicator) -> case gleam@string:split(Indicator, <<" WHERE "/utf8>>) of [From] -> {From, none}; [From@1 | Rest] -> {From@1, {some, gleam@string:join(Rest, <<" WHERE "/utf8>>)}}; _ -> {Indicator, none} end. -file("src/caffeine_lang/codegen/newrelic.gleam", 323). ?DOC(" Build an NRQL event sub-block (good_events or valid_events).\n"). -spec build_nrql_event_block(binary(), binary(), gleam@option:option(binary())) -> terra_madre@hcl:block(). build_nrql_event_block(Block_type, From, Where_clause) -> Attrs = case Where_clause of {some, Where} -> [{<<"from"/utf8>>, {string_literal, From}}, {<<"where"/utf8>>, {string_literal, Where}}]; none -> [{<<"from"/utf8>>, {string_literal, From}}] end, {block, Block_type, [], maps:from_list(Attrs), []}. -file("src/caffeine_lang/codegen/newrelic.gleam", 213). ?DOC( " Build the events block from indicators and evaluation expression.\n" " Determines which indicators map to valid_events and good_events based\n" " on the evaluation expression structure (numerator = good, denominator = valid).\n" ). -spec build_events_block( gleam@dict:dict(binary(), binary()), binary(), binary() ) -> {ok, terra_madre@hcl:block()} | {error, caffeine_lang@errors:compilation_error()}. build_events_block(Indicators, Evaluation_expr, Identifier) -> Indicator_names = maps:keys(Indicators), gleam@result:'try'( extract_good_valid_names(Evaluation_expr, Indicator_names, Identifier), fun(_use0) -> {Good_name, Valid_name} = _use0, gleam@result:'try'( begin _pipe = gleam_stdlib:map_get(Indicators, Good_name), gleam@result:replace_error( _pipe, {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<<<<<"expectation '"/utf8, Identifier/binary>>/binary, "' - indicator '"/utf8>>/binary, Good_name/binary>>/binary, "' not found"/utf8>>, caffeine_lang@errors:empty_context()} ) end, fun(Good_indicator) -> gleam@result:'try'( begin _pipe@1 = gleam_stdlib:map_get( Indicators, Valid_name ), gleam@result:replace_error( _pipe@1, {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<<<<<"expectation '"/utf8, Identifier/binary>>/binary, "' - indicator '"/utf8>>/binary, Valid_name/binary>>/binary, "' not found"/utf8>>, caffeine_lang@errors:empty_context()} ) end, fun(Valid_indicator) -> {Good_from, Good_where} = parse_nrql_indicator( Good_indicator ), {Valid_from, Valid_where} = parse_nrql_indicator( Valid_indicator ), Good_events_block = build_nrql_event_block( <<"good_events"/utf8>>, Good_from, Good_where ), Valid_events_block = build_nrql_event_block( <<"valid_events"/utf8>>, Valid_from, Valid_where ), {ok, {block, <<"events"/utf8>>, [], maps:from_list( [{<<"account_id"/utf8>>, terra_madre@hcl:ref( <<"var.newrelic_account_id"/utf8>> )}] ), [Valid_events_block, Good_events_block]}} end ) end ) end ). -file("src/caffeine_lang/codegen/newrelic.gleam", 346). ?DOC(false). -spec window_to_rolling_count(integer()) -> {ok, integer()} | {error, caffeine_lang@errors:compilation_error()}. window_to_rolling_count(Days) -> case Days of 1 -> {ok, Days}; 7 -> {ok, Days}; 28 -> {ok, Days}; _ -> {error, {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<"Illegal window_in_days value: "/utf8, (erlang:integer_to_binary(Days))/binary>>/binary, ". New Relic accepts only 1, 7, or 28."/utf8>>, caffeine_lang@errors:empty_context()}} end. -file("src/caffeine_lang/codegen/newrelic.gleam", 361). ?DOC(" Build a description string for the SLO.\n"). -spec build_description(caffeine_lang@linker@ir:intermediate_representation()) -> binary(). build_description(Ir) -> Runbook = case caffeine_lang@linker@ir:get_slo_fields(erlang:element(6, Ir)) of {some, Slo} -> erlang:element(7, Slo); none -> none end, case Runbook of {some, Url} -> <<<<"[Runbook]("/utf8, Url/binary>>/binary, ")"/utf8>>; none -> <<<<<<<<<<<<"Managed by Caffeine ("/utf8, (erlang:element(3, erlang:element(2, Ir)))/binary>>/binary, "/"/utf8>>/binary, (erlang:element(6, erlang:element(2, Ir)))/binary>>/binary, "/"/utf8>>/binary, (erlang:element(4, erlang:element(2, Ir)))/binary>>/binary, ")"/utf8>> end. -file("src/caffeine_lang/codegen/newrelic.gleam", 119). ?DOC(false). -spec ir_to_terraform_resource( caffeine_lang@linker@ir:intermediate_representation() ) -> {ok, terra_madre@terraform:resource()} | {error, caffeine_lang@errors:compilation_error()}. ir_to_terraform_resource(Ir) -> Identifier = caffeine_lang@linker@ir:ir_to_identifier(Ir), Resource_name = terra_madre@common:sanitize_terraform_identifier( erlang:element(3, Ir) ), gleam@result:'try'( begin _pipe = caffeine_lang@linker@ir:get_slo_fields( erlang:element(6, Ir) ), gleam@option:to_result( _pipe, {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<"expectation '"/utf8, Identifier/binary>>/binary, "' - missing SLO artifact data"/utf8>>, caffeine_lang@errors:empty_context()} ) end, fun(Slo) -> gleam@result:'try'( begin _pipe@1 = erlang:element(5, Slo), gleam@option:to_result( _pipe@1, {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<"expectation '"/utf8, Identifier/binary>>/binary, "' - missing evaluation for New Relic SLO"/utf8>>, caffeine_lang@errors:empty_context()} ) end, fun(Evaluation_expr) -> gleam@result:'try'( begin _pipe@2 = caffeine_query_language@generator:resolve_slo_to_expression( Evaluation_expr, erlang:element(3, Slo) ), gleam@result:map_error( _pipe@2, fun(Err) -> {generator_terraform_resolution_error, <<"newrelic"/utf8>>, <<<<<<"expectation '"/utf8, Identifier/binary>>/binary, "' - "/utf8>>/binary, Err/binary>>, caffeine_lang@errors:empty_context()} end ) end, fun(_) -> gleam@result:'try'( begin _pipe@3 = window_to_rolling_count( erlang:element(4, Slo) ), gleam@result:map_error( _pipe@3, fun(Err@1) -> caffeine_lang@errors:prefix_error( Err@1, Identifier ) end ) end, fun(Rolling_count) -> gleam@result:'try'( build_events_block( erlang:element(3, Slo), Evaluation_expr, Identifier ), fun(Events_block) -> Description = build_description(Ir), Resource = {resource, <<"newrelic_service_level"/utf8>>, Resource_name, maps:from_list( [{<<"guid"/utf8>>, terra_madre@hcl:ref( <<"var.newrelic_entity_guid"/utf8>> )}, {<<"name"/utf8>>, {string_literal, erlang:element( 2, erlang:element( 2, Ir ) )}}, {<<"description"/utf8>>, {string_literal, Description}}] ), [Events_block, {block, <<"objective"/utf8>>, [], maps:from_list( [{<<"target"/utf8>>, {float_literal, erlang:element( 2, Slo )}}] ), [{block, <<"time_window"/utf8>>, [], maps:new(), [terra_madre@hcl:simple_block( <<"rolling"/utf8>>, [{<<"count"/utf8>>, {int_literal, Rolling_count}}, {<<"unit"/utf8>>, {string_literal, <<"DAY"/utf8>>}}] )]}]}], terra_madre@hcl:empty_meta(), none}, {ok, Resource} end ) end ) end ) end ) end ). -file("src/caffeine_lang/codegen/newrelic.gleam", 33). ?DOC(false). -spec generate_resources( list(caffeine_lang@linker@ir:intermediate_representation()) ) -> {ok, list(terra_madre@terraform:resource())} | {error, caffeine_lang@errors:compilation_error()}. generate_resources(Irs) -> _pipe = Irs, gleam@list:try_map(_pipe, fun ir_to_terraform_resource/1). -file("src/caffeine_lang/codegen/newrelic.gleam", 19). ?DOC(" Generate Terraform HCL from a list of New Relic IntermediateRepresentations.\n"). -spec generate_terraform( list(caffeine_lang@linker@ir:intermediate_representation()) ) -> {ok, binary()} | {error, caffeine_lang@errors:compilation_error()}. generate_terraform(Irs) -> gleam@result:'try'( generate_resources(Irs), fun(Resources) -> {ok, caffeine_lang@codegen@generator_utils:render_terraform_config( Resources, terraform_settings(), [provider()], variables() )} end ).