# `@lazarv/react-server/telemetry`

OpenTelemetry integration. Safe no-op when OpenTelemetry packages are not installed — import `getTracer`, `getMeter`, `withSpan`, and friends directly without guarding.

## Functions

### `getMeter`

```ts
function getMeter(): Meter;
```

Get the active OpenTelemetry meter.
Returns a no-op meter when telemetry is disabled.

### `getMetrics`

```ts
function getMetrics(): {
    httpRequestDuration: {
        record(value: number, attributes?: Record<string, string | number>): void;
    };
    httpActiveRequests: {
        add(value: number, attributes?: Record<string, string | number>): void;
    };
    rscRenderDuration: {
        record(value: number, attributes?: Record<string, string | number>): void;
    };
    domRenderDuration: {
        record(value: number, attributes?: Record<string, string | number>): void;
    };
    actionDuration: {
        record(value: number, attributes?: Record<string, string | number>): void;
    };
    cacheHits: {
        add(value: number, attributes?: Record<string, string | number>): void;
    };
    cacheMisses: {
        add(value: number, attributes?: Record<string, string | number>): void;
    };
} | null;
```

Built-in metrics instruments. Returns `null` when telemetry is disabled.

### `getOtelContext`

```ts
function getOtelContext(): Context | null;
```

Get the OTel context for the current request.

### `getSpan`

```ts
function getSpan(): Span;
```

Get the current request span from the per-request context.
Returns a no-op span when telemetry is disabled or called outside a request.

### `getTracer`

```ts
function getTracer(): Tracer;
```

Get the active OpenTelemetry tracer.
Returns a no-op tracer when telemetry is disabled.

### `injectTraceContext`

```ts
function injectTraceContext(headers: Headers): Promise<void>;
```

Inject W3C trace context into outgoing response headers.
Useful when making downstream HTTP calls that should be correlated.

### `withSpan`

```ts
function withSpan<T>(name: string, fn: (span: Span) => Promise<T> | T): Promise<T>;
function withSpan<T>(name: string, attributes: Record<string, string | number | boolean>, fn: (span: Span) => Promise<T> | T): Promise<T>;
```

Execute `fn` within a child span of the current request span.

**Parameters**

- `name` — Span name
- `fn` — Function to execute inside the span

**Returns** — The return value of `fn`

```ts
import { withSpan } from "@lazarv/react-server/telemetry";

const result = await withSpan("db.query", async (span) => {
  span.setAttribute("db.system", "postgres");
  return await db.query("SELECT ...");
});
```

## Interfaces

### `Meter`

```ts
interface Meter {
    createCounter(name: string, options?: unknown): {
        add(value: number, attributes?: Record<string, unknown>): void;
    };
    createHistogram(name: string, options?: unknown): {
        record(value: number, attributes?: Record<string, unknown>): void;
    };
    createUpDownCounter(name: string, options?: unknown): {
        add(value: number, attributes?: Record<string, unknown>): void;
    };
}
```

Minimal Meter interface compatible with

### `Span`

```ts
interface Span {
    setAttribute(key: string, value: unknown): Span;
    setAttributes(attributes: Record<string, unknown>): Span;
    addEvent(name: string, attributes?: Record<string, unknown>): Span;
    setStatus(status: {
        code: number;
        message?: string;
    }): Span;
    recordException(exception: unknown): void;
    end(): void;
    isRecording(): boolean;
    spanContext(): {
        traceId: string;
        spanId: string;
        traceFlags: number;
    };
    updateName(name: string): Span;
}
```

Minimal Span interface compatible with

### `Tracer`

```ts
interface Tracer {
    startSpan(name: string, options?: unknown, context?: unknown): Span;
    startActiveSpan<F extends (span: Span) => unknown>(name: string, fn: F): ReturnType<F>;
}
```

Minimal Tracer interface compatible with

## Types

### `Context`

```ts
type Context = unknown;
```

OTel context — opaque type.
