autotel
Version:
Write Once, Observe Anywhere
201 lines (197 loc) • 7.29 kB
TypeScript
import { SpanStatusCode, TimeInput, Link, BaggageEntry } from '@opentelemetry/api';
/**
* Trace context types and utilities
*/
/**
* Base trace context containing trace identifiers
*/
interface TraceContextBase {
traceId: string;
spanId: string;
correlationId: string;
}
/**
* Attribute value types following OpenTelemetry specification.
* Supports primitive values and arrays of homogeneous primitives.
*/
type AttributeValue = string | number | boolean | string[] | number[] | boolean[];
/**
* Span methods available on trace context
*/
interface SpanMethods {
/** Set a single attribute on the span */
setAttribute(key: string, value: AttributeValue): void;
/** Set multiple attributes on the span */
setAttributes(attrs: Record<string, AttributeValue>): void;
/** Set the status of the span */
setStatus(status: {
code: SpanStatusCode;
message?: string;
}): void;
/** Record an exception on the span */
recordException(exception: Error, time?: TimeInput): void;
/** Add an event to the span (for logging milestones/checkpoints) */
addEvent(name: string, attributesOrStartTime?: Record<string, AttributeValue> | TimeInput, startTime?: TimeInput): void;
/** Add a link to another span */
addLink(link: Link): void;
/** Add multiple links to other spans */
addLinks(links: Link[]): void;
/** Update the span name dynamically */
updateName(name: string): void;
/** Check if the span is recording */
isRecording(): boolean;
}
/**
* Baggage methods available on trace context
*
* @template TBaggage - Optional type for typed baggage (defaults to undefined for untyped)
*/
interface BaggageMethods<TBaggage extends Record<string, unknown> | undefined = undefined> {
/**
* Get a baggage entry by key
* @param key - Baggage key
* @returns Baggage entry value or undefined
*/
getBaggage(key: string): string | undefined;
/**
* Set a baggage entry
*
* Note: OpenTelemetry contexts are immutable. For proper scoping across async
* boundaries, use withBaggage() instead. This method updates baggage in the
* current context which may not propagate to all child operations.
*
* @param key - Baggage key
* @param value - Baggage value
* @returns The baggage value that was set (for chaining)
*
* @example Using withBaggage() (recommended)
* ```typescript
* await withBaggage({ baggage: { 'key': 'value' }, fn: async () => {
* // Baggage is available here and in child spans
* });
* ```
*/
setBaggage(key: string, value: string): string;
/**
* Delete a baggage entry
*
* Note: OpenTelemetry contexts are immutable. For proper scoping across async
* boundaries, use withBaggage() with only the entries you want instead.
*
* @param key - Baggage key
*/
deleteBaggage(key: string): void;
/**
* Get all baggage entries
* @returns Map of all baggage entries
*/
getAllBaggage(): Map<string, BaggageEntry>;
/**
* Get typed baggage (only available when TBaggage is defined)
* This is used internally by defineBaggageSchema()
*
* @internal
*/
getTypedBaggage?: TBaggage extends Record<string, unknown> ? <T extends TBaggage>(namespace?: string) => Partial<T> | undefined : never;
/**
* Set typed baggage (only available when TBaggage is defined)
* This is used internally by defineBaggageSchema()
*
* @internal
*/
setTypedBaggage?: TBaggage extends Record<string, unknown> ? <T extends TBaggage>(namespace: string | undefined, value: Partial<T>) => void : never;
}
/**
* Complete trace context that merges base context, span methods, and baggage methods
*
* This is the ctx parameter passed to factory functions in trace().
* It provides access to trace IDs, span manipulation methods, and baggage operations.
*
* @template TBaggage - Optional type for typed baggage support
*
* @example Untyped (default)
* ```typescript
* export const handler = trace((ctx) => async () => {
* ctx.getBaggage('key'); // returns string | undefined
* });
* ```
*
* @example Typed baggage
* ```typescript
* type TenantBaggage = { tenantId: string; region?: string };
*
* export const handler = trace<TenantBaggage>((ctx) => async () => {
* // Use typed schema helper for type-safe access
* const schema = defineBaggageSchema<TenantBaggage>('tenant');
* const tenant = schema.get(ctx); // Partial<TenantBaggage> | undefined
* });
* ```
*/
type TraceContext<TBaggage extends Record<string, unknown> | undefined = undefined> = TraceContextBase & SpanMethods & BaggageMethods<TBaggage>;
/**
* Define a typed baggage schema for type-safe baggage operations
*
* This helper provides a type-safe API for working with baggage entries.
* The namespace parameter is optional and prefixes all keys to avoid collisions.
*
* @template T - The baggage schema type (all fields are treated as optional)
* @param namespace - Optional namespace to prefix baggage keys
*
* @example Basic usage
* ```typescript
* type TenantBaggage = { tenantId: string; region?: string };
* const tenantBaggage = defineBaggageSchema<TenantBaggage>('tenant');
*
* export const handler = trace<TenantBaggage>((ctx) => async () => {
* // Get typed baggage
* const tenant = tenantBaggage.get(ctx);
* if (tenant?.tenantId) {
* console.log('Tenant:', tenant.tenantId);
* }
*
* // Set typed baggage
* tenantBaggage.set(ctx, { tenantId: 't1', region: 'us-east-1' });
* });
* ```
*
* @example With withBaggage helper
* ```typescript
* const tenantBaggage = defineBaggageSchema<TenantBaggage>('tenant');
*
* export const handler = trace<TenantBaggage>((ctx) => async () => {
* return await tenantBaggage.with(ctx, { tenantId: 't1' }, async () => {
* // Baggage is available here and in child spans
* const tenant = tenantBaggage.get(ctx);
* });
* });
* ```
*/
declare function defineBaggageSchema<T extends Record<string, unknown>>(namespace?: string): {
/**
* Get typed baggage from context
* @param ctx - Trace context
* @returns Partial baggage object or undefined if no baggage is set
*/
get: (ctx: TraceContext<T>) => Partial<T> | undefined;
/**
* Set typed baggage in context
*
* Note: For proper scoping across async boundaries, use the `with` method instead
*
* @param ctx - Trace context
* @param value - Partial baggage object to set
*/
set: (ctx: TraceContext<T>, value: Partial<T>) => void;
/**
* Run a function with typed baggage properly scoped
*
* This is the recommended way to set baggage as it ensures proper
* scoping across async boundaries.
*
* @param ctx - Trace context (can be omitted, will use active context)
* @param value - Partial baggage object to set
* @param fn - Function to execute with the baggage
*/
with: <R>(ctxOrValue: TraceContext<T> | Partial<T>, valueOrFn: Partial<T> | (() => R | Promise<R>), maybeFn?: () => R | Promise<R>) => R | Promise<R>;
};
export { type AttributeValue as A, type TraceContext as T, defineBaggageSchema as d };