UNPKG

autotel

Version:
208 lines (206 loc) 7.86 kB
/** * Event Subscriber Interface (Type-only) * * Import this interface to create custom subscribers without importing implementations. * Keeps core package focused on OpenTelemetry with zero extra dependencies. * * For ready-made subscribers (PostHog, Mixpanel, Amplitude, Segment), * see the separate `autotel-subscribers` package. * * @example Custom subscriber * ```typescript * import { EventSubscriber } from 'autotel/event-subscriber'; * * class MyCustomSubscriber implements EventSubscriber { * trackEvent(name: string, attributes?: Record<string, any>): void { * // Send to your events platform * } * // ... implement other methods * } * ``` * * @example Use pre-built subscribers * ```typescript * import { Events } from 'autotel/events'; * import { PostHogSubscriber } from 'autotel-subscribers/posthog'; * import { MixpanelSubscriber } from 'autotel-subscribers/mixpanel'; * * const event =new Event('checkout', { * subscribers: [ * new PostHogSubscriber({ apiKey: 'phc_...' }), * new MixpanelSubscriber({ token: '...' }) * ] * }); * ``` */ /** * Event attributes (supports any JSON-serializable values) * * Allows primitive types for flat attributes and unknown for flexibility * with nested objects when using subscribers that support JSON payloads * (e.g., WebhookSubscriber). */ type EventAttributes = Record<string, unknown>; /** * Permissive input type for event attributes * * Accepts undefined/null values which will be filtered out before sending. * This improves DX when working with optional properties from objects. * * @example * ```typescript * // No need to filter out undefined values manually * event.trackEvent('user.action', { * userId: user.id, * email: user.email, // might be undefined * plan: user.subscription, // might be null * }); * ``` */ type EventAttributesInput = Record<string, string | number | boolean | undefined | null>; /** * Funnel step status */ type FunnelStatus = 'started' | 'completed' | 'abandoned' | 'failed'; /** * Outcome status */ type OutcomeStatus = 'success' | 'failure' | 'partial'; /** * Autotel event context for trace correlation * * This structured object contains trace context and correlation IDs. * Subscribers decide how to map/flatten these for their platform. */ interface AutotelEventContext { /** Trace ID (32 hex chars) - present when inside a trace */ trace_id?: string; /** Span ID (16 hex chars) - present when inside a span */ span_id?: string; /** Trace flags (2 hex chars, e.g., '01' for sampled) */ trace_flags?: string; /** Raw tracestate string - present if tracestate exists */ trace_state?: string; /** Clickable trace URL - present if traceUrl config is set */ trace_url?: string; /** Correlation ID (always present, 16 hex chars) */ correlation_id: string; /** Number of linked parent traces (batch/fan-in scenarios) */ linked_trace_id_count?: number; /** Stable hash of linked trace IDs (default for batch/fan-in) */ linked_trace_id_hash?: string; /** Full array of linked trace IDs (only if includeLinkedTraceIds: true) */ linked_trace_ids?: string[]; } /** * Options for event tracking methods */ interface EventTrackingOptions { /** Autotel trace context to include in the event */ autotel?: AutotelEventContext; } /** * Event subscriber interface * * Implement this to send events to any platform. * Zero runtime dependencies - just types. * * All tracking methods are async to support: * - Backpressure signaling (buffer full) * - Streaming platforms (Kafka, Kinesis, Pub/Sub) * - Await delivery confirmation * - Proper error propagation */ interface EventSubscriber { /** * Track an event (e.g., "user.registered", "order.created") * * @param name - Event name * @param attributes - Optional event attributes * @param options - Optional tracking options including autotel context * @returns Promise that resolves when event is sent (or buffered) */ trackEvent(name: string, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>; /** * Track a funnel step (e.g., checkout: started → completed) * * @param funnelName - Funnel name * @param step - Funnel step status * @param attributes - Optional event attributes * @param options - Optional tracking options including autotel context * @returns Promise that resolves when event is sent (or buffered) */ trackFunnelStep(funnelName: string, step: FunnelStatus, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>; /** * Track an outcome (e.g., "payment.processing" → success/failure) * * @param operationName - Operation name * @param outcome - Outcome status * @param attributes - Optional event attributes * @param options - Optional tracking options including autotel context * @returns Promise that resolves when event is sent (or buffered) */ trackOutcome(operationName: string, outcome: OutcomeStatus, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>; /** * Track a value/metric (e.g., revenue, cart value) * * @param name - Metric name * @param value - Numeric value * @param attributes - Optional event attributes * @param options - Optional tracking options including autotel context * @returns Promise that resolves when event is sent (or buffered) */ trackValue(name: string, value: number, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>; /** * Track funnel progression with custom step names * * Unlike trackFunnelStep which uses FunnelStatus enum values, * this method allows any string as the step name for flexible funnel tracking. * * @param funnelName - Name of the funnel (e.g., "checkout", "onboarding") * @param stepName - Custom step name (e.g., "cart_viewed", "payment_entered") * @param stepNumber - Optional numeric position in the funnel * @param attributes - Optional event attributes * @param options - Optional tracking options including autotel context * * @example * ```typescript * // Track custom checkout steps * await subscriber.trackFunnelProgression('checkout', 'cart_viewed', 1); * await subscriber.trackFunnelProgression('checkout', 'shipping_selected', 2); * await subscriber.trackFunnelProgression('checkout', 'payment_entered', 3); * await subscriber.trackFunnelProgression('checkout', 'order_confirmed', 4); * ``` */ trackFunnelProgression?(funnelName: string, stepName: string, stepNumber?: number, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>; /** * Optional: Flush pending events and clean up resources * * Implement this if your subscriber buffers events, maintains connections, * or needs cleanup before shutdown. Called during graceful shutdown. * * @example * ```typescript * class MySubscriber implements EventSubscriber { * async shutdown(): Promise<void> { * await this.flushBuffer(); * await this.closeConnections(); * } * } * ``` */ shutdown?(): Promise<void>; /** * Optional: Subscriber name for debugging and error reporting * * @example "PostHogSubscriber", "SnowflakeSubscriber", "CustomWebhookSubscriber" */ readonly name?: string; /** * Optional: Subscriber version for debugging * * @example "1.0.0" */ readonly version?: string; } export type { AutotelEventContext, EventAttributes, EventAttributesInput, EventSubscriber, EventTrackingOptions, FunnelStatus, OutcomeStatus };