feat: wrap OTel exporters with circuit breaker

Summary

Introduces FallibleMetricExporter and FallibleSpanExporter in src/common/observability/ that wrap OTLPMetricExporter and OTLPTraceExporter respectively.

Each wrapper uses MaxAttemptsCircuitBreaker from @gitlab-org/gitlab-lsp to permanently disable export after 3 consecutive failures, logging a single warning. This keeps the extension silent and well-behaved when the OTLP endpoint is blocked by a customer firewall.

Without this, PeriodicExportingMetricReader logs an export failure every 60 seconds indefinitely, and BatchSpanProcessor retries span exports on every flush — both with no built-in retry limit.

Both exporters are placed in src/common/observability/ so they can be reused if a browser OTel implementation is added later. @opentelemetry/sdk-trace-base@2.7.1 is added as a direct dependency to deduplicate the version used across all OTel packages.

How to test

Apply the following patch to src/desktop/observability/node_observability_service.ts to use an unreachable endpoint and speed up the export interval:

-const DEFAULT_OTLP_BASE_URL = 'https://67713089.otel.gitlab-o11y.com:14318';
+const DEFAULT_OTLP_BASE_URL = 'http://localhost:19999'; // TESTING: unreachable endpoint
-        exportTimeoutMillis: 5000,
+        exportTimeoutMillis: 2000, // TESTING: reduced timeout
-          exportIntervalMillis: 60000,
+          exportIntervalMillis: 3000, // TESTING: reduced from 60000

Then:

  1. Run the extension (F5)
  2. Open View → Output → GitLab
  3. After ~10s you should see a circuit breaker warning:

2026-06-03T22:10:41:719 [warning]: [FallibleMetricExporter] OTel metric export failed 3 consecutive times. Disabling further export attempts. The OTLP endpoint may be blocked by a firewall.

Closes #2289 (closed)

Edited by Olena Horal-Koretska

Merge request reports

Loading
Loading