> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ai-coustics.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenTelemetry

> Export SDK operational metrics to your own observability backend via OpenTelemetry.

<Warning>
  This is an experimental feature. The API and available metrics may change in future SDK versions.
  Please reach out to ai-coustics support if you want to use or provide feedback on this functionality.
</Warning>

## Overview

The ai-coustics SDK can export operational metrics via [OpenTelemetry](https://opentelemetry.io) (OTel), giving you full visibility into audio processing performance, usage, and quality in your own infrastructure.

<Note>
  These metrics are exported to **your own** observability backend. They are entirely separate from the [product telemetry](/reference/concepts/sdk-telemetry) the SDK sends to ai-coustics.
</Note>

## What is OpenTelemetry?

OpenTelemetry is a vendor-neutral, open-source observability framework. It provides a standardized way to collect and export telemetry data (metrics, traces, and logs) from your applications. All major observability platforms support OTel natively, including Grafana, Datadog, New Relic, Honeycomb, and many others.

The ai-coustics SDK currently exposes **metrics only**. Traces and logs are not emitted.

## Configuration

To activate the OTel metrics pipeline, set the `AIC_SDK_OTEL_ENABLE` environment variable to `1`. The SDK uses the standard OpenTelemetry environment variables for endpoint configuration.

No code changes are required in your SDK integration. Set the variables in your runtime environment and restart your service.

```bash theme={null}
# Activate the OTel metrics pipeline
export AIC_SDK_OTEL_ENABLE=1

# Point to your OTLP-compatible endpoint (default: http://localhost:4318)
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
```

The SDK exports metrics using the **OTLP/HTTP** protocol with **Protobuf** encoding. It registers all instruments under:

* **Service name:** `aic-sdk`
* **Meter name:** `aic_usage`

<Note>
  OTel metrics export is **not available on WASM targets**. It is only supported on native (non-WASM) builds of the SDK.
</Note>

<Note>
  The `api.key` attribute attached to every metric observation is a **SHA-256 hash** of your API key, not the raw key itself. It is safe to store in your telemetry backend.
</Note>

### Environment Variables

| Variable                      | Description                                                                    |
| :---------------------------- | :----------------------------------------------------------------------------- |
| `AIC_SDK_OTEL_ENABLE`         | Set to `1` to activate the OTel metrics pipeline. Any other value disables it. |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP endpoint URL. Defaults to `http://localhost:4318`.                        |
| `OTEL_EXPORTER_OTLP_HEADERS`  | Comma-separated key=value pairs for authentication headers.                    |
| `OTEL_METRIC_EXPORT_TIMEOUT`  | Export timeout in milliseconds. Defaults to `30000` (30s).                     |

<Note>
  The metric export interval is configured per-processor via the `export_interval_ms` field on `AicOtelConfig`, passed to `aic_processor_create`. Set it to `0` to use the default of 60 000 ms.
</Note>

For a full list of supported environment variables, see the [OpenTelemetry SDK Environment Variables specification](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/).

## Session Attributes

Every metric observation includes the following attributes, allowing you to filter and group by session, API key, SDK version, or model.

| Attribute     | Description                                        |
| :------------ | :------------------------------------------------- |
| `api.key`     | SHA-256 hash of the API key used for this session. |
| `session.id`  | Unique identifier for the processing session.      |
| `sdk.version` | Version of the ai-coustics SDK.                    |
| `model.id`    | Identifier of the enhancement model in use.        |

## Metrics Reference

### Usage

Cumulative counters tracking how much audio has been processed.

| Metric             | Type          | Unit | Description                                                                                                   |
| :----------------- | :------------ | :--- | :------------------------------------------------------------------------------------------------------------ |
| `usage.processed`  | Counter (u64) | ms   | Cumulative duration of audio processed this session.                                                          |
| `usage.disallowed` | Counter (u64) | ms   | Cumulative duration of audio that was bypassed this session due to unauthorized usage (e.g. invalid license). |

### Audio Configuration

Gauges reflecting the audio stream configuration for the session. These values are set once during initialization.

| Metric              | Type        | Unit    | Description                                           |
| :------------------ | :---------- | :------ | :---------------------------------------------------- |
| `audio.sample_rate` | Gauge (u64) | Hz      | Sample rate of the audio stream.                      |
| `audio.channels`    | Gauge (u64) |         | Number of audio channels.                             |
| `audio.frame_size`  | Gauge (u64) | samples | Number of samples per processing frame (per channel). |

### Processor State

Gauges reflecting the current state of the audio processor.

| Metric                        | Type        | Unit    | Description                                                                                                                                                       |
| :---------------------------- | :---------- | :------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `processor.output_delay`      | Gauge (u64) | samples | Algorithmic delay introduced by the enhancement model. Convert to ms: $\text{delay\_ms} = \frac{\text{value} \times 1000}{\text{sample\_rate}}$. Lower is better. |
| `processor.enhancement_level` | Gauge (f64) |         | Current enhancement strength (0.0 to 1.0). Higher = more aggressive enhancement.                                                                                  |
| `processor.bypass`            | Gauge (u64) |         | Whether the processor is in bypass mode. 1 = bypass active, 0 = processing active.                                                                                |
| `processor.vad_created`       | Gauge (u64) |         | Whether a voice activity detection (VAD) context has been created. 1 = created, 0 = not created.                                                                  |

### Experimental Metrics

<Warning>
  Experimental metrics are prefixed with `experimental.` and may change or be removed in future SDK versions. Do not build critical alerting on these without pinning your SDK version.
</Warning>

#### Performance

| Metric                                        | Type          | Unit | Description                                                                                                                                                                                         |
| :-------------------------------------------- | :------------ | :--- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `experimental.processor.realtime_violations`  | Counter (u64) |      | Cumulative number of `process()` calls that exceeded the audio buffer duration, indicating real-time budget overruns. Lower is better; sustained values indicate CPU pressure or thread contention. |
| `experimental.processor.process_duration_avg` | Gauge (f64)   | ns   | Average wall-clock time spent inside `process()` per call over the last export interval. Lower is better.                                                                                           |
| `experimental.processor.process_duration_max` | Gauge (u64)   | ns   | Peak wall-clock time spent inside `process()` in any single call during the last export interval. Lower is better.                                                                                  |

#### Voice Activity Detection

| Metric                                | Type          | Unit | Description                                                                                         |
| :------------------------------------ | :------------ | :--- | :-------------------------------------------------------------------------------------------------- |
| `experimental.vad.speech_duration_ms` | Counter (u64) | ms   | Cumulative duration of audio frames classified as containing speech by the voice activity detector. |

#### Audio Quality

| Metric                                       | Type          | Unit    | Description                                                                                                                                                                                                          |
| :------------------------------------------- | :------------ | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `experimental.audio.input_clipping_samples`  | Counter (u64) | samples | Cumulative number of input samples whose absolute value reached or exceeded 1.0 (full-scale clipping). Lower is better; sustained values indicate bad hardware or encoding upstream.                                 |
| `experimental.audio.output_clipping_samples` | Counter (u64) | samples | Cumulative number of output samples whose absolute value reached or exceeded 1.0 after enhancement. Lower is better.                                                                                                 |
| `experimental.audio.snr`                     | Gauge (f64)   | dB      | Signal-to-noise ratio of the enhanced audio over the last export interval. Computed as $10 \log_{10} \left( \frac{\text{signal\_power}}{\text{noise\_power}} \right)$. Higher is better. Not reported during bypass. |

## Deployment Examples

<Tabs>
  <Tab title="Grafana">
    Point the SDK at a [Grafana Alloy](https://grafana.com/docs/alloy/) instance or an [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) that forwards to Grafana Mimir.

    ```bash theme={null}
    export AIC_SDK_OTEL_ENABLE=1
    export OTEL_EXPORTER_OTLP_ENDPOINT="http://alloy.internal:4318"
    ```
  </Tab>

  <Tab title="Datadog">
    The [Datadog Agent](https://docs.datadoghq.com/opentelemetry/otlp_ingest_in_the_agent/) accepts OTLP metrics on port 4318 when OTLP ingest is enabled.

    ```bash theme={null}
    export AIC_SDK_OTEL_ENABLE=1
    export OTEL_EXPORTER_OTLP_ENDPOINT="http://datadog-agent:4318"
    ```

    Enable OTLP ingest in your Datadog Agent configuration:

    ```yaml theme={null}
    # datadog.yaml
    otlp_config:
      receiver:
        protocols:
          http:
            endpoint: 0.0.0.0:4318
    ```
  </Tab>

  <Tab title="New Relic">
    Send metrics directly to the [New Relic OTLP endpoint](https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp/).

    ```bash theme={null}
    export AIC_SDK_OTEL_ENABLE=1
    export OTEL_EXPORTER_OTLP_ENDPOINT="https://otlp.nr-data.net:4318"
    export OTEL_EXPORTER_OTLP_HEADERS="api-key=YOUR_NEW_RELIC_LICENSE_KEY"
    ```
  </Tab>

  <Tab title="OTel Collector">
    Use a standard [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) with an OTLP receiver and your preferred exporter.

    ```bash theme={null}
    export AIC_SDK_OTEL_ENABLE=1
    export OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-collector:4318"
    ```

    Minimal Collector configuration:

    ```yaml theme={null}
    # otel-collector-config.yaml
    receivers:
      otlp:
        protocols:
          http:
            endpoint: 0.0.0.0:4318

    exporters:
      # Configure your preferred backend here
      debug:
        verbosity: detailed

    service:
      pipelines:
        metrics:
          receivers: [otlp]
          exporters: [debug]
    ```
  </Tab>
</Tabs>

## Runtime Behavior

* The OTel pipeline is process-wide: concurrent SDK sessions share one exporter pipeline.
* Metric observations remain session-specific via attributes such as `session.id`, `api.key`, `sdk.version`, and `model.id`.
* If your collector is unreachable, export attempts for that interval fail and are dropped by the OTel exporter. Audio processing continues.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Metrics are not appearing in my backend">
    1. Verify that `AIC_SDK_OTEL_ENABLE=1` is set in the environment where the SDK runs.
    2. Confirm `OTEL_EXPORTER_OTLP_ENDPOINT` points to a reachable OTLP endpoint.
    3. Check firewall rules and network connectivity between your application and the collector.
  </Accordion>

  <Accordion title="How often are metrics exported?">
    Metrics are exported according to the `export_interval_ms` field on `AicOtelConfig` (default: 60s when set to `0`).
  </Accordion>

  <Accordion title="What is the exporter timeout?">
    The export timeout is controlled by `OTEL_METRIC_EXPORT_TIMEOUT` (default: 30s).
  </Accordion>
</AccordionGroup>
