Implement feature negotiation for CI job telemetry (Rails side)

Summary

Implement the Rails side of feature negotiation for CI job telemetry. When a Runner requests a job, the Rails response should include a features.tracing object that signals telemetry is enabled and provides trace context for that job.

Job payload change

Add a tracing entry to the existing features object in the /api/v4/jobs/request response:

{
  "features": {
    "tracing": {
      "trace_id": "<hex-encoded 16-byte trace ID derived from root pipeline ID>",
      "span_parent_id": "<hex-encoded 8-byte span ID of the trigger/bridge job, if child pipeline>",
      "otel_endpoints": ["https://otel-collector.gitlab.net/v1/traces"]
    }
  }
}
  • Presence of features.tracing = telemetry enabled; absence = telemetry disabled (no boolean flag needed).
  • trace_id is derived deterministically from the root pipeline ID, so all jobs across parent and child pipelines share the same trace.
  • span_parent_id is included only for child pipeline jobs and references the trigger (bridge) job's span ID, allowing child pipeline jobs to nest under the trigger job in the trace tree.

This is a unified payload — sampling configuration is not included:

  • Sampling is handled entirely at the OTEL Collector level using the probabilistic sampler processor, adjustable without Rails or Runner changes
  • The OTEL Collector endpoint is provided from Rails via features.tracing.otel_endpoints (array, max 2) — first entry is a Rails application setting (see #591941 (closed)); optional second entry is a customer-configured BYO OTLP endpoint (project/group level, future). No static runner-side config.toml configuration needed.

Requirements

  1. Add tracing (with trace_id and optional span_parent_id) to the features object in the job payload response
  2. Controlled by a project-level feature flag for gradual rollout
    • MVC: enable for DevExp Customer0 projects on hosted runners
    • Broader rollout: enable progressively for more projects
  3. Include trace_id (derived from root pipeline ID) and span_parent_id (for child pipelines) inside features.tracing (see #590587 (closed))

Architecture Reference

Parent Epic

&20945

Edited by Pedro Pombeiro