Current section

Files

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

src/caffeine_lang@codegen@newrelic.erl

-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
).