Telemetry
Observe Updatecli pipeline execution with OpenTelemetry tracing
Description
Updatecli supports distributed tracing via OpenTelemetry. When enabled, every pipeline run emits spans that show exactly where time is spent and which resources succeeded or failed.
Tracing is opt-in and disabled by default. When tracing initialization fails, Updatecli continues normally — tracing never blocks execution.
Enabling Tracing
Configuration is done entirely via standard OpenTelemetry environment variables. No Updatecli-specific flags are required.
| Variable | Description |
|---|---|
| Selects the exporter. Supported values: |
| Collector endpoint for all signals (e.g. |
| Override the endpoint specifically for traces. |
When neither OTEL_TRACES_EXPORTER nor any endpoint variable is set, tracing is fully disabled (noop). When only an endpoint is set with no exporter name, Updatecli infers otlp (gRPC).
Note | The console and stdout exporter values are aliases — both print spans to stdout. This is useful for verifying that tracing works, but the output is very verbose (one JSON block per span). For day-to-day use, prefer sending traces to a backend like Jaeger or Grafana Tempo. |
Span Hierarchy
Each Updatecli run produces a trace with the following span structure:
updatecli (root)
├── updatecli.prepare
│ ├── updatecli.load_configurations
│ ├── updatecli.init_scm
│ └── updatecli.autodiscovery
└── updatecli.run
├── updatecli.pipeline (one per pipeline)
│ └── updatecli.resource (one per source, condition, or target)
├── updatecli.push_commits (apply mode only)
├── updatecli.run_actions
└── updatecli.prune_scm_branches (apply mode with branch cleanup enabled)Note | updatecli.push_commits and updatecli.prune_scm_branches are only emitted in apply mode when push is enabled. They will not appear in diff or prepare traces. |
Span Attributes
Root Span
| Attribute | Description |
|---|---|
| The CLI subcommand that was run (e.g. |
| The Updatecli version string. |
Run Span
| Attribute | Description |
|---|---|
| Total number of pipelines executed in this run. |
| Whether the run was in dry-run mode. |
Pipeline Span
| Attribute | Description |
|---|---|
| Human-readable pipeline name. |
| Unique pipeline identifier. |
| Number of sources in the pipeline. |
| Number of conditions in the pipeline. |
| Number of targets in the pipeline. |
| Present (and set to |
| Final result of the pipeline execution. |
| Crawler that generated this pipeline (autodiscovered pipelines only). |
Resource Span
| Attribute | Description |
|---|---|
| Resource identifier within the pipeline. |
| Resource category: |
| Resource name. |
| Plugin kind (e.g. |
| Execution result of this resource. |
| Human-readable description of what the resource did. |
Condition-Specific Attributes
| Attribute | Description |
|---|---|
| Whether the condition passed. |
| ID of the source this condition depends on, if any. |
Target-Specific Attributes
| Attribute | Description |
|---|---|
| Whether the target made a change. |
| Whether this target ran in dry-run mode. |
| ID of the source this target applies, if any. |
| Files modified by this target. |
Span Events
| Event | Span |
|---|---|
Description |
|
| Emitted on target resource spans that modified files. The changed files are available in the |
|
|
Prepare Span Attributes
| Span | Attribute | Description |
|---|---|---|
|
| Number of pipelines loaded from manifests. |
|
| Whether default crawlers were enabled (true when no manifests are found). |
Result Values
Pipeline and resource results use the following symbols:
| Symbol | Meaning |
|---|---|
| Success |
| Attention — a change was detected (or would be applied in dry-run mode) |
| Failure |
| Skipped |
HTTP Instrumentation
Outgoing HTTP requests — to registries, GitHub, and other external APIs — are automatically instrumented via an otelhttp transport wrapper. HTTP spans appear as children of the pipeline span, giving full visibility into external API latency without any additional configuration.
Credential Safety
Error messages recorded on spans are automatically sanitized to strip URL-embedded credentials before they are sent to the trace backend. For example, https://user:token@github.com is recorded as https://*:*@github.com. This prevents accidental token leaks regardless of which backend you use.
Examples
Local Debugging with Stdout
Print spans to stdout without running a collector:
OTEL_TRACES_EXPORTER=console updatecli pipeline diff --config manifest.yamlImportant | The console exporter is very verbose — it outputs a full JSON block for every span, including HTTP requests. It is best suited for one-off verification, not regular use. For a better experience, use a trace backend like Jaeger (see below). |
Jaeger
Start Jaeger all-in-one locally:
docker run --rm -p 4317:4317 -p 16686:16686 \
jaegertracing/all-in-one:latestThen run Updatecli with the gRPC endpoint. Because only the endpoint is set, Updatecli infers otlp (gRPC) automatically:
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 updatecli pipeline apply --config manifest.yamlOpen http://localhost:16686 to explore the traces.
Grafana Tempo or Any OTLP-Compatible Backend
OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317 updatecli pipeline apply --config manifest.yamlHTTP Exporter
For backends that only accept HTTP/protobuf instead of gRPC:
OTEL_TRACES_EXPORTER=otlphttp \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
updatecli pipeline apply --config manifest.yaml