quickwit-oss/quickwit · error

failed to install global metrics recorder

Error message

failed to install global metrics recorder

What it means

init_metrics_provider builds a metrics recorder (Prometheus or OTLP-backed) and installs it as the process-wide global recorder via metrics::set_global_recorder. The metrics crate allows only ONE global recorder per process; if set_global_recorder returns Err, installation failed and Quickwit aborts startup with this anyhow error.

Source

Thrown at quickwit/quickwit-telemetry-exporters/src/metrics.rs:45

    let prometheus_recorder = crate::prometheus::metrics::build_recorder()?;

    let (recorder, meter_provider) = if otlp_config.is_enabled() {
        let (otlp_recorder, meter_provider) =
            crate::otlp::metrics::build_recorder(service_version, otlp_config)?;
        let recorder = FanoutBuilder::default()
            .add_recorder(prometheus_recorder)
            .add_recorder(otlp_recorder)
            .build();
        (recorder, Some(meter_provider))
    } else {
        let recorder = FanoutBuilder::default()
            .add_recorder(prometheus_recorder)
            .build();
        (recorder, None)
    };

    metrics::set_global_recorder(recorder)
        .map_err(|_| anyhow::anyhow!("failed to install global metrics recorder"))?;
    quickwit_metrics::describe_metrics();

    Ok(meter_provider)
}

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Ensure init_metrics_provider is called exactly once per process
  2. In tests, guard initialization with OnceLock/Once so only the first call installs the recorder
  3. If embedding Quickwit, reuse the host's recorder setup or skip Quickwit's global recorder init

Example fix

// before
static INIT: OnceLock<()> = OnceLock::new();
fn setup() { init_metrics_provider().unwrap(); }
// after
static INIT: OnceLock<()> = OnceLock::new();
fn setup() { INIT.get_or_init(|| init_metrics_provider().unwrap()); }
Defensive patterns

Strategy: validation

Validate before calling

// Rust: only init once per process
static METRICS_INIT: OnceLock<MeterProvider> = OnceLock::new();
fn provider() -> &MeterProvider { METRICS_INIT.get_or_init(|| init_metrics_provider().expect("metrics init")) }

Try / catch

init_metrics_provider().map_err(|e| {
    if e.to_string().contains("already") { /* recorder already installed - proceed */ }
    else { bail!(e) }
})?;

Prevention

When it happens

Trigger: Calling init_metrics_provider more than once in the same process (e.g. test harness calling it in multiple tests sharing a process, or double initialization in embedded usage); a recorder was already installed by another library before Quickwit init.

Common situations: Rust unit/integration tests that each call quickwit telemetry init in the same test binary; embedding quickwit as a library where the host app already set a global metrics recorder; duplicated init in CLI bootstrap paths.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/854cac97ac10208f. Report an issue: GitHub.