Terraform Provider

The LogStruct Terraform provider offers type-safe helpers for building CloudWatch filter patterns from your structured logs, and validates struct/event combinations at plan time.

Installation

Add the provider to your Terraform configuration. The provider version tracks LogStruct releases and uses the same tag.

Required Providers
terraform {
  required_providers {
    logstruct = {
      source  = "DocSpring/logstruct"
      version = "~> 0.2" # matches LogStruct tag
    }
  }
}

CloudWatch Metric Filter Example

Compile a CloudWatch JSON filter for a known struct/event and wire it into an AWS metric filter. Invalid combinations produce Terraform diagnostics during validate/plan.

Data Source
data "logstruct_cloudwatch_filter" "email_delivered" {
  struct = "ActionMailer"
  event  = "delivered"
}
AWS Metric Filter
resource "aws_cloudwatch_log_metric_filter" "email_delivered_count" {
  name           = "Email Delivered Count"
  log_group_name = var.log_group.docspring
  pattern        = data.logstruct_cloudwatch_filter.email_delivered.pattern

  metric_transformation {
    name          = "docspring_email_delivered_count"
    namespace     = var.namespace.logs
    value         = "1"
    default_value = "0"
    unit          = "Count"
  }
}

The compiled pattern looks like: { $.src = "mailer" && $.evt = "delivered" ... }and includes canonical key names with any fixed source constraints.

Validation and Safety

  • Structs and events are validated at plan time using the embedded LogStruct catalog exported from this repository.
  • If allowed events or keys change in a newer LogStruct release, your Terraform plan will fail fast with clear diagnostics.

Versioning

  • Provider versions mirror LogStruct tags (for example, v0.2.0).
  • Use a compatible constraint like ~> 0.2 to receive non-breaking updates.

Recipes

A few helpful patterns you can copy and adapt:

Count Email Deliveries
data "logstruct_cloudwatch_filter" "email_delivered" {
  struct = "ActionMailer"
  event  = "delivered"
}

resource "aws_cloudwatch_log_metric_filter" "email_delivered_count" {
  name           = "Email Delivered Count"
  log_group_name = var.log_group.app
  pattern        = data.logstruct_cloudwatch_filter.email_delivered.pattern

  metric_transformation {
    name          = "app_email_delivered_count"
    namespace     = var.namespace.logs
    value         = "1"
    unit          = "Count"
  }
}
Count Successful GoodJob Runs
data "logstruct_cloudwatch_filter" "goodjob_finish" {
  struct = "GoodJob"
  event  = "finish"
}

resource "aws_cloudwatch_log_metric_filter" "goodjob_finish_count" {
  name           = "GoodJob Finish Count"
  log_group_name = var.log_group.app
  pattern        = data.logstruct_cloudwatch_filter.goodjob_finish.pattern

  metric_transformation {
    name      = "app_goodjob_finish_count"
    namespace = var.namespace.logs
    value     = "1"
    unit      = "Count"
  }
}
Count All SQL Queries
data "logstruct_cloudwatch_filter" "sql_queries" {
  struct = "SQL"
  event  = "database"
}

resource "aws_cloudwatch_log_metric_filter" "sql_count" {
  name           = "SQL Query Count"
  log_group_name = var.log_group.app
  pattern        = data.logstruct_cloudwatch_filter.sql_queries.pattern

  metric_transformation {
    name      = "app_sql_query_count"
    namespace = var.namespace.logs
    value     = "1"
    unit      = "Count"
  }
}
Count Email Delivery Attempts
data "logstruct_cloudwatch_filter" "email_delivery_attempt" {
  struct = "ActionMailer"
  event  = "delivery"
}

resource "aws_cloudwatch_log_metric_filter" "email_delivery_attempt_count" {
  name           = "Email Delivery Attempt Count"
  log_group_name = var.log_group.app
  pattern        = data.logstruct_cloudwatch_filter.email_delivery_attempt.pattern

  metric_transformation {
    name      = "app_email_delivery_attempt_count"
    namespace = var.namespace.logs
    value     = "1"
    unit      = "Count"
  }
}

For delivery failures, use metric math to compare attempts vs. delivered counts. CloudWatch filter patterns do not support numeric comparisons, so slow-query thresholds are usually handled downstream (for example, count + percentiles in metrics/dashboards). See the provider README for more examples and details.