Skip to content

Constructs & Workloads

synthkit's catalog is a collection of isolated construct and workload modules. The current catalog has 50 construct kinds and 3 workload kinds (53 total). Each construct is a separate Go package under internal/construct/<kind>/; workloads live under internal/workload/<kind>/. Neither constructs nor workloads import each other or the blueprint package — isolation is enforced by internal/archtest.

Construct granularity principle

A construct boundary is drawn at the smallest unit that is independently declarable in a blueprint AND carries a distinct shared identity or cross-construct join — not at the delivery pipeline.

  • Distinct fixture + distinct declaration + distinct join → separate construct, sharing a mechanic library. ec2, rds, and elasticache are separate because each hangs off its own fixture type (fixture.Node, fixture.DB, fixture.Cache) and joins to other constructs through that identity.
  • Same pipeline + same identity + declared together → one construct with config-gated sub-families. cw_infra bundles ALB/NLB/EBS/NAT/EKS/S3/Firehose off one cloud identity, each family gated by a per-family switch. k8s_cluster gates OpenCost/Kepler/Alloy via k8s_monitoring config.
  • Engine/type variants of one resource → a config discriminator, not a new kind. RDS Postgres vs Aurora Postgres share the rds construct; the engine selects the CloudWatch family variant.

For the emission switch that controls which constructs a declaration fans into, see emission-switches.md.

Kubernetes

Constructs in this group are substrate-scoped — they carry no blueprint label. The cluster name disambiguates across blueprints.

KindDescriptionSignal area
k8s_clusterCore k8s-monitoring substrate: kube-state-metrics, node-exporter, cAdvisor, kubelet. Gates OpenCost/Kepler and the Alloy collector via k8s_monitoring config.k8s
k8s_profilingPyroscope-based continuous profiling substrate for workloads running in the cluster.profiles
ksm_ingressKSM ingress metrics (kube_ingress_*) with cluster disambiguation.k8s
etcdetcd cluster health and Raft metrics.k8s-addons

Kubernetes add-ons

Add-ons are declared under cluster.addons in the blueprint. Each is substrate-scoped and emits pod-joined metrics + logs.

KindDescriptionSignal area
argocdArgo CD controller and application metrics.k8s-addons
cert_managercert-manager certificate lifecycle metrics.k8s-addons
cluster_autoscalerCluster Autoscaler node scaling and utilization metrics.k8s-addons
core_dnsCoreDNS request and cache metrics.k8s-addons
ebs_csiAWS EBS CSI driver metrics (volume attach, provision, I/O).k8s-addons
envoy_gatewayEnvoy Gateway proxy metrics (upstream/downstream request rates, latency).k8s-addons
external_dnsExternalDNS DNS sync and registry metrics.k8s-addons
karpenterKarpenter node provisioner metrics (node lifecycle, disruption, scheduling).k8s-addons
load_balancer_controllerAWS Load Balancer Controller metrics.k8s-addons
vpc_cniAWS VPC CNI IP allocation metrics.k8s-addons

Alloy health

KindDescriptionSignal area
alloy_healthGrafana Alloy / agent health and pipeline metrics.fm

AWS infrastructure (CloudWatch)

These constructs are blueprint-scoped (they carry the blueprint selector label). They use internal/cw for the five-stat CloudWatch expansion (_sum/_average/_maximum/_minimum/_sample_count).

KindDescriptionSignal areaBlueprint declaration
ec2EC2 instance CloudWatch metrics (aws_ec2_*). Shares fixture.Node identity with the k8s cluster.cwGated by cluster.observability.cloudwatch
cw_infraCloudWatch infrastructure families: ALB, NLB, EBS, NAT Gateway, EKS control plane, S3, Kinesis Firehose. Each family is independently gated.cwcloud.cloudwatch.* switches

AWS databases and cache

KindDescriptionSignal areaBlueprint declaration
rdsRDS CloudWatch metrics (aws_rds_*). Shares fixture.DB with dbo11y constructs. Supports Postgres, MySQL, Aurora variants.cwdatabases[].observability.cloudwatch
elasticacheElastiCache CloudWatch metrics (aws_elasticache_*).cwcaches[].observability.cloudwatch
docdbAmazon DocumentDB CloudWatch metrics (aws_docdb_*).cwdatabases[].engine: documentdb
neptuneAmazon Neptune CloudWatch metrics (aws_neptune_*).cwdatabases[].engine: neptune
aossAmazon OpenSearch Serverless (AOSS) CloudWatch metrics.cwintegrations: aoss

AWS managed services

KindDescriptionSignal area
glueAWS Glue job and crawler CloudWatch metrics.cw
mwaaAmazon Managed Workflows for Apache Airflow CloudWatch metrics.cw
lambda11 FunctionName/account bases; optional cloud.lambda.functions. Remote-write only.cw
sqsNine ordinary queue bases; optional cloud.sqs.queues. Remote-write only.cw
dynamodb15 provisioned table/account bases; optional cloud.dynamodb.tables. Remote-write only.cw
redshiftTen provisioned-cluster/queue/latency bases; optional cloud.redshift.clusters. Remote-write only.cw
cloudwatch_logsTwo uncompressed intake bases and four optional independent Lambda delivery-observation bases; cloud.cloudwatch_logs.log_groups. Remote-write only.cw
schedulerEventBridge Scheduler invocation attempts per schedule group and account for fixed-rate schedules, plus opt-in target error and dropped counts; cloud.scheduler.schedules. Remote-write only.cw

The five captured-service consumers have conservative one-declaration-per-blueprint/account/ region/kind admission. See authoring and explicit model assumptions and the canonical emitted subset. ESM/fair/info families remain withheld. Redshift user-query/NodeID/managed-storage expansions and Logs by-data-source and other delivery selectors/profiles are withheld. Optional group-owned subscription_filters use literal Lambda/P21 only and four required independent period values; bytes are already compressed. No compression, retry/loss, intake relationship, pipeline or cross-service join is inferred.

Declared pipelines

A batch pipeline is declared once, under the environment's cloud.pipelines:, and drives every construct that executes or orchestrates one of its stages from one deterministic run timeline (the shared internal/pipelinerun mechanic). It adds no metric names of its own: each construct maps the timeline onto its existing CloudWatch families.

cloud:
  mwaa: { environments: [etl-airflow] }
  glue: { jobs: [] }
  pipelines:
    - name: orders_daily
      environment: etl-airflow    # the MWAA environment orchestrating it; omit if none
      every: 24h                  # cadence, 1m to 168h
      offset: 2h                  # trigger phase inside every; omit for a seed-derived phase
      stages:
        - { name: extract,   service: glue,    resource: orders-extract,   duration: 12m }
        - { name: transform, service: glue,    resource: orders-transform, duration: 20m }
        - { name: publish,   service: airflow,                             duration: 2m }
  • Pipeline names are unique across the whole blueprint, including different environments and pipelines with disjoint stage names. The loader rejects repeats with both owning environment names; rename the pipeline declaration, not its CloudWatch dimensions. Pipeline and stage names match [a-z0-9_-]+; the canonical incident target remains <pipeline>.<stage>. Environment names are not delimiter-restricted, so they are not concatenated into stage targets.
  • Run k triggers at k × every + offset, anchored on the Unix epoch. Each stage takes its duration with a ±15% per-run jitter. The resolver supplies the same environment-scoped seed (<blueprint>:<environment>) to Glue and MWAA; phase, duration and failure draws additionally include the pipeline name. Named identity, not declaration order, determines the timeline. Existing single-environment targets and nonpipeline output are unchanged.
  • glue: every glue-stage resource is emitted as a job (added to jobs). Its run-time aggregates and executor gauges follow the stage's execution time in each window and read zero between runs. Jobs that are not stages keep their usual values.
  • mwaa: for the environment named by environment, queued_tasks and running_tasks (both namespaces) count the pipeline's waiting and executing stages, and aws_mwaa_approximate_age_of_oldest_task is the oldest wait. The environment must be listed in mwaa.environments. Declared pipelines also supply sparse AmazonMWAA DAG outcome timers: aws_amazonmwaa_dagduration_success_* and aws_amazonmwaa_dagduration_failed_* carry dimension_DAG=<pipeline-name>. Their five statistics describe actual trigger-to-terminal durations in milliseconds, including waits, with sample count equal to matching completions. aws_amazonmwaa_task_instance_failures_* aggregates failed stages across the environment with literal dimension_DAG=All and dimension_Task=All; it does not invent per-task failure dimensions. No matching outcome means no observation (all five series absent), even after an earlier nonempty window. Remote-write and native OTLP share this behavior. Environments without a pipeline retain their old output. See the MWAA contract in the CloudWatch signal catalogue.
  • A glue stage needs a cloud.glue block and an environment needs a cloud.mwaa block; the loader rejects either missing.
  • lambda, sqs and redshift stages are accepted and take part in the timeline, but have no emitting pipeline adapters. The independent cloud.lambda and cloud.sqs consumers do not consume that timeline; positive Redshift source observations do not install a consumer.
  • Stages are failure targets: see Incidents.

Database Observability (dbo11y)

Substrate-scoped. Shares fixture.DB identity with the corresponding CloudWatch construct.

KindDescriptionSignal areaBlueprint declaration
dbo11y_postgresGrafana Database Observability for PostgreSQL — query digests, connection pool, replication.dbo11ydatabases[].observability.dbo11y: true
dbo11y_mysqlGrafana Database Observability for MySQL.dbo11ydatabases[].observability.dbo11y: true

Both accept the database declaration's optional resource: binding to a dependency or pool, with the CloudWatch lane still required. Independently compiled causal models use the same master clock; no shared mutable construct state or special scheduler is involved. The trailing-minute mean latency scales statement-seconds increments and existing synthetic query/wait durations in both metric and log output. Pool mean busy connections match the CloudWatch connection reading; dependency-only bindings keep baseline connections. This does not attribute acquisition wait to a server Lock/IO category or invent SQL errors. MySQL running threads and server maximum connections remain baseline. Bound instances ignore legacy database-axis modes; unbound output is unchanged. See database bindings and bound incidents. DocumentDB/Neptune dbo11y remains unsupported.

CSP: Azure and GCP

Both are substrate-scoped. Sub-families are gated by sub_signals: [...] in the integration declaration (empty/omitted = all emit).

KindDescriptionSignal area
csp_azureGrafana CSP Azure integration: VMs, App Service, SQL, Storage, Cosmos DB, Functions, and more.cspazure
csp_gcpGrafana CSP GCP integration: Compute, Cloud SQL, Cloud Storage, Pub/Sub, Cloud Run, BigTable.cspgcp

AI & LLM

All AI/LLM constructs are blueprint-scoped and tech-generic. gen_ai metrics go via sink/promrw final names; spans via the hand-encoded OTLP seam. The OTel metrics SDK ban applies.

KindDescriptionSignal areaBlueprint declaration
bedrockAmazon Bedrock CloudWatch model invocation metrics (aws_bedrock_*).bedrockintegrations: bedrock
agentcoreAWS Bedrock AgentCore CloudWatch metrics and Loki logs.agentcoreintegrations: agentcore
portkey_gatewayPortkey AI gateway: request/token/cost metrics scraped from the Portkey API.portkeyintegrations: portkey_gateway
portkey_pollerPortkey native scrape metrics (the separate Portkey Prometheus exporter path).portkeyintegrations: portkey_poller
langsmith_evalLangSmith evaluation metrics: scores, pass rates, latency by evaluator.langsmithintegrations: langsmith_eval
langsmith_platformLangSmith platform-level metrics: run volumes, latency, token counts.langsmithintegrations: langsmith_platform
snowflakeSnowflake Cortex usage and query metrics via the Snowflake Grafana integration.snowflakeintegrations: snowflake
qualification_pipelineAI qualification pipeline metrics (model evaluation + selection flow).qualificationintegrations: qualification_pipeline

Network

KindDescriptionSignal areaBlueprint declaration
network_topologySNMP topology exporter metrics: device availability, interface I/O, link state, federation metrics. Mirrors the external network-topology-exporter signal contract.nettopointegrations: network_topology

Hosts

KindDescriptionSignal areaBlueprint declaration
hostBare-metal or VM host metrics (node_exporter-style) for non-k8s hosts.hosthosts:

Integrations and Grafana products

These constructs model external systems Grafana Cloud ingests, or Grafana Cloud products you have enabled.

KindDescriptionSignal areaBlueprint section
cloudflareCloudflare zone metrics via the Grafana Cloudflare integration (blueprint-scoped).cloudflareintegrations: cloudflare
beyla_agentGrafana Beyla eBPF instrumentation — application RED metrics without SDK instrumentation.beylaintegrations: beyla
synthetic_monitoringGrafana Synthetic Monitoring check data: probe results, latency, reachability.smfeatures: synthetic_monitoring
fleet_managementGrafana Fleet Management collector registration and health.fmfeatures: fleet_management

Workloads

Workloads mint request-correlated telemetry. They share the blueprint's ledger for end-to-end correlation IDs. Both workload kinds may coexist in one blueprint.

KindWhen to useDescription
web_serviceA single serviceEmits RED metrics, traces (browser → backend → DB hops), optional RUM/Faro beacons, optional gen_ai hops. The simple, common case.
appA multi-service graphA declared graph of typed service nodes (services:), each emitting its own custom metrics/logs/spans via the telemetry DSL. One ledger mint drives one correlated trace across the whole graph. Use when you need per-service incident targeting, per-service scaling, or custom metric families per node.

The app workload's telemetry DSL supports typed nodes (frontend/web/grpc/worker/job/stream/gateway/db/cache/llm/agent/tool/workflow/retrieval), ValueModel one-of value generators (const, enum, int_range, float_range, normal, shape, ref), and reusable Profile bundles from the catalog in internal/telemetryspec/profiles.

For workload configuration and the telemetry DSL reference, see workloads.md.