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

# OpenTelemetry

> Learn how to export OpenTelemetry data to Openlayer

<img width="700" style={{ borderRadius: "0.5rem" }} src="https://mintcdn.com/openlayer-docs/uFW8OPdLUePRsPDk/images/integrations/otel_hero.png?fit=max&auto=format&n=uFW8OPdLUePRsPDk&q=85&s=4d491689cdcf8db7c58f7d45e946666e" alt="OTel hero" data-path="images/integrations/otel_hero.png" />

[OpenTelemetry](https://opentelemetry.io/docs/) (OTel) is an open-source framework used to collect observability data.
It is widely used by frameworks like [Semantic Kernel](https://devblogs.microsoft.com/semantic-kernel/observability-in-semantic-kernel/),
[Vercel AI SDK](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry),
[Spring AI](https://docs.spring.io/spring-ai/reference/observability/index.html),
[Google Agent Development Kit (ADK)](/docs/integrations/google-adk), and others.

You can configure Openlayer as the backend for your OTel trace data. If you are already
using a framework that captures OTel traces, you can point it to [Openlayer’s OTel endpoint](#opentelemetry-endpoint) to export
traces and monitor your AI system.

## OpenTelemetry endpoint

Openlayer accepts OTel traces at the following endpoint: `https://api.openlayer.com/v1/otel`.
This endpoint uses the [OTLP protocol](https://opentelemetry.io/docs/specs/otel/protocol/) and expects telemetry data in **protobuf** format over **HTTPS**.
Request bodies may be sent uncompressed or compressed with **gzip** or **deflate**. Any other
`Content-Encoding`, such as `zstd`, is rejected with a `415` naming the encoding.

Most OTel-instrumented SDKs use this format by default, but be sure to check your SDK’s documentation
to confirm your setup.

To send OTel data to Openlayer, configure your SDK to use the endpoint above and include
the correct authentication headers. This is typically done using the environment variables shown below.

```bash theme={null}
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.openlayer.com/v1/otel
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer YOUR_OPENLAYER_API_KEY, x-bt-parent=pipeline_id:YOUR_OPENLAYER_PIPELINE_ID"
```

<Info>
  Some SDKs and exporters take a signal-specific setting instead of the base URL
  — for example `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`. Those need the full path:
  `https://api.openlayer.com/v1/otel/v1/traces`.
</Info>

## Using an OpenTelemetry Collector

If your traces already flow through an [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/),
export them to Openlayer with an `otlphttp` exporter:

```yaml theme={null}
exporters:
  otlphttp/openlayer:
    endpoint: https://api.openlayer.com/v1/otel
    headers:
      Authorization: "Bearer YOUR_OPENLAYER_API_KEY"
      x-bt-parent: "pipeline_id:YOUR_OPENLAYER_PIPELINE_ID"

service:
  pipelines:
    traces:
      exporters: [otlphttp/openlayer]
```

The exporter appends `/v1/traces` to `endpoint`, so give it the base URL above.
Leave `compression` unset: the exporter enables `gzip` by default and Openlayer
accepts it.

## Property mapping

When Openlayer receives OTel data, it transforms it into its own trace format.
This involves mapping properties from the [GenAI semantic convention](https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/)
and popular frameworks into Openlayer’s trace data model.

<Warning>
  The OTel GenAI semantic convention is still evolving. If an integration does
  not work as expected or if Openlayer does not parse all attributes correctly,
  please [reach out](mailto:support@openlayer.com).
</Warning>

## Sessions and users

Openlayer reads the `openlayer.session.id` and `openlayer.user.id` span attributes to
group traces into [sessions and users](/docs/monitoring/sessions-and-users). If your whole
request is traced in one process, setting the attributes on your root span is enough:

<CodeGroup>
  ```python Python theme={null}
  span.set_attribute("openlayer.session.id", session_id)
  span.set_attribute("openlayer.user.id", user_id)
  ```

  ```typescript TypeScript theme={null}
  span.setAttribute("openlayer.session.id", sessionId);
  span.setAttribute("openlayer.user.id", userId);
  ```
</CodeGroup>

To carry the IDs onto **every** span — including spans created by libraries and by other
services your app calls — use [W3C
Baggage](https://opentelemetry.io/docs/concepts/signals/baggage/) instead: set the IDs
once at the session boundary, and a `BaggageSpanProcessor` stamps them onto each span the
process creates. Instrumented HTTP clients forward baggage alongside `traceparent`, so
downstream services need no Openlayer-specific code.

<CodeGroup>
  ```python Python theme={null}
  from opentelemetry import baggage, context
  from opentelemetry.processor.baggage import BaggageSpanProcessor

  # When configuring your TracerProvider (pip install opentelemetry-processor-baggage):
  provider.add_span_processor(
      BaggageSpanProcessor(lambda key: key.startswith("openlayer."))
  )

  # At the session boundary, set the IDs once:
  ctx = baggage.set_baggage("openlayer.session.id", session_id)
  ctx = baggage.set_baggage("openlayer.user.id", user_id, context=ctx)
  token = context.attach(ctx)
  try:
      ...  # every span created here carries the session and user
  finally:
      context.detach(token)
  ```

  ```typescript TypeScript theme={null}
  import { context, propagation } from "@opentelemetry/api";
  import { BaggageSpanProcessor } from "@opentelemetry/baggage-span-processor";

  // When configuring your provider (npm install @opentelemetry/baggage-span-processor):
  new BaggageSpanProcessor((key) => key.startsWith("openlayer."));

  // At the session boundary, set the IDs once:
  const bag = propagation.createBaggage({
    "openlayer.session.id": { value: sessionId },
    "openlayer.user.id": { value: userId },
  });
  context.with(propagation.setBaggage(context.active(), bag), () => {
    // every span created here carries the session and user
  });
  ```
</CodeGroup>

<Warning>
  Baggage travels in plaintext HTTP headers to **every** downstream service the
  instrumented client calls — including third-party APIs. Filter which keys you
  propagate (the snippets above only copy `openlayer.*`) and keep sensitive
  values out of baggage.
</Warning>

## Distributed tracing across services

OpenTelemetry propagates trace context (the W3C `traceparent` header) across service
boundaries by default when both sides run instrumented HTTP clients and servers. For a
system of multiple traced services — for example, agents calling each other — you have
two options:

* **One pipeline for all services**: point every service's exporter at the same
  `x-bt-parent` pipeline, and their spans merge into a single trace that crosses process
  boundaries.
* **One project per service**: point each service at its own project's pipeline. With
  trace context propagating exactly as before, Openlayer promotes each service's part of
  the trace into a full record in its own project and links the records **directionally**
  — the caller's record shows a *Continues in …* chip and the callee's record shows a
  *Called from …* chip, each deep-linking to the other.

Links are **direct call edges only**: a service that fans out to several others gets one
chip per callee, and two services that merely share a trace without calling each other
are not linked. Lookups are always restricted to your workspace and the projects you can
access.

<Note>
  Per-project linking relies on remote-root promotion, which is enabled per
  workspace — reach out to your Openlayer contact to turn it on. For a complete
  worked example (including Google ADK agents), see the [A2A protocol
  integration](/docs/integrations/a2a-protocol#one-project-per-agent-linked-traces).
</Note>

## Libraries and frameworks with OpenTelemetry support

Any OpenTelemetry-compatible instrumentation can be used to export traces to Openlayer.

The libraries and frameworks below are already instrumented for OpenTelemetry and traces
can be exported to Openlayer.

Check out their dedicated integration guides to learn how to set it up:

* [OpenLLMetry](/docs/integrations/openllmetry)
* [OpenLIT](/docs/integrations/openlit)
* [Microsoft Agent Framework](/docs/integrations/microsoft-agent-framework)
* [Semantic Kernel](/docs/integrations/semantic-kernel)
* [Spring AI](/docs/integrations/spring-ai)
* [Pydantic AI](/docs/integrations/pydantic-ai)
* [Strands Agents](/docs/integrations/strands-agents)
* [Google Agent Development Kit (ADK)](/docs/integrations/google-adk)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.