Telemetry
This guide explains how to run application telemetry on Control Plane with
cpflow. It is intentionally generic: the examples use placeholder service
names, simple metric names, and backend-neutral collector configuration.
cpflow does not instrument application code. It helps deploy the Control Plane
workloads and environment values that already-instrumented applications use to
send traces, metrics, and logs.
Quick Navigation
| Page | Use it for |
|---|---|
| Collector workload | Control Plane workload template, collector ports, and matching config.yaml |
| Application instrumentation | Generic app env vars and simple Ruby/Node examples |
| Pipelines | Receivers, processors, exporters, and how signals flow |
| Review apps | Review-app isolation, sampling, secrets, and egress controls |
| Troubleshooting | Commands and checks for missing telemetry |
Recommended Shape
flowchart LR
app["Application workload(s)"]
collector["Collector workload"]
backend["Telemetry backend(s)"]
dashboard["Dashboards and alerts"]
app -->|"OTLP HTTP :4318"| collector
app -->|"Optional StatsD TCP :9127"| collector
collector -->|"Traces, metrics, logs"| backend
backend --> dashboard
Keep the collector inside the same GVC as the application unless your team has a separate, intentionally shared telemetry GVC. A same-GVC collector keeps review, staging, and production wiring easy to reason about and avoids accidental cross-environment data mixing.
What cpflow Provides
cpflow apply-template already applies ordinary Control Plane workload
templates from .controlplane/templates. Telemetry can therefore be added with
project templates and app environment values; no custom cpflow telemetry
command is required.
Use cpflow for:
- Deploying an OpenTelemetry Collector workload template.
- Applying GVC or workload environment variables that point apps at the collector.
- Reusing the same setup shape for review, staging, and production apps.
- Tailing application and collector logs with
cpflow logs.
Application code is still responsible for:
- Installing OpenTelemetry, StatsD, Prometheus, or framework-specific instrumentation libraries.
- Setting service names and resource attributes.
- Creating custom spans or metrics.
- Filtering sensitive data before it leaves the process.
Signal Flow
flowchart TB
subgraph app["Application process"]
trace_sdk["Trace SDK"]
metric_sdk["Metric SDK"]
otlp_logs["OTLP logs"]
stdout_logs["stdout/stderr logs"]
end
subgraph collector["Collector workload"]
receivers["Receivers"]
processors["Processors"]
exporters["Exporters"]
end
traces["Trace backend"]
metrics["Metrics backend"]
logs["OTLP log backend"]
platform_logs["Platform log capture"]
platform_logs_backend["Platform log backend"]
trace_sdk -->|"OTLP traces"| receivers
metric_sdk -->|"OTLP metrics or StatsD TCP"| receivers
otlp_logs -->|"OTLP logs"| receivers
stdout_logs -->|"bypasses collector"| platform_logs
platform_logs -->|"cpflow logs and historical queries"| platform_logs_backend
receivers --> processors
processors --> exporters
exporters --> traces
exporters --> metrics
exporters --> logs
stdout/stderr logs bypass the collector and are captured directly by the
platform. Use cpflow logs for live tailing.
For new instrumentation, prefer OTLP over HTTP on port 4318. It is the most
portable path because it can carry traces, metrics, and logs through one
well-known protocol. Use StatsD only when your application already has a simple
StatsD client or when a metric library cannot emit OTLP yet.
Minimal Rollout Checklist
-
Add
.controlplane/templates/open-telemetry-collector-secrets.ymland.controlplane/templates/open-telemetry-collector.yml. -
Package a collector
config.yamlthat binds every port exposed by the workload template. -
Build the collector image and push it to your registry. Update the workload template's
image:field to that pushed image reference before applying it. -
Add both collector templates to
setup_app_templatesin.controlplane/controlplane.yml(see Collectorcontrolplane.yml):open-telemetry-collector-secretsfirst, thenopen-telemetry-collector. -
Add the collector to
additional_workloadsin.controlplane/controlplane.yml. -
Set application env vars such as
OTEL_SERVICE_NAME,OTEL_EXPORTER_OTLP_ENDPOINT, andOTEL_EXPORTER_OTLP_PROTOCOL. -
For an existing app, apply both collector templates in the same order: identity and policy first, then the collector workload.
cpflow apply-template open-telemetry-collector-secrets -a $APP_NAME
cpflow apply-template open-telemetry-collector -a $APP_NAMEFor a brand-new app,
cpflow setup-appapplies the configured templates insetup_app_templatesorder. -
Confirm collector logs, application exporter logs, and backend ingestion.
The collector workload and its config.yaml must be kept in sync. If the
workload exposes 4318, 9127, or 9292, the collector config must bind those
same ports. Exposing a port in Control Plane does not automatically enable a
collector receiver or exporter.
Generic Naming
Use generic service names, metric names, and resource attributes in reusable telemetry templates. See Service Names for examples and avoidance rules.
More Detail
Start with Collector workload, then read Application instrumentation. Use Troubleshooting when signals do not appear in the backend.