# Integrating OpenTelemetry

This guide explains how to use EventSourcingDB with **OpenTelemetry tracing**. It covers how to propagate trace context via CloudEvents, how EventSourcingDB handles that context, and what constraints apply.

## Overview

EventSourcingDB supports **[OpenTelemetry](https://opentelemetry.io/) trace context propagation** using the **[CloudEvents Distributed Tracing extension](https://github.com/cloudevents/spec/blob/v1.0.1/extensions/distributed-tracing.md)**. This allows events to carry trace information for **distributed tracing across systems**.

*(Changed in 1.3)* EventSourcingDB **does not generate or modify tracing data**. It simply **validates**, **stores**, and **returns** the trace context provided by the client.

## Using Trace Context

To associate trace context with an event, add the **`traceparent` field** at the top level of the event. You may also include the **optional `tracestate` field**. Both fields must appear at the top level of the event, not inside `data`:

```json
{
  // ...
  "data": {
    // ...
  },
  "traceparent": "00-eb0e08452e7ee4b0d3b8b30987c37951-c31bc0a7013beab8-00",
  "tracestate": "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE"
}
```

Trace context is **entirely optional**. If `traceparent` is omitted, the event is accepted without tracing metadata. However, **if `tracestate` is included, `traceparent` must also be set**. Both fields are strictly validated for correct syntax before an event is accepted.

### Trace Context Format

The **`traceparent` field** must conform to the **[W3C Trace Context specification](https://www.w3.org/TR/trace-context/)**:

```text
<version>-<trace-id>-<span-id>-<trace-flags>
```

- *(Changed in 1.3)* **Version**: 2 hex digits (must be `00`)
- **Trace ID**: 32 lowercase hex digits (16 bytes), not all zeros
- **Span ID**: 16 lowercase hex digits (8 bytes), not all zeros
- *(Changed in 1.3)* **Trace Flags**: 2 hex digits (must be `00` or `01`)

The **`tracestate` field** must be a **comma-separated list of key-value pairs**, with **at most 32 pairs** and **each key at most once**:

- *(Changed in 1.3)* **Keys**: up to 256 lowercase letters, digits, `_`, and `-`, starting with a letter, or a multi-tenant key of the form `tenant@system`
- **Values**: up to 256 letters, digits, `.`, `_`, and `-`

> **What Do `rojo` and `congo` Mean?**
>
> These are **example vendor keys** from the W3C spec, demonstrating how multiple telemetry systems can share trace metadata. In real applications, you'd use identifiers relevant to your tracing backend (e.g., `datadog=...`, `vendorX=...`).

## Reading and Observing Trace Context

*(Changed in 1.3)* When events are read or observed, any `traceparent` and `tracestate` values are **returned exactly as stored** – unmodified and in their original form. This allows downstream systems or analysis tools to **follow the trace across service boundaries**.

```json
{
  // ...
  "data": {
    // ...
  },
  "traceparent": "00-eb0e08452e7ee4b0d3b8b30987c37951-c31bc0a7013beab8-00",
  "tracestate": "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE"
}
```

## Best Practices

- **Always set `traceparent`** when emitting events from a traced operation
- **Use `tracestate` only if needed** by your telemetry backend
- **Validate trace context** before writing events
- Use tools like **[Jaeger](https://www.jaegertracing.io/)** or **[Grafana Tempo](https://grafana.com/oss/tempo/)** to **visualize traces** across services

Propagating trace context through events enables end-to-end observability – even in **asynchronous, decoupled architectures**.
