TL; DR: here are my notes on provisioning Google log-based metrics using Terraform and YAML. The metrics are defined in YAML in a clean fashion and they will be created via terraform apply
# my-metrics.yaml metrics: my-custom-metric-from-logs: bucket_name: my-logging-bucket-name filter: | logName="projects/my-gcp-project/logs/my-logging-bucket-name" resource.type="global" jsonPayload.filter.criteria="block" labels: ip: type: STRING field: jsonPayload.client_ip regex: ([0-9]+\.[0-9]+\.[0-9]+) # only grab the first 3 numbers to reduce the amount of labels # some optional defaults defaults: type: INT64 unit: "1" disabled: false
The HCL part for Terraform
locals { manifest = yamldecode(file("./my-metrics.yaml")) metrics = { for k, v in local.manifest.metrics : k => merge(v, { // bucket_name is optional in YAML as global logs won't need this bucket_name = can(v.bucket_name) ? format( "projects/%s/locations/global/buckets/%s", var.project, v.bucket_name ) : null // check and use REGEXP_EXTRACT when regex is present label_extractors = { for lk, lv in try(v.labels, {}) : lk => can(lv.regex) ? "REGEXP_EXTRACT(${lv.field}, \"${lv.regex}\")" : "EXTRACT(${lv.field})" } }) } defaults = local.manifest.defaults } resource "google_logging_metric" "default" { for_each = local.metrics project = var.project name = each.key filter = each.value.filter bucket_name = each.value.bucket_name metric_descriptor { metric_kind = "DELTA" value_type = try(each.value.type, local.defaults.type, "INT64") unit = try(each.value.unit, local.defaults.unit, "1") dynamic "labels" { for_each = try(each.value.labels, {}) content { key = labels.key value_type = labels.value.type description = try(labels.value.description, "") } } display_name = try(each.value.name, each.key) } value_extractor = try(each.value.value_extractor, "") label_extractors = each.value.label_extractors }
Ref.
1, https://cloud.google.com/logging/docs/logs-based-metrics
2, https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/logging_metric
🙂