我正在尝试基于提供相关配置的 yaml 配置文件创建 New Relic 的服务级对象。 我的 yaml 配置:
slo:
targets:
- first_slo:
name: "My First SLO"
endpoints:
- path: /api/method1
method: GET
- path: /api/method2
method: PUT
objectives:
availability:
threshold: 99.9
- first_slo:
name: "My Second SLO"
endpoints:
- path: /api/method12
method: GET
- path: /api/method23
method: PUT
objectives:
availability:
threshold: 99.99
我想迭代这个示例配置来构建对象,但我正在努力使用嵌套迭代来形成正确的 NRQL 查询。
我的地形文件:
resource "newrelic_service_level" "availability" {
for_each = var.config.slo.targets
guid = var.guid
name = "${each.value.name} - Availability"
description = "Proportion of requests that are served successfully."
events {
account_id = var.account_id
valid_events {
from = "Transaction"
where = "transactionType='Web' AND entityGuid = '${var.guid}' AND (OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS)"
}
bad_events {
from = "Transaction"
where = "transactionType= 'Web' AND entityGuid = '${var.guid}' AND numeric(response.status) >= 500 AND (OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS)"
}
}
objective {
target = each.value.objectives.availability.threshold
time_window {
rolling {
count = 7
unit = "DAY"
}
}
}
}
所以基本上我在这里尝试做的是使用 NRQL 查询创建一个服务级别,该查询仅针对与此特定目标相关的 URI 和方法的特定组合进行过滤 - 我在配置中拥有的 URI 和方法文件。
所以对于第一个 SLO,
OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS
应该翻译成这样:
(request.uri = '/api/method1' AND request.method = 'GET') OR (request.uri = '/api/method2' AND request.method = 'PUT')
我目前的解决方案是手动构建查询并将其添加到每个 SLO 的配置中,但它不可读且难以维护。
我将非常感谢有关如何动态构建查询的任何建议。
您当然可以使用 Terraform 构建该查询。这是一个小
.tf
文件,展示了您如何做到这一点:
locals {
config = yamldecode(file("${path.root}/vars.yaml"))
parsed = [for d in local.config.slo.targets : {
name : d["name"]
condition : join(" OR ", [for e in d["endpoints"] : "(request.uri = '${e["path"]}' AND request.method = '${e["method"]}')"])
}]
}
output "parsed" {
value = local.parsed
}
这期望您的 yaml 文件位于其旁边,名称为
vars.yaml
,并生成:
$ terraform plan
Changes to Outputs:
+ parsed = [
+ {
+ condition = "(request.uri = '/api/method1' AND request.method = 'GET') OR (request.uri = '/api/method2' AND request.method = 'PUT')"
+ name = "My First SLO"
},
+ {
+ condition = "(request.uri = '/api/method12' AND request.method = 'GET') OR (request.uri = '/api/method23' AND request.method = 'PUT')"
+ name = "My Second SLO"
},
]
对于您的模块,您可以只使用
join(...)
部分代替OR_CONDITION_BETWEEN_ALL_THE_METHODS_AND_URIS
。重复它应该没问题(只要你记录它,自然),但如果你不喜欢大长线,你可以创建一个子模块来封装它。或者您可以在预处理 locals
块中构建查询字符串,可能使用 merge
函数将查询字符串添加到每个目标配置的其余部分。