import type { Middleware } from "../types.mjs"; /** Minimal OpenTelemetry \`Tracer\` surface we need — matches * \`@opentelemetry/api\` but typed locally so the middleware doesn't * require the peer at build time. */ export interface OtelTracer { startActiveSpan: (name: string, options: { attributes?: Record; }, fn: (span: OtelSpan) => T | Promise) => T | Promise; } export interface OtelSpan { setAttribute: (key: string, value: unknown) => void; recordException: (err: unknown) => void; setStatus: (status: { code: 1 | 2; message?: string; }) => void; end: () => void; } export interface TelemetryOptions { /** Tracer to drive. Usually \`trace.getTracer("unemail")\` from * \`@opentelemetry/api\`. When omitted the middleware is a no-op. */ tracer?: OtelTracer; /** Sampling hook — return \`false\` to skip span creation for a given * send (useful to avoid tracing health-check emails). */ sample?: (attributes: Record) => boolean; } /** Middleware that wraps each send in an OpenTelemetry span. * * ```ts * import { trace } from "@opentelemetry/api" * email.use(withTelemetry({ tracer: trace.getTracer("unemail") })) * ``` * * Attributes emitted: * - \`email.driver\`, \`email.stream\`, \`email.attempt\` * - \`email.to\`, \`email.subject.length\` * - \`email.message_id\` (set on success) * - \`email.error.code\` (set on failure) * * The full recipient is emitted — strip it by wrapping \`tracer\` yourself * if you have stricter PII rules. */ export declare function withTelemetry(options?: TelemetryOptions): Middleware;