# `Continuum.OpenTelemetry`
[🔗](https://github.com/Yyeger/Continuum/blob/main/lib/continuum/open_telemetry.ex#L1)

Optional OpenTelemetry bridge for Continuum telemetry events.

Continuum does not depend on OpenTelemetry. Applications that already use
OpenTelemetry can add the `:opentelemetry` and `:opentelemetry_api` packages,
configure their exporter, and call `setup/1` from their application startup.

    {:ok, _handler_id} = Continuum.OpenTelemetry.setup()

The bridge turns existing `[:continuum, ...]` telemetry events into short
spans:

  * a `continuum.run_attempt` span for each engine attempt, closed when the
    run suspends, completes, fails, is cancelled, or loses its lease
  * a `continuum.activity_attempt` span for each activity attempt, closed
    when the activity completes, fails, or is retried
  * a `continuum.compensation_attempt` span for each compensation attempt,
    closed when the compensation completes or fails

Child-workflow and `continue_as_new` events are recorded as breadcrumbs on the
parent/originating run-attempt span; a child's own execution is already
captured by its own `continuum.run_attempt` spans, correlated by run id.

Run-attempt spans always include `continuum.run_id`. When the run metadata
contains a persisted W3C `traceparent`, the span also gets a link to that
original trace context so resumed attempts can be correlated across process
and VM restarts.

In durable Postgres mode, activity attempts run in worker processes after the
engine attempt has suspended. Those activity spans are usually sibling roots
correlated by `continuum.run_id`, not children of the run-attempt span.

# `handler_id`

```elixir
@type handler_id() :: term()
```

Handler id returned by `setup/1` and accepted by `detach/1`.

# `detach`

```elixir
@spec detach(handler_id()) :: :ok | {:error, :not_found}
```

Detaches a bridge installed by `setup/1`.

# `setup`

```elixir
@spec setup(keyword()) :: {:ok, handler_id()} | {:error, term()}
```

Attaches the OpenTelemetry bridge to Continuum telemetry events.

By default this expects `:opentelemetry` and `:opentelemetry_api` to be loaded
by the host application. If they are not available, returns
`{:error, :opentelemetry_not_loaded}` and does not attach handlers.

Options:

  * `:handler_id` - telemetry handler id. Defaults to a stable Continuum id.
  * `:tracer` - internal testing hook. Production callers should leave this
    unset so the real OpenTelemetry API is used.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
