# Observability Module # Provides unified logging, metrics, and tracing across all environments locals { environments = var.environments global_config = var.global_config clusters = var.clusters # Extract observability config obs_config = try(local.global_config, {}) logging_config = try(local.obs_config.logging, {}) metrics_config = try(local.obs_config.metrics, {}) tracing_config = try(local.obs_config.tracing, {}) } # ============================================ # LOGGING CONFIGURATION # ============================================ # Generate logging configuration per environment resource "local_file" "logging_config" { for_each = local.clusters filename = "${path.module}/../../../../config/observability/logging-${each.key}.yaml" content = yamlencode({ cluster = each.key provider = try(local.logging_config.provider, "loki") endpoint = try(local.logging_config.central_endpoint, "") config = { loki = { url = try(local.logging_config.central_endpoint, "http://loki:3100") labels = { cluster = each.key provider = try(local.environments[each.key].provider, "unknown") } } elasticsearch = { url = try(local.logging_config.central_endpoint, "") index = "besu-network-${each.key}" } } }) } # ============================================ # METRICS CONFIGURATION # ============================================ # Generate Prometheus/metrics configuration resource "local_file" "metrics_config" { for_each = local.clusters filename = "${path.module}/../../../../config/observability/metrics-${each.key}.yaml" content = yamlencode({ cluster = each.key provider = try(local.metrics_config.provider, "prometheus") endpoint = try(local.metrics_config.central_endpoint, "") scrape_configs = [ { job_name = "besu-validators" kubernetes_sd_configs = [{ role = "pod" }] relabel_configs = [{ source_labels = ["__meta_kubernetes_pod_label_role"] action = "keep" regex = "validator" }] }, { job_name = "besu-rpc" kubernetes_sd_configs = [{ role = "pod" }] relabel_configs = [{ source_labels = ["__meta_kubernetes_pod_label_role"] action = "keep" regex = "rpc" }] } ] }) } # ============================================ # TRACING CONFIGURATION # ============================================ # Generate tracing configuration resource "local_file" "tracing_config" { for_each = local.clusters filename = "${path.module}/../../../../config/observability/tracing-${each.key}.yaml" content = yamlencode({ cluster = each.key provider = try(local.tracing_config.provider, "jaeger") endpoint = try(local.tracing_config.central_endpoint, "") config = { jaeger = { agent_host = try(split(":", local.tracing_config.central_endpoint)[0], "jaeger") agent_port = try(split(":", local.tracing_config.central_endpoint)[1], "6831") } zipkin = { url = try(local.tracing_config.central_endpoint, "http://zipkin:9411") } } }) } # ============================================ # GRAFANA DASHBOARDS # ============================================ # Generate Grafana dashboard configuration resource "local_file" "grafana_dashboards" { filename = "${path.module}/../../../../config/observability/grafana-dashboards.yaml" content = yamlencode({ dashboards = { for name, cluster in local.clusters : name => { title = "Besu Network - ${name}" panels = [ { title = "Block Production Rate" targets = [ { expr = "rate(besu_blockchain_blocks_added_total[5m])" legendFormat = "{{cluster}}" } ] }, { title = "Validator Health" targets = [ { expr = "besu_validator_health" legendFormat = "{{validator}}" } ] }, { title = "RPC Requests" targets = [ { expr = "rate(besu_rpc_requests_total[5m])" legendFormat = "{{method}}" } ] } ] } } }) }