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

# Spans

> Timing and nesting units of work within a trace

## What are Spans?

A **span** represents a single unit of work within a trace — an operation with a start, an end, and a status. Where [events](/concepts/events) are instantaneous milestones, spans have a **duration** and can **nest**, letting you break a trace into a tree of sub-operations (for example `quote → approve → swap`).

Spans follow the same shape as OpenTelemetry spans: a name, start and end time, optional attributes, and a terminal status (`OK`, `ERROR`, or unset).

## Opening a Span

Use `trace.startSpan()` to open a span and `span.end()` to close it:

```typescript theme={null}
const span = trace.startSpan('swap_quote', {
  attributes: { dex: 'uniswap', pair: 'ETH/USDC' }
});

// ... do work ...

span.end({ status: 'OK' });
```

`startSpan()` returns a [`Span`](/api-reference/span) handle immediately. The span id is a W3C Trace Context span id (16 lowercase hex characters), available as `span.id`.

## The `span()` Wrapper

For the common case, `trace.span(name, fn)` opens a span, runs your function, and ends the span automatically — with status `OK` if it returns, or `ERROR` (plus the error message) if it throws. It works with both sync and async functions and returns whatever your function returns:

```typescript theme={null}
const quote = await trace.span('fetch_quote', async (span) => {
  span.setAttribute('amountIn', '1.5');
  const q = await getQuote();
  span.addEvent('quote_received', { price: q.price });
  return q;
});
```

If `getQuote()` throws, the span is ended with `ERROR` and the error is re-thrown — you don't need a `try/catch` just to record the failure.

## Nesting Spans

Open a child span from a parent to build a tree of work:

```typescript theme={null}
await trace.span('checkout', async (checkout) => {
  await trace.span('validate', async () => { /* ... */ });

  const charge = checkout.startSpan('charge');
  await chargeCard();
  charge.end({ status: 'OK' });
});
```

A span opened via `trace.startSpan()` is parented to the innermost span that is currently open (or becomes a root of the trace when none is). Override the parent explicitly with `parentSpanId`:

```typescript theme={null}
const child = trace.startSpan('retry', { parentSpanId: parent.id });
```

## Events Under a Span

Events recorded while a span is open nest under it in the trace timeline. There are two ways to record them:

```typescript theme={null}
const span = trace.startSpan('upload');

// 1. Explicit — always attaches to this span (recommended, async-safe)
span.info('chunk_sent', { index: 0 });

// 2. Ambient — trace-level calls attach to the innermost open span
trace.info('progress', { pct: 50 });   // nests under 'upload'

span.end();
trace.info('done');   // no open span → trace-level
```

<Note>
  Ambient nesting is reliable for synchronous code. In concurrent async code the "active span" is shared per-trace, so prefer the span's own methods (`span.info()`, `span.addEvent()`) for precise attribution.
</Note>

## Span Status

End a span with an OTLP-style status:

| Status  | Meaning                                       |
| ------- | --------------------------------------------- |
| `OK`    | The operation completed successfully          |
| `ERROR` | The operation failed (pair with a `message`)  |
| `UNSET` | No explicit status — the default when omitted |

```typescript theme={null}
span.end();                                          // UNSET
span.end({ status: 'OK' });
span.end({ status: 'ERROR', message: 'quote timed out' });
```

The `span()` wrapper sets these for you: `OK` on return, `ERROR` plus the error message on throw.

## Span Attributes

Because a span's attributes are sent when the span opens, set them at creation or synchronously right after — before the span first flushes:

```typescript theme={null}
const span = trace.startSpan('swap', { attributes: { dex: 'uniswap' } });
span.setAttribute('amountIn', '1.5');
```

## Spans vs. Events

|         | Events                           | Spans                                 |
| ------- | -------------------------------- | ------------------------------------- |
| Shape   | A point in time                  | A duration (start → end)              |
| Nesting | Flat (can attach to a span)      | Tree (parent/child)                   |
| Status  | Severity (`info`/`warn`/`error`) | `OK` / `ERROR` / `UNSET`              |
| Use for | Milestones, state changes        | Operations you want to time and group |

Reach for a span when you want to time an operation or group related work; reach for an [event](/concepts/events) to mark a moment within it.

## Next Steps

<CardGroup cols={2}>
  <Card title="Span (API)" icon="code" href="/api-reference/span">
    Full Span class reference
  </Card>

  <Card title="Events" icon="flag" href="/concepts/events">
    Instantaneous milestones
  </Card>
</CardGroup>
