这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@bkonkle
Copy link

@bkonkle bkonkle commented Nov 17, 2025

Summary

This PR adds an experimental observability pipeline to Turborepo that can export run and task metrics via OpenTelemetry (OTLP). The feature is opt‑in: file‑based configuration (experimentalObservability in turbo.json) is gated behind a future flag, while environment variables and CLI flags can enable OTEL without modifying config files. The configuration model is designed so that additional observability backends can be added later without changing the public configuration shape.

Motivation

Turborepo already computes rich run summaries and per‑task metadata (durations, cache status, SCM info, etc.), but these insights were only available locally (e.g. via --dry=json/--summarize). This change lets users send those metrics to any OTLP‑compatible collector for long‑term analysis, alerting, and correlation with other telemetry, while keeping the core CLI behavior unchanged.

High‑level design

  • New observability abstraction

    • Introduces an observability module with:

      • RunObserver trait: “record metrics for a completed run” and shutdown.

      • observability::Handle: an opaque, cloneable handle used by the rest of turborepo-lib.

    • Currently only an OTEL implementation exists, but the abstraction allows plugging in other backends later.

  • New turborepo-otel crate

    • Wraps opentelemetry, opentelemetry-otlp, and related crates.

    • Provides:

      • Config (endpoint, protocol, headers, timeout, resource attributes, metric toggles).

      • RunMetricsPayload and TaskMetricsPayload structs that encode a completed run and its tasks.

      • Handle::try_new(config) which builds an OTLP metrics exporter (gRPC or HTTP/protobuf) and exposes:

        • record_run(&RunMetricsPayload)

        • shutdown()

  • Observability configuration model

    • ConfigurationOptions now includes:

      • experimental_observability: Option<ExperimentalObservabilityOptions>

      • ExperimentalObservabilityOptions is a wrapper with:

        • otel: Option<ExperimentalOtelOptions>
    • This mirrors the turbo.json shape (experimentalObservability.otel) and leaves room for future backends to be added next to otel without reworking the config surface.

    • File‑based sources (turbo.json and .turbo/config.json) only populate experimental_observability when the root turbo.json has futureFlags.experimentalObservability: true. Env vars and CLI flags always participate in layering and are not gated by the future flag, so they can be used to experiment without changing config files.

Configuration surfaces

turbo.json

  • Observability is guarded by a future flag:

    {
      "futureFlags": {
        "experimentalObservability": true
      },
      "experimentalObservability": {
        "otel": {
          "enabled": true,
          "protocol": "grpc",              // or "http/protobuf"
          "endpoint": "https://collector.example.com",
          "headers": {
            "X-API-Key": "your-api-key"
          },
          "timeoutMs": 10000,
          "resource": {
            "service.name": "turborepo"
          },
          "metrics": {
            "runSummary": true,
            "taskDetails": false
          }
        }
      }
    }
  • Rules:

    • The experimentalObservability block is only read when futureFlags.experimentalObservability is true in the root turbo.json.

    • For file‑based config, experimentalObservability.otel.endpoint is required; otherwise the OTEL exporter is treated as disabled.

    • Package‑level turbo.json files cannot define experimentalObservability or futureFlags.

Environment variables

  • Env vars map directly into ExperimentalOtelOptions and then into the experimental_observability.otel wrapper (even if the future flag is disabled or absent):

    • TURBO_EXPERIMENTAL_OTEL_ENABLED1, 0, true, or false

    • TURBO_EXPERIMENTAL_OTEL_PROTOCOL – protocol string:

      • grpc
      • or HTTP/protobuf, where any of http/protobuf, http, or http_protobuf map to the HTTP/protobuf variant
    • TURBO_EXPERIMENTAL_OTEL_ENDPOINT – collector URL

    • TURBO_EXPERIMENTAL_OTEL_TIMEOUT_MS – timeout in milliseconds

    • TURBO_EXPERIMENTAL_OTEL_HEADERS – comma‑separated key=value pairs

    • TURBO_EXPERIMENTAL_OTEL_RESOURCE – comma‑separated key=value pairs

    • TURBO_EXPERIMENTAL_OTEL_METRICS_RUN_SUMMARY1, 0, true, or false

    • TURBO_EXPERIMENTAL_OTEL_METRICS_TASK_DETAILS1, 0, true, or false

  • Parsing behavior:

    • Boolean env flags accept 1/0 and true/false (other values produce a targeted configuration error that names the offending env var).

    • TURBO_EXPERIMENTAL_OTEL_PROTOCOL rejects unsupported values with a clear configuration error.

    • Header/resource strings must be key=value entries, separated by commas; malformed entries are rejected with a clear error instead of being ignored.

CLI flags

  • New global flags provide a CLI override layer:

    • --experimental-otel-enabled[=true|false]

    • --experimental-otel-protocol <grpc|http-protobuf>

    • --experimental-otel-endpoint <URL>

    • --experimental-otel-timeout-ms <MILLISECONDS>

    • --experimental-otel-header KEY=VALUE (repeatable)

    • --experimental-otel-resource KEY=VALUE (repeatable)

    • --experimental-otel-metrics-run-summary[=true|false]

    • --experimental-otel-metrics-task-details[=true|false]

  • These flags are converted to ExperimentalOtelOptions and wrapped into ExperimentalObservabilityOptions by the layered config builder, overriding env vars and turbo.json where provided. Like env vars, they do not depend on futureFlags.experimentalObservability and can enable or tweak OTEL even when file‑based observability config is gated off.

Metrics exported

  • Run‑level metrics (enabled by metrics.runSummary, default true):

    • Run duration (ms).

    • Number of tasks attempted, failed, and cached.

    • Run exit code.

    • SCM branch and revision (when available).

    • Attributes include:

      • turbo.run.id

      • turbo.run.exit_code

      • turbo.version

      • turbo.scm.branch

      • turbo.scm.revision

  • Task‑level metrics (enabled by metrics.taskDetails, default false):

    • Per‑task execution duration (ms).

    • Cache hit/miss events and optional cache source.

    • Cache time saved (ms) on hits.

    • Task exit code.

    • Identifiers for correlation:

      • turbo.task.id

      • turbo.task.name

      • turbo.task.package

      • turbo.task.hash

      • turbo.task.external_inputs_hash

      • turbo.task.command

  • OTEL resource attributes:

    • service.name defaults to "turborepo" but can be overridden via the resource map.

    • Additional resource attributes from config are attached to all metrics.

Integration into the run lifecycle

  • ConfigurationOptions now aggregates observability configuration from:

    • turbo.json (root only, guarded by futureFlags.experimentalObservability)

    • global/local config

    • environment variables

    • CLI flags

  • Opts exposes experimental_observability: Option<ExperimentalObservabilityOptions>.

  • RunBuilder:

    • Reads opts.experimental_observability and, if present, calls observability::Handle::try_init.

    • Stores the resulting handle on the Run struct.

  • At the end of a real run, the RunSummary uses this handle to:

    • Record metrics derived from the same data that powers the run summary output.

    • Call shutdown() on the OTEL SDK to flush any buffered data before process exit.

  • Dry runs (--dry / --dry=json) do not emit OTEL metrics:

    • For dry runs, the summary path short‑circuits after printing the textual/JSON summary and returns early, without recording or flushing OTEL metrics.

Failure modes and compatibility

  • The feature is strictly opt‑in:

    • If enabled is explicitly false or no valid endpoint is configured, no exporter is created.

    • If configuration parsing fails (bad protocol, malformed headers, invalid env flags), errors are reported as configuration errors rather than failing silently.

  • Exporter initialization and shutdown are non‑fatal:

    • If the OTLP exporter cannot be built (e.g. invalid headers, SDK errors), Turborepo logs a warning and runs without observability.

    • Errors during shutdown are logged but do not affect the run’s exit code.

  • Compile‑time feature gating:

    • The OTEL implementation is behind an otel Cargo feature on turborepo-lib/turbo; if the binary is built without this feature, no exporter is initialized (observability config is effectively a no‑op, aside from normal config parsing/validation).
  • Existing behavior is unchanged when observability is not configured:

    • No new network calls are made.

    • No extra metrics are emitted.

    • CLI and config semantics remain the same for users who don’t opt into this feature.

How to use

  1. Deploy or point to an OTLP‑compatible collector.

  2. In the root turbo.json, enable futureFlags.experimentalObservability and define an experimentalObservability.otel block with at least an endpoint (and optional protocol, headers, etc.), or configure via environment variables / CLI flags (which can be used even without the future flag).

  3. Start with metrics.runSummary: true and metrics.taskDetails: false to verify the setup and then opt into taskDetails when more granular task metrics are useful.

This PR lays the foundation for observability in Turborepo with a concrete OTEL implementation, a configuration model that supports layered overrides (file, env, CLI), and room to grow to additional backends over time.

@turbo-orchestrator turbo-orchestrator bot added the area: docs Improvements or additions to documentation label Nov 17, 2025
@vercel
Copy link
Contributor

vercel bot commented Nov 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
examples-basic-web Ready Ready Preview Comment Nov 18, 2025 3:40pm
examples-designsystem-docs Ready Ready Preview Comment Nov 18, 2025 3:40pm
examples-gatsby-web Ready Ready Preview Comment Nov 18, 2025 3:40pm
examples-kitchensink-blog Ready Ready Preview Comment Nov 18, 2025 3:40pm
examples-nonmonorepo Ready Ready Preview Comment Nov 18, 2025 3:40pm
examples-svelte-web Ready Ready Preview Comment Nov 18, 2025 3:40pm
examples-tailwind-web Ready Ready Preview Comment Nov 18, 2025 3:40pm
examples-vite-web Ready Ready Preview Comment Nov 18, 2025 3:40pm
turbo-site Ready Ready Preview Comment Nov 18, 2025 3:40pm

Copy link
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Build Fix:

Two code blocks are missing required title attributes. The documentation framework requires all code blocks to have titles. The blocks at line 789 (under experimentalObservability.otel.headers) and line 812 (under experimentalObservability.otel.resource) both use the opening marker ```jsonc without a title attribute, causing the build to fail.

View Details
📝 Patch Details
diff --git a/docs/site/content/docs/reference/configuration.mdx b/docs/site/content/docs/reference/configuration.mdx
index ccce2e05e..1cb37964c 100644
--- a/docs/site/content/docs/reference/configuration.mdx
+++ b/docs/site/content/docs/reference/configuration.mdx
@@ -786,7 +786,7 @@ The OTLP collector endpoint URL. For example:
 
 Optional HTTP headers to include with export requests. Useful for authentication (e.g., API keys) or custom metadata.
 
-```jsonc
+```jsonc title="./turbo.json"
 {
   "experimentalObservability": {
     "otel": {
@@ -809,7 +809,7 @@ Timeout in milliseconds for export requests to the collector.
 
 Optional resource attributes to attach to all exported metrics. These help identify the source of metrics in your observability platform.
 
-```jsonc
+```jsonc title="./turbo.json"
 {
   "experimentalObservability": {
     "otel": {

Analysis

Missing code block titles in documentation

What fails: Next.js build fails during static page generation for the /docs/reference/configuration page. The MDX renderer requires all code blocks to have title attributes.

How to reproduce:

cd docs/site
pnpm run build

Result before fix:

Error occurred prerendering page "/docs/reference/configuration"
Error: Code blocks must have titles. If you are creating a terminal, use "Terminal" for the title. Else, add a file path name.

Result after fix:

✓ Compiled successfully in 32.7s
[Build completes successfully with all 236 pages generated]

Root cause: Two code blocks in docs/site/content/docs/reference/configuration.mdx were missing the required title attribute:

  • Line 789: Code block under experimentalObservability.otel.headers
  • Line 812: Code block under experimentalObservability.otel.resource

Both blocks were changed from ```jsonc to ```jsonc title="./turbo.json" to match the pattern used throughout the documentation.

Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: docs Improvements or additions to documentation area: site

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants