iii-sdk 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{iii-7FpY7bi9.d.mts → iii-CAEmlG6f.d.mts} +18 -5
- package/dist/iii-CAEmlG6f.d.mts.map +1 -0
- package/dist/{iii-BhtLRYBs.d.cts → iii-DEbgvZtB.d.cts} +15 -2
- package/dist/iii-DEbgvZtB.d.cts.map +1 -0
- package/dist/index.cjs +9 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +9 -7
- package/dist/index.mjs.map +1 -1
- package/dist/{otel-worker-gauges-Dka1CFDy.mjs → otel-worker-gauges-CHooGOLC.mjs} +144 -12
- package/dist/otel-worker-gauges-CHooGOLC.mjs.map +1 -0
- package/dist/{otel-worker-gauges-8AUNGQgJ.cjs → otel-worker-gauges-CLZyxI1P.cjs} +137 -5
- package/dist/otel-worker-gauges-CLZyxI1P.cjs.map +1 -0
- package/dist/stream-Bzpo5JNV.d.mts.map +1 -1
- package/dist/telemetry.cjs +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.mts +1 -1
- package/dist/telemetry.mjs +1 -1
- package/package.json +1 -1
- package/tests/api-triggers.test.ts +163 -0
- package/tests/bridge.test.ts +84 -0
- package/tests/exports.test.ts +37 -0
- package/tests/fetch-instrumentation.test.ts +623 -0
- package/tests/fixtures/config-test.yaml +66 -0
- package/tests/healthcheck.test.ts +1 -2
- package/tests/kv-server.test.ts +82 -0
- package/tests/pubsub.test.ts +117 -0
- package/tests/setup.ts +2 -32
- package/tests/state.test.ts +1 -2
- package/tests/stream.test.ts +1 -2
- package/tests/utils.ts +2 -23
- package/dist/iii-7FpY7bi9.d.mts.map +0 -1
- package/dist/iii-BhtLRYBs.d.cts.map +0 -1
- package/dist/otel-worker-gauges-8AUNGQgJ.cjs.map +0 -1
- package/dist/otel-worker-gauges-Dka1CFDy.mjs.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["getOtelLogger","traceId?: string","serviceName?: string","spanId?: string","attributes: Record<string, string | undefined>","otelContext","address: string","fullTrigger: RegisterTriggerMessage","SeverityNumber","msgType: MessageType","message: Record<string, unknown>"],"sources":["../src/iii-types.ts","../src/logger.ts","../src/context.ts","../src/iii.ts"],"sourcesContent":["export enum MessageType {\n RegisterFunction = 'registerfunction',\n UnregisterFunction = 'unregisterfunction',\n RegisterService = 'registerservice',\n InvokeFunction = 'invokefunction',\n InvocationResult = 'invocationresult',\n RegisterTriggerType = 'registertriggertype',\n RegisterTrigger = 'registertrigger',\n UnregisterTrigger = 'unregistertrigger',\n UnregisterTriggerType = 'unregistertriggertype',\n TriggerRegistrationResult = 'triggerregistrationresult',\n WorkerRegistered = 'workerregistered',\n}\n\nexport type RegisterTriggerTypeMessage = {\n message_type: MessageType.RegisterTriggerType\n id: string\n description: string\n}\n\nexport type UnregisterTriggerTypeMessage = {\n message_type: MessageType.UnregisterTriggerType\n id: string\n}\n\nexport type UnregisterTriggerMessage = {\n message_type: MessageType.UnregisterTrigger\n id: string\n type?: string\n}\n\nexport type TriggerRegistrationResultMessage = {\n message_type: MessageType.TriggerRegistrationResult\n id: string\n type: string\n function_id: string\n result?: unknown\n error?: unknown\n}\n\nexport type RegisterTriggerMessage = {\n message_type: MessageType.RegisterTrigger\n id: string\n type: string\n function_id: string\n config: unknown\n}\n\nexport type RegisterServiceMessage = {\n message_type: MessageType.RegisterService\n id: string\n description?: string\n parent_service_id?: string\n}\n\nexport type RegisterFunctionFormat = {\n name: string\n /**\n * The description of the parameter\n */\n description?: string\n /**\n * The type of the parameter\n */\n type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'map'\n /**\n * The body of the parameter\n */\n body?: RegisterFunctionFormat[]\n /**\n * The items of the parameter\n */\n items?: RegisterFunctionFormat\n /**\n * Whether the parameter is required\n */\n required?: boolean\n}\n\nexport type RegisterFunctionMessage = {\n message_type: MessageType.RegisterFunction\n /**\n * The path of the function\n */\n id: string\n /**\n * The description of the function\n */\n description?: string\n /**\n * The request format of the function\n */\n request_format?: RegisterFunctionFormat\n /**\n * The response format of the function\n */\n response_format?: RegisterFunctionFormat\n metadata?: Record<string, unknown>\n}\n\nexport type InvokeFunctionMessage = {\n message_type: MessageType.InvokeFunction\n /**\n * This is optional for async invocations\n */\n invocation_id?: string\n /**\n * The path of the function\n */\n function_id: string\n /**\n * The data to pass to the function\n */\n data: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n}\n\nexport type InvocationResultMessage = {\n message_type: MessageType.InvocationResult\n /**\n * The id of the invocation\n */\n invocation_id: string\n /**\n * The path of the function\n */\n function_id: string\n result?: unknown\n error?: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n}\n\nexport type FunctionInfo = {\n function_id: string\n description?: string\n request_format?: RegisterFunctionFormat\n response_format?: RegisterFunctionFormat\n metadata?: Record<string, unknown>\n}\n\nexport type WorkerStatus = 'connected' | 'available' | 'busy' | 'disconnected'\n\nexport type WorkerInfo = {\n id: string\n name?: string\n runtime?: string\n version?: string\n os?: string\n ip_address?: string\n status: WorkerStatus\n connected_at_ms: number\n function_count: number\n functions: string[]\n active_invocations: number\n}\n\nexport type WorkerRegisteredMessage = {\n message_type: MessageType.WorkerRegistered\n worker_id: string\n}\n\nexport type UnregisterFunctionMessage = {\n message_type: MessageType.UnregisterFunction\n id: string\n}\n\nexport type IIIMessage =\n | RegisterFunctionMessage\n | UnregisterFunctionMessage\n | InvokeFunctionMessage\n | InvocationResultMessage\n | RegisterServiceMessage\n | RegisterTriggerMessage\n | RegisterTriggerTypeMessage\n | UnregisterTriggerMessage\n | UnregisterTriggerTypeMessage\n | TriggerRegistrationResultMessage\n | WorkerRegisteredMessage\n","import { SeverityNumber } from '@opentelemetry/api-logs'\nimport { getLogger as getOtelLogger } from './telemetry-system'\nimport { safeStringify } from './utils'\n\nexport type LoggerParams = {\n message: string\n trace_id?: string\n span_id?: string\n service_name?: string\n data?: unknown\n /** @deprecated Use service_name instead */\n function_name?: string\n}\n\nexport class Logger {\n private _otelLogger: ReturnType<typeof getOtelLogger> | null = null\n\n private get otelLogger() {\n // Lazy initialization: re-fetch logger if not yet available\n if (!this._otelLogger) {\n this._otelLogger = getOtelLogger()\n }\n return this._otelLogger\n }\n\n constructor(\n private readonly traceId?: string,\n private readonly serviceName?: string,\n private readonly spanId?: string,\n ) {}\n\n private emit(message: string, severity: SeverityNumber, data?: unknown): void {\n const attributes: Record<string, string | undefined> = {}\n\n if (this.traceId) {\n attributes.trace_id = this.traceId\n }\n if (this.spanId) {\n attributes.span_id = this.spanId\n }\n if (this.serviceName) {\n attributes['service.name'] = this.serviceName\n }\n if (data !== undefined) {\n attributes['log.data'] = typeof data === 'string' ? data : safeStringify(data)\n }\n\n if (this.otelLogger) {\n this.otelLogger.emit({\n severityNumber: severity,\n body: message,\n attributes: Object.keys(attributes).length > 0 ? attributes : undefined,\n })\n } else {\n // Fallback to console when OTEL is not available\n switch (severity) {\n case SeverityNumber.DEBUG:\n console.debug(message, data)\n break\n case SeverityNumber.INFO:\n console.info(message, data)\n break\n case SeverityNumber.WARN:\n console.warn(message, data)\n break\n case SeverityNumber.ERROR:\n console.error(message, data)\n break\n default:\n console.log(message, data)\n }\n }\n }\n\n info(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.INFO, data)\n }\n\n warn(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.WARN, data)\n }\n\n error(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.ERROR, data)\n }\n\n debug(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.DEBUG, data)\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { Span } from '@opentelemetry/api'\nimport { context as otelContext } from '@opentelemetry/api'\nimport { Logger } from './logger'\n\nexport type Context = {\n logger: Logger\n /** The active OpenTelemetry span for adding custom attributes, events, etc. */\n trace?: Span\n}\n\nconst globalStorage = new AsyncLocalStorage<Context>()\n\nexport const withContext = async <T>(\n fn: (context: Context) => Promise<T>,\n ctx: Context,\n): Promise<T> => {\n // Capture the current OTel context before entering AsyncLocalStorage.run()\n // This preserves the OpenTelemetry trace context across async boundaries\n const currentOtelContext = otelContext.active()\n\n return globalStorage.run(ctx, async () => {\n // Restore the OTel context inside the run() scope\n // This ensures trace propagation works when handlers call iii.call\n return otelContext.with(currentOtelContext, async () => await fn(ctx))\n })\n}\n\nexport const getContext = (): Context => {\n const store = globalStorage.getStore()\n if (store) {\n return store\n }\n\n const logger = new Logger()\n\n return { logger }\n}\n","import { context } from '@opentelemetry/api'\nimport { createRequire } from 'node:module'\nimport * as os from 'node:os'\nimport { type Data, WebSocket } from 'ws'\nimport {\n type IIIConnectionState,\n type IIIReconnectionConfig,\n DEFAULT_BRIDGE_RECONNECTION_CONFIG,\n DEFAULT_INVOCATION_TIMEOUT_MS,\n EngineFunctions,\n EngineTriggers,\n} from './iii-constants'\nimport {\n type IIIMessage,\n type FunctionInfo,\n type InvocationResultMessage,\n type InvokeFunctionMessage,\n MessageType,\n type RegisterFunctionMessage,\n type RegisterServiceMessage,\n type RegisterTriggerMessage,\n type RegisterTriggerTypeMessage,\n type TriggerRegistrationResultMessage,\n type WorkerInfo,\n type WorkerRegisteredMessage,\n} from './iii-types'\nimport { withContext } from './context'\nimport { Logger } from './logger'\nimport type { IStream } from './stream'\nimport {\n currentSpanId,\n currentTraceId,\n extractContext,\n getLogger,\n getMeter,\n getTracer,\n injectBaggage,\n injectTraceparent,\n initOtel,\n shutdownOtel,\n SeverityNumber,\n SpanKind,\n withSpan,\n type OtelConfig,\n} from './telemetry-system'\nimport { registerWorkerGauges, stopWorkerGauges } from './otel-worker-gauges'\nimport type { TriggerHandler } from './triggers'\nimport type {\n ISdk,\n FunctionsAvailableCallback,\n Invocation,\n LogCallback,\n LogConfig,\n LogSeverityLevel,\n OtelLogEvent,\n RemoteFunctionData,\n RemoteFunctionHandler,\n RemoteTriggerTypeData,\n Trigger,\n FunctionRef,\n} from './types'\n\nconst require = createRequire(import.meta.url)\nconst { version: SDK_VERSION } = require('../package.json')\n\nfunction getOsInfo(): string {\n return `${os.platform()} ${os.release()} (${os.arch()})`\n}\n\nfunction getDefaultWorkerName(): string {\n return `${os.hostname()}:${process.pid}`\n}\n\n/** Callback type for connection state changes */\nexport type ConnectionStateCallback = (state: IIIConnectionState) => void\n\nexport type InitOptions = {\n workerName?: string\n enableMetricsReporting?: boolean\n /** Default timeout for function invocations in milliseconds */\n invocationTimeoutMs?: number\n /** Configuration for WebSocket reconnection behavior */\n reconnectionConfig?: Partial<IIIReconnectionConfig>\n /** OpenTelemetry configuration. OTel is initialized automatically by default.\n * Set `{ enabled: false }` or env `OTEL_ENABLED=false/0/no/off` to disable.\n * The engineWsUrl is set automatically from the III address. */\n otel?: Omit<OtelConfig, 'engineWsUrl'>\n}\n\nclass Sdk implements ISdk {\n private ws?: WebSocket\n private functions = new Map<string, RemoteFunctionData>()\n private services = new Map<string, Omit<RegisterServiceMessage, 'functions'>>()\n private invocations = new Map<string, Invocation & { timeout?: NodeJS.Timeout }>()\n private triggers = new Map<string, RegisterTriggerMessage>()\n private triggerTypes = new Map<string, RemoteTriggerTypeData>()\n private functionsAvailableCallbacks = new Set<FunctionsAvailableCallback>()\n private functionsAvailableTrigger?: Trigger\n private functionsAvailableFunctionPath?: string\n private logCallbacks = new Map<LogCallback, LogConfig>()\n private logTrigger?: Trigger\n private logFunctionPath?: string\n private messagesToSend: Record<string, unknown>[] = []\n private workerName: string\n private workerId?: string\n private reconnectTimeout?: NodeJS.Timeout\n private metricsReportingEnabled: boolean\n private invocationTimeoutMs: number\n private reconnectionConfig: IIIReconnectionConfig\n private reconnectAttempt = 0\n private connectionState: IIIConnectionState = 'disconnected'\n private stateCallbacks = new Set<ConnectionStateCallback>()\n private isShuttingDown = false\n\n constructor(\n private readonly address: string,\n options?: InitOptions,\n ) {\n this.workerName = options?.workerName ?? getDefaultWorkerName()\n this.metricsReportingEnabled = options?.enableMetricsReporting ?? true\n this.invocationTimeoutMs = options?.invocationTimeoutMs ?? DEFAULT_INVOCATION_TIMEOUT_MS\n this.reconnectionConfig = {\n ...DEFAULT_BRIDGE_RECONNECTION_CONFIG,\n ...options?.reconnectionConfig,\n }\n\n // Initialize OpenTelemetry (enabled by default, opt-out via config or env)\n initOtel({ ...options?.otel, engineWsUrl: this.address })\n\n this.connect()\n }\n\n registerTriggerType = <TConfig>(\n triggerType: Omit<RegisterTriggerTypeMessage, 'message_type'>,\n handler: TriggerHandler<TConfig>,\n ): void => {\n this.sendMessage(MessageType.RegisterTriggerType, triggerType, true)\n this.triggerTypes.set(triggerType.id, {\n message: { ...triggerType, message_type: MessageType.RegisterTriggerType },\n handler,\n })\n }\n\n on = (event: string, callback: (arg?: unknown) => void): void => {\n this.ws?.on(event, callback)\n }\n\n unregisterTriggerType = (triggerType: Omit<RegisterTriggerTypeMessage, 'message_type'>): void => {\n this.sendMessage(MessageType.UnregisterTriggerType, triggerType, true)\n this.triggerTypes.delete(triggerType.id)\n }\n\n registerTrigger = (trigger: Omit<RegisterTriggerMessage, 'message_type' | 'id'>): Trigger => {\n const id = crypto.randomUUID()\n const fullTrigger: RegisterTriggerMessage = {\n ...trigger,\n id,\n message_type: MessageType.RegisterTrigger,\n }\n this.sendMessage(MessageType.RegisterTrigger, fullTrigger, true)\n this.triggers.set(id, fullTrigger)\n\n return {\n unregister: () => {\n this.sendMessage(MessageType.UnregisterTrigger, {\n id,\n message_type: MessageType.UnregisterTrigger,\n type: fullTrigger.type,\n })\n this.triggers.delete(id)\n },\n }\n }\n\n registerFunction = (\n message: Omit<RegisterFunctionMessage, 'message_type'>,\n handler: RemoteFunctionHandler,\n ): FunctionRef => {\n if (!message.id || message.id.trim() === '') {\n throw new Error('id is required')\n }\n\n this.sendMessage(MessageType.RegisterFunction, message, true)\n this.functions.set(message.id, {\n message: { ...message, message_type: MessageType.RegisterFunction },\n handler: async (input, traceparent?: string, baggage?: string) => {\n // If we have a tracer, wrap in a span and pass it to the context\n if (getTracer()) {\n // Extract both traceparent and baggage into a parent context\n const parentContext = extractContext(traceparent, baggage)\n\n return context.with(parentContext, () =>\n withSpan(`invoke ${message.id}`, { kind: SpanKind.SERVER }, async span => {\n const traceId = currentTraceId() ?? crypto.randomUUID()\n const spanId = currentSpanId()\n const logger = new Logger(traceId, message.id, spanId)\n const ctx = { logger, trace: span }\n\n return withContext(async () => await handler(input), ctx)\n }),\n )\n }\n\n // Fallback without tracing\n const traceId = crypto.randomUUID()\n const logger = new Logger(traceId, message.id)\n const ctx = { logger }\n\n return withContext(async () => await handler(input), ctx)\n },\n })\n\n return {\n id: message.id,\n unregister: () => {\n this.sendMessage(MessageType.UnregisterFunction, { id: message.id }, true)\n this.functions.delete(message.id)\n },\n }\n }\n\n registerService = (message: Omit<RegisterServiceMessage, 'message_type'>): void => {\n this.sendMessage(MessageType.RegisterService, message, true)\n this.services.set(message.id, { ...message, message_type: MessageType.RegisterService })\n }\n\n call = async <TInput, TOutput>(\n function_id: string,\n data: TInput,\n timeoutMs?: number,\n ): Promise<TOutput> => {\n const invocation_id = crypto.randomUUID()\n // Inject trace context and baggage if available\n const traceparent = injectTraceparent()\n const baggage = injectBaggage()\n const effectiveTimeout = timeoutMs ?? this.invocationTimeoutMs\n\n return new Promise<TOutput>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const invocation = this.invocations.get(invocation_id)\n if (invocation) {\n this.invocations.delete(invocation_id)\n reject(new Error(`Invocation timeout after ${effectiveTimeout}ms: ${function_id}`))\n }\n }, effectiveTimeout)\n\n this.invocations.set(invocation_id, {\n resolve: (result: TOutput) => {\n clearTimeout(timeout)\n resolve(result)\n },\n reject: (error: unknown) => {\n clearTimeout(timeout)\n reject(error)\n },\n timeout,\n })\n\n this.sendMessage(MessageType.InvokeFunction, {\n invocation_id,\n function_id,\n data,\n traceparent,\n baggage,\n })\n })\n }\n\n callVoid = <TInput>(function_id: string, data: TInput): void => {\n // Inject trace context and baggage if available\n const traceparent = injectTraceparent()\n const baggage = injectBaggage()\n this.sendMessage(MessageType.InvokeFunction, { function_id, data, traceparent, baggage })\n }\n\n listFunctions = async (): Promise<FunctionInfo[]> => {\n const result = await this.call<Record<string, never>, { functions: FunctionInfo[] }>(\n EngineFunctions.LIST_FUNCTIONS,\n {},\n )\n return result.functions\n }\n\n listWorkers = async (): Promise<WorkerInfo[]> => {\n const result = await this.call<Record<string, never>, { workers: WorkerInfo[] }>(\n EngineFunctions.LIST_WORKERS,\n {},\n )\n return result.workers\n }\n\n private registerWorkerMetadata(): void {\n this.callVoid(EngineFunctions.REGISTER_WORKER, {\n runtime: 'node',\n version: SDK_VERSION,\n name: this.workerName,\n os: getOsInfo(),\n })\n }\n\n createStream = <TData>(streamName: string, stream: IStream<TData>): void => {\n this.registerFunction({ id: `stream::get(${streamName})` }, stream.get.bind(stream))\n this.registerFunction({ id: `stream::set(${streamName})` }, stream.set.bind(stream))\n this.registerFunction({ id: `stream::delete(${streamName})` }, stream.delete.bind(stream))\n this.registerFunction({ id: `stream::list(${streamName})` }, stream.list.bind(stream))\n this.registerFunction(\n { id: `stream::list_groups(${streamName})` },\n stream.listGroups.bind(stream),\n )\n }\n\n onFunctionsAvailable = (callback: FunctionsAvailableCallback): (() => void) => {\n this.functionsAvailableCallbacks.add(callback)\n\n if (!this.functionsAvailableTrigger) {\n if (!this.functionsAvailableFunctionPath) {\n this.functionsAvailableFunctionPath = `engine.on_functions_available.${crypto.randomUUID()}`\n }\n\n const function_id = this.functionsAvailableFunctionPath\n if (!this.functions.has(function_id)) {\n this.registerFunction(\n { id: function_id },\n async ({ functions }: { functions: FunctionInfo[] }) => {\n this.functionsAvailableCallbacks.forEach(handler => {\n handler(functions)\n })\n return null\n },\n )\n }\n\n this.functionsAvailableTrigger = this.registerTrigger({\n type: EngineTriggers.FUNCTIONS_AVAILABLE,\n function_id,\n config: {},\n })\n }\n\n return () => {\n this.functionsAvailableCallbacks.delete(callback)\n if (this.functionsAvailableCallbacks.size === 0 && this.functionsAvailableTrigger) {\n this.functionsAvailableTrigger.unregister()\n this.functionsAvailableTrigger = undefined\n }\n }\n }\n\n onLog = (callback: LogCallback, config?: LogConfig): (() => void) => {\n const effectiveConfig = config ?? { level: 'all' }\n this.logCallbacks.set(callback, effectiveConfig)\n\n if (!this.logTrigger) {\n if (!this.logFunctionPath) {\n this.logFunctionPath = `engine.on_log.${crypto.randomUUID()}`\n }\n\n const function_id = this.logFunctionPath\n if (!this.functions.has(function_id)) {\n this.registerFunction({ id: function_id }, async (log: OtelLogEvent) => {\n this.logCallbacks.forEach((cfg, handler) => {\n try {\n const minSeverity = this.severityTextToNumber(cfg.level ?? 'all')\n if (cfg.level === 'all' || log.severity_number >= minSeverity) {\n handler(log)\n }\n } catch (error) {\n this.logError('Log callback handler threw an exception', error)\n }\n })\n return null\n })\n }\n\n this.logTrigger = this.registerTrigger({\n type: EngineTriggers.LOG,\n function_id,\n config: { level: 'all', severity_min: 0 },\n })\n }\n\n return () => {\n this.logCallbacks.delete(callback)\n if (this.logCallbacks.size === 0 && this.logTrigger) {\n this.logTrigger.unregister()\n this.logTrigger = undefined\n }\n }\n }\n\n /**\n * Get the current connection state.\n */\n getConnectionState = (): IIIConnectionState => {\n return this.connectionState\n }\n\n /**\n * Register a callback to be notified of connection state changes.\n * @returns A function to unregister the callback\n */\n onConnectionStateChange = (callback: ConnectionStateCallback): (() => void) => {\n this.stateCallbacks.add(callback)\n // Immediately notify of current state\n callback(this.connectionState)\n return () => this.stateCallbacks.delete(callback)\n }\n\n /**\n * Gracefully shutdown the iii, cleaning up all resources.\n */\n shutdown = async (): Promise<void> => {\n this.isShuttingDown = true\n\n this.stopMetricsReporting()\n\n // Shutdown OpenTelemetry\n await shutdownOtel()\n\n // Clear reconnection timeout\n this.clearReconnectTimeout()\n\n // Reject all pending invocations\n for (const [_id, invocation] of this.invocations) {\n if (invocation.timeout) {\n clearTimeout(invocation.timeout)\n }\n invocation.reject(new Error('iii is shutting down'))\n }\n this.invocations.clear()\n\n // Close WebSocket\n if (this.ws) {\n this.ws.removeAllListeners()\n this.ws.close()\n this.ws = undefined\n }\n\n // Clear callbacks\n this.stateCallbacks.clear()\n\n this.setConnectionState('disconnected')\n }\n\n // private methods\n\n private setConnectionState(state: IIIConnectionState): void {\n if (this.connectionState !== state) {\n this.connectionState = state\n for (const callback of this.stateCallbacks) {\n try {\n callback(state)\n } catch (error) {\n this.logError('Error in connection state callback', error)\n }\n }\n }\n }\n\n private connect(): void {\n if (this.isShuttingDown) {\n return\n }\n\n this.setConnectionState('connecting')\n this.ws = new WebSocket(this.address)\n this.ws.on('open', this.onSocketOpen.bind(this))\n this.ws.on('close', this.onSocketClose.bind(this))\n this.ws.on('error', this.onSocketError.bind(this))\n }\n\n private clearReconnectTimeout(): void {\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout)\n this.reconnectTimeout = undefined\n }\n }\n\n private scheduleReconnect(): void {\n if (this.isShuttingDown) {\n return\n }\n\n const { maxRetries, initialDelayMs, backoffMultiplier, maxDelayMs, jitterFactor } =\n this.reconnectionConfig\n\n if (maxRetries !== -1 && this.reconnectAttempt >= maxRetries) {\n this.setConnectionState('failed')\n this.logError(`Max reconnection retries (${maxRetries}) reached, giving up`)\n return\n }\n\n if (this.reconnectTimeout) {\n return // Already scheduled\n }\n\n const exponentialDelay = initialDelayMs * backoffMultiplier ** this.reconnectAttempt\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs)\n const jitter = cappedDelay * jitterFactor * (2 * Math.random() - 1)\n const delay = Math.floor(cappedDelay + jitter)\n\n this.setConnectionState('reconnecting')\n console.debug(`[iii] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempt + 1})...`)\n\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectTimeout = undefined\n this.reconnectAttempt++\n this.connect()\n }, delay)\n }\n\n private onSocketError(error: Error): void {\n this.logError('WebSocket error', error)\n }\n\n private startMetricsReporting(): void {\n if (!this.metricsReportingEnabled || !this.workerId) {\n return\n }\n\n const meter = getMeter()\n if (!meter) {\n console.warn(\n '[iii] Worker metrics disabled: OpenTelemetry not initialized. Call initOtel() with metricsEnabled: true before creating the iii.',\n )\n return\n }\n\n registerWorkerGauges(meter, {\n workerId: this.workerId,\n workerName: this.workerName,\n })\n }\n\n private stopMetricsReporting(): void {\n stopWorkerGauges()\n }\n\n private onSocketClose(): void {\n this.ws?.removeAllListeners()\n this.ws?.terminate()\n this.ws = undefined\n\n this.setConnectionState('disconnected')\n this.stopMetricsReporting()\n this.scheduleReconnect()\n }\n\n private onSocketOpen(): void {\n this.clearReconnectTimeout()\n this.reconnectAttempt = 0\n this.setConnectionState('connected')\n\n this.ws?.on('message', this.onMessage.bind(this))\n\n this.triggerTypes.forEach(({ message }) => {\n this.sendMessage(MessageType.RegisterTriggerType, message, true)\n })\n this.services.forEach(service => {\n this.sendMessage(MessageType.RegisterService, service, true)\n })\n this.functions.forEach(({ message }) => {\n this.sendMessage(MessageType.RegisterFunction, message, true)\n })\n this.triggers.forEach(trigger => {\n this.sendMessage(MessageType.RegisterTrigger, trigger, true)\n })\n\n // Optimized: swap with empty array instead of splice\n const pending = this.messagesToSend\n this.messagesToSend = []\n for (const message of pending) {\n if (\n message.type === MessageType.InvokeFunction &&\n typeof message.invocation_id === 'string' &&\n !this.invocations.has(message.invocation_id)\n ) {\n continue\n }\n this.sendMessageRaw(JSON.stringify(message))\n }\n\n this.registerWorkerMetadata()\n }\n\n private isOpen(): boolean {\n return this.ws?.readyState === WebSocket.OPEN\n }\n\n private sendMessageRaw(data: string): void {\n if (this.ws && this.isOpen()) {\n try {\n this.ws.send(data, err => {\n if (err) {\n this.logError('Failed to send message', err)\n }\n })\n } catch (error) {\n this.logError('Exception while sending message', error)\n }\n }\n }\n\n private toWireFormat(\n messageType: MessageType,\n message: Omit<IIIMessage, 'message_type'>,\n ): Record<string, unknown> {\n const { message_type: _, ...rest } = message as Record<string, unknown>\n if (messageType === MessageType.RegisterTrigger && 'type' in message) {\n const { type: triggerType, ...triggerRest } = message as RegisterTriggerMessage\n return { type: messageType, ...triggerRest, trigger_type: triggerType }\n }\n if (messageType === MessageType.UnregisterTrigger && 'type' in message) {\n const { type: triggerType, ...triggerRest } = message as RegisterTriggerMessage\n return { type: messageType, ...triggerRest, trigger_type: triggerType }\n }\n if (messageType === MessageType.TriggerRegistrationResult && 'type' in message) {\n const { type: triggerType, ...resultRest } = message as TriggerRegistrationResultMessage\n return { type: messageType, ...resultRest, trigger_type: triggerType }\n }\n return { type: messageType, ...rest } as Record<string, unknown>\n }\n\n private sendMessage(\n messageType: MessageType,\n message: Omit<IIIMessage, 'message_type'>,\n skipIfClosed = false,\n ): void {\n const wireMessage = this.toWireFormat(messageType, message)\n if (this.isOpen()) {\n this.sendMessageRaw(JSON.stringify(wireMessage))\n } else if (!skipIfClosed) {\n this.messagesToSend.push(wireMessage)\n }\n }\n\n private logError(message: string, error?: unknown): void {\n const otelLogger = getLogger()\n const errorMessage = error instanceof Error ? error.message : String(error ?? '')\n\n if (otelLogger) {\n otelLogger.emit({\n severityNumber: SeverityNumber.ERROR,\n body: `[iii] ${message}${errorMessage ? `: ${errorMessage}` : ''}`,\n })\n } else {\n console.error(`[iii] ${message}`, error ?? '')\n }\n }\n\n private severityTextToNumber(level: LogSeverityLevel): number {\n switch (level) {\n case 'trace':\n return 1\n case 'debug':\n return 5\n case 'info':\n return 9\n case 'warn':\n return 13\n case 'error':\n return 17\n case 'fatal':\n return 21\n case 'all':\n return 0\n default:\n return 0\n }\n }\n\n private onInvocationResult(invocation_id: string, result: unknown, error: unknown): void {\n const invocation = this.invocations.get(invocation_id)\n\n if (invocation) {\n if (invocation.timeout) {\n clearTimeout(invocation.timeout)\n }\n error ? invocation.reject(error) : invocation.resolve(result)\n }\n\n this.invocations.delete(invocation_id)\n }\n\n private async onInvokeFunction<TInput>(\n invocation_id: string | undefined,\n function_id: string,\n input: TInput,\n traceparent?: string,\n baggage?: string,\n ): Promise<unknown> {\n const fn = this.functions.get(function_id)\n // Get response traceparent/baggage after handler runs (will be current span's context)\n const getResponseTraceparent = () => injectTraceparent() ?? traceparent\n const getResponseBaggage = () => injectBaggage() ?? baggage\n\n if (fn) {\n if (!invocation_id) {\n try {\n await fn.handler(input, traceparent, baggage)\n } catch (error) {\n this.logError(`Error invoking function ${function_id}`, error)\n }\n return\n }\n\n try {\n const result = await fn.handler(input, traceparent, baggage)\n this.sendMessage(MessageType.InvocationResult, {\n invocation_id,\n function_id,\n result,\n traceparent: getResponseTraceparent(),\n baggage: getResponseBaggage(),\n })\n } catch (error) {\n this.sendMessage(MessageType.InvocationResult, {\n invocation_id,\n function_id,\n error: { code: 'invocation_failed', message: (error as Error).message },\n traceparent: getResponseTraceparent(),\n baggage: getResponseBaggage(),\n })\n }\n } else {\n this.sendMessage(MessageType.InvocationResult, {\n invocation_id,\n function_id,\n error: { code: 'function_not_found', message: 'Function not found' },\n traceparent,\n baggage,\n })\n }\n }\n\n private async onRegisterTrigger(message: {\n trigger_type: string\n id: string\n function_id: string\n config: unknown\n }) {\n const { trigger_type, id, function_id, config } = message\n const triggerTypeData = this.triggerTypes.get(trigger_type)\n\n if (triggerTypeData) {\n try {\n await triggerTypeData.handler.registerTrigger({ id, function_id, config })\n this.sendMessage(MessageType.TriggerRegistrationResult, {\n id,\n message_type: MessageType.TriggerRegistrationResult,\n type: trigger_type,\n function_id,\n })\n } catch (error) {\n this.sendMessage(MessageType.TriggerRegistrationResult, {\n id,\n message_type: MessageType.TriggerRegistrationResult,\n type: trigger_type,\n function_id,\n error: { code: 'trigger_registration_failed', message: (error as Error).message },\n })\n }\n } else {\n this.sendMessage(MessageType.TriggerRegistrationResult, {\n id,\n message_type: MessageType.TriggerRegistrationResult,\n type: trigger_type,\n function_id,\n error: { code: 'trigger_type_not_found', message: 'Trigger type not found' },\n })\n }\n }\n\n private onMessage(socketMessage: Data): void {\n let msgType: MessageType\n let message: Record<string, unknown>\n\n try {\n const parsed = JSON.parse(socketMessage.toString()) as Record<string, unknown>\n msgType = parsed.type as MessageType\n const { type: _, ...rest } = parsed\n message = rest\n } catch (error) {\n this.logError('Failed to parse incoming message', error)\n return\n }\n\n if (msgType === MessageType.InvocationResult) {\n const { invocation_id, result, error } = message as InvocationResultMessage\n this.onInvocationResult(invocation_id, result, error)\n } else if (msgType === MessageType.InvokeFunction) {\n const { invocation_id, function_id, data, traceparent, baggage } =\n message as InvokeFunctionMessage\n this.onInvokeFunction(invocation_id, function_id, data, traceparent, baggage)\n } else if (msgType === MessageType.RegisterTrigger) {\n this.onRegisterTrigger(\n message as { trigger_type: string; id: string; function_id: string; config: unknown },\n )\n } else if (msgType === MessageType.WorkerRegistered) {\n const { worker_id } = message as WorkerRegisteredMessage\n this.workerId = worker_id\n console.debug('[iii] Worker registered with ID:', worker_id)\n this.startMetricsReporting()\n }\n }\n}\n\nexport const init = (address: string, options?: InitOptions): ISdk => new Sdk(address, options)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["getOtelLogger","traceId?: string","serviceName?: string","spanId?: string","attributes: Record<string, string | undefined>","otelContext","address: string","fullTrigger: RegisterTriggerMessage","SpanKind","SeverityNumber","msgType: MessageType","message: Record<string, unknown>"],"sources":["../src/iii-types.ts","../src/logger.ts","../src/context.ts","../src/iii.ts"],"sourcesContent":["export enum MessageType {\n RegisterFunction = 'registerfunction',\n UnregisterFunction = 'unregisterfunction',\n RegisterService = 'registerservice',\n InvokeFunction = 'invokefunction',\n InvocationResult = 'invocationresult',\n RegisterTriggerType = 'registertriggertype',\n RegisterTrigger = 'registertrigger',\n UnregisterTrigger = 'unregistertrigger',\n UnregisterTriggerType = 'unregistertriggertype',\n TriggerRegistrationResult = 'triggerregistrationresult',\n WorkerRegistered = 'workerregistered',\n}\n\nexport type RegisterTriggerTypeMessage = {\n message_type: MessageType.RegisterTriggerType\n id: string\n description: string\n}\n\nexport type UnregisterTriggerTypeMessage = {\n message_type: MessageType.UnregisterTriggerType\n id: string\n}\n\nexport type UnregisterTriggerMessage = {\n message_type: MessageType.UnregisterTrigger\n id: string\n type?: string\n}\n\nexport type TriggerRegistrationResultMessage = {\n message_type: MessageType.TriggerRegistrationResult\n id: string\n type: string\n function_id: string\n result?: unknown\n error?: unknown\n}\n\nexport type RegisterTriggerMessage = {\n message_type: MessageType.RegisterTrigger\n id: string\n type: string\n function_id: string\n config: unknown\n}\n\nexport type RegisterServiceMessage = {\n message_type: MessageType.RegisterService\n id: string\n description?: string\n parent_service_id?: string\n}\n\nexport type RegisterFunctionFormat = {\n name: string\n /**\n * The description of the parameter\n */\n description?: string\n /**\n * The type of the parameter\n */\n type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'map'\n /**\n * The body of the parameter\n */\n body?: RegisterFunctionFormat[]\n /**\n * The items of the parameter\n */\n items?: RegisterFunctionFormat\n /**\n * Whether the parameter is required\n */\n required?: boolean\n}\n\nexport type RegisterFunctionMessage = {\n message_type: MessageType.RegisterFunction\n /**\n * The path of the function\n */\n id: string\n /**\n * The description of the function\n */\n description?: string\n /**\n * The request format of the function\n */\n request_format?: RegisterFunctionFormat\n /**\n * The response format of the function\n */\n response_format?: RegisterFunctionFormat\n metadata?: Record<string, unknown>\n}\n\nexport type InvokeFunctionMessage = {\n message_type: MessageType.InvokeFunction\n /**\n * This is optional for async invocations\n */\n invocation_id?: string\n /**\n * The path of the function\n */\n function_id: string\n /**\n * The data to pass to the function\n */\n data: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n}\n\nexport type InvocationResultMessage = {\n message_type: MessageType.InvocationResult\n /**\n * The id of the invocation\n */\n invocation_id: string\n /**\n * The path of the function\n */\n function_id: string\n result?: unknown\n error?: unknown\n /**\n * W3C trace-context traceparent header for distributed tracing\n */\n traceparent?: string\n /**\n * W3C baggage header for cross-cutting context propagation\n */\n baggage?: string\n}\n\nexport type FunctionInfo = {\n function_id: string\n description?: string\n request_format?: RegisterFunctionFormat\n response_format?: RegisterFunctionFormat\n metadata?: Record<string, unknown>\n}\n\nexport type WorkerStatus = 'connected' | 'available' | 'busy' | 'disconnected'\n\nexport type WorkerInfo = {\n id: string\n name?: string\n runtime?: string\n version?: string\n os?: string\n ip_address?: string\n status: WorkerStatus\n connected_at_ms: number\n function_count: number\n functions: string[]\n active_invocations: number\n}\n\nexport type WorkerRegisteredMessage = {\n message_type: MessageType.WorkerRegistered\n worker_id: string\n}\n\nexport type UnregisterFunctionMessage = {\n message_type: MessageType.UnregisterFunction\n id: string\n}\n\nexport type IIIMessage =\n | RegisterFunctionMessage\n | UnregisterFunctionMessage\n | InvokeFunctionMessage\n | InvocationResultMessage\n | RegisterServiceMessage\n | RegisterTriggerMessage\n | RegisterTriggerTypeMessage\n | UnregisterTriggerMessage\n | UnregisterTriggerTypeMessage\n | TriggerRegistrationResultMessage\n | WorkerRegisteredMessage\n","import { SeverityNumber } from '@opentelemetry/api-logs'\nimport { getLogger as getOtelLogger } from './telemetry-system'\nimport { safeStringify } from './utils'\n\nexport type LoggerParams = {\n message: string\n trace_id?: string\n span_id?: string\n service_name?: string\n data?: unknown\n /** @deprecated Use service_name instead */\n function_name?: string\n}\n\nexport class Logger {\n private _otelLogger: ReturnType<typeof getOtelLogger> | null = null\n\n private get otelLogger() {\n // Lazy initialization: re-fetch logger if not yet available\n if (!this._otelLogger) {\n this._otelLogger = getOtelLogger()\n }\n return this._otelLogger\n }\n\n constructor(\n private readonly traceId?: string,\n private readonly serviceName?: string,\n private readonly spanId?: string,\n ) {}\n\n private emit(message: string, severity: SeverityNumber, data?: unknown): void {\n const attributes: Record<string, string | undefined> = {}\n\n if (this.traceId) {\n attributes.trace_id = this.traceId\n }\n if (this.spanId) {\n attributes.span_id = this.spanId\n }\n if (this.serviceName) {\n attributes['service.name'] = this.serviceName\n }\n if (data !== undefined) {\n attributes['log.data'] = typeof data === 'string' ? data : safeStringify(data)\n }\n\n if (this.otelLogger) {\n this.otelLogger.emit({\n severityNumber: severity,\n body: message,\n attributes: Object.keys(attributes).length > 0 ? attributes : undefined,\n })\n } else {\n // Fallback to console when OTEL is not available\n switch (severity) {\n case SeverityNumber.DEBUG:\n console.debug(message, data)\n break\n case SeverityNumber.INFO:\n console.info(message, data)\n break\n case SeverityNumber.WARN:\n console.warn(message, data)\n break\n case SeverityNumber.ERROR:\n console.error(message, data)\n break\n default:\n console.log(message, data)\n }\n }\n }\n\n info(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.INFO, data)\n }\n\n warn(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.WARN, data)\n }\n\n error(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.ERROR, data)\n }\n\n debug(message: string, data?: unknown): void {\n this.emit(message, SeverityNumber.DEBUG, data)\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { Span } from '@opentelemetry/api'\nimport { context as otelContext } from '@opentelemetry/api'\nimport { Logger } from './logger'\n\nexport type Context = {\n logger: Logger\n /** The active OpenTelemetry span for adding custom attributes, events, etc. */\n trace?: Span\n}\n\nconst globalStorage = new AsyncLocalStorage<Context>()\n\nexport const withContext = async <T>(\n fn: (context: Context) => Promise<T>,\n ctx: Context,\n): Promise<T> => {\n // Capture the current OTel context before entering AsyncLocalStorage.run()\n // This preserves the OpenTelemetry trace context across async boundaries\n const currentOtelContext = otelContext.active()\n\n return globalStorage.run(ctx, async () => {\n // Restore the OTel context inside the run() scope\n // This ensures trace propagation works when handlers call iii.call\n return otelContext.with(currentOtelContext, async () => await fn(ctx))\n })\n}\n\nexport const getContext = (): Context => {\n const store = globalStorage.getStore()\n if (store) {\n return store\n }\n\n const logger = new Logger()\n\n return { logger }\n}\n","import { context } from '@opentelemetry/api'\nimport { createRequire } from 'node:module'\nimport * as os from 'node:os'\nimport { type Data, WebSocket } from 'ws'\nimport {\n type IIIConnectionState,\n type IIIReconnectionConfig,\n DEFAULT_BRIDGE_RECONNECTION_CONFIG,\n DEFAULT_INVOCATION_TIMEOUT_MS,\n EngineFunctions,\n EngineTriggers,\n} from './iii-constants'\nimport {\n type IIIMessage,\n type FunctionInfo,\n type InvocationResultMessage,\n type InvokeFunctionMessage,\n MessageType,\n type RegisterFunctionMessage,\n type RegisterServiceMessage,\n type RegisterTriggerMessage,\n type RegisterTriggerTypeMessage,\n type TriggerRegistrationResultMessage,\n type WorkerInfo,\n type WorkerRegisteredMessage,\n} from './iii-types'\nimport { withContext } from './context'\nimport { Logger } from './logger'\nimport type { IStream } from './stream'\nimport {\n currentSpanId,\n currentTraceId,\n extractContext,\n getLogger,\n getMeter,\n getTracer,\n injectBaggage,\n injectTraceparent,\n initOtel,\n shutdownOtel,\n SeverityNumber,\n SpanKind,\n withSpan,\n type OtelConfig,\n} from './telemetry-system'\nimport { registerWorkerGauges, stopWorkerGauges } from './otel-worker-gauges'\nimport type { TriggerHandler } from './triggers'\nimport type {\n ISdk,\n FunctionsAvailableCallback,\n Invocation,\n LogCallback,\n LogConfig,\n LogSeverityLevel,\n OtelLogEvent,\n RemoteFunctionData,\n RemoteFunctionHandler,\n RemoteTriggerTypeData,\n Trigger,\n FunctionRef,\n} from './types'\n\nconst require = createRequire(import.meta.url)\nconst { version: SDK_VERSION } = require('../package.json')\n\nfunction getOsInfo(): string {\n return `${os.platform()} ${os.release()} (${os.arch()})`\n}\n\nfunction getDefaultWorkerName(): string {\n return `${os.hostname()}:${process.pid}`\n}\n\n/** Callback type for connection state changes */\nexport type ConnectionStateCallback = (state: IIIConnectionState) => void\n\nexport type InitOptions = {\n workerName?: string\n enableMetricsReporting?: boolean\n /** Default timeout for function invocations in milliseconds */\n invocationTimeoutMs?: number\n /** Configuration for WebSocket reconnection behavior */\n reconnectionConfig?: Partial<IIIReconnectionConfig>\n /** OpenTelemetry configuration. OTel is initialized automatically by default.\n * Set `{ enabled: false }` or env `OTEL_ENABLED=false/0/no/off` to disable.\n * The engineWsUrl is set automatically from the III address. */\n otel?: Omit<OtelConfig, 'engineWsUrl'>\n}\n\nclass Sdk implements ISdk {\n private ws?: WebSocket\n private functions = new Map<string, RemoteFunctionData>()\n private services = new Map<string, Omit<RegisterServiceMessage, 'functions'>>()\n private invocations = new Map<string, Invocation & { timeout?: NodeJS.Timeout }>()\n private triggers = new Map<string, RegisterTriggerMessage>()\n private triggerTypes = new Map<string, RemoteTriggerTypeData>()\n private functionsAvailableCallbacks = new Set<FunctionsAvailableCallback>()\n private functionsAvailableTrigger?: Trigger\n private functionsAvailableFunctionPath?: string\n private logCallbacks = new Map<LogCallback, LogConfig>()\n private logTrigger?: Trigger\n private logFunctionPath?: string\n private messagesToSend: Record<string, unknown>[] = []\n private workerName: string\n private workerId?: string\n private reconnectTimeout?: NodeJS.Timeout\n private metricsReportingEnabled: boolean\n private invocationTimeoutMs: number\n private reconnectionConfig: IIIReconnectionConfig\n private reconnectAttempt = 0\n private connectionState: IIIConnectionState = 'disconnected'\n private stateCallbacks = new Set<ConnectionStateCallback>()\n private isShuttingDown = false\n\n constructor(\n private readonly address: string,\n options?: InitOptions,\n ) {\n this.workerName = options?.workerName ?? getDefaultWorkerName()\n this.metricsReportingEnabled = options?.enableMetricsReporting ?? true\n this.invocationTimeoutMs = options?.invocationTimeoutMs ?? DEFAULT_INVOCATION_TIMEOUT_MS\n this.reconnectionConfig = {\n ...DEFAULT_BRIDGE_RECONNECTION_CONFIG,\n ...options?.reconnectionConfig,\n }\n\n // Initialize OpenTelemetry (enabled by default, opt-out via config or env)\n initOtel({ ...options?.otel, engineWsUrl: this.address })\n\n this.connect()\n }\n\n registerTriggerType = <TConfig>(\n triggerType: Omit<RegisterTriggerTypeMessage, 'message_type'>,\n handler: TriggerHandler<TConfig>,\n ): void => {\n this.sendMessage(MessageType.RegisterTriggerType, triggerType, true)\n this.triggerTypes.set(triggerType.id, {\n message: { ...triggerType, message_type: MessageType.RegisterTriggerType },\n handler,\n })\n }\n\n on = (event: string, callback: (arg?: unknown) => void): void => {\n this.ws?.on(event, callback)\n }\n\n unregisterTriggerType = (triggerType: Omit<RegisterTriggerTypeMessage, 'message_type'>): void => {\n this.sendMessage(MessageType.UnregisterTriggerType, triggerType, true)\n this.triggerTypes.delete(triggerType.id)\n }\n\n registerTrigger = (trigger: Omit<RegisterTriggerMessage, 'message_type' | 'id'>): Trigger => {\n const id = crypto.randomUUID()\n const fullTrigger: RegisterTriggerMessage = {\n ...trigger,\n id,\n message_type: MessageType.RegisterTrigger,\n }\n this.sendMessage(MessageType.RegisterTrigger, fullTrigger, true)\n this.triggers.set(id, fullTrigger)\n\n return {\n unregister: () => {\n this.sendMessage(MessageType.UnregisterTrigger, {\n id,\n message_type: MessageType.UnregisterTrigger,\n type: fullTrigger.type,\n })\n this.triggers.delete(id)\n },\n }\n }\n\n registerFunction = (\n message: Omit<RegisterFunctionMessage, 'message_type'>,\n handler: RemoteFunctionHandler,\n ): FunctionRef => {\n if (!message.id || message.id.trim() === '') {\n throw new Error('id is required')\n }\n\n this.sendMessage(MessageType.RegisterFunction, message, true)\n this.functions.set(message.id, {\n message: { ...message, message_type: MessageType.RegisterFunction },\n handler: async (input, traceparent?: string, baggage?: string) => {\n // If we have a tracer, wrap in a span and pass it to the context\n if (getTracer()) {\n // Extract both traceparent and baggage into a parent context\n const parentContext = extractContext(traceparent, baggage)\n\n return context.with(parentContext, () =>\n withSpan(`call ${message.id}`, { kind: SpanKind.SERVER }, async span => {\n const traceId = currentTraceId() ?? crypto.randomUUID()\n const spanId = currentSpanId()\n const logger = new Logger(traceId, message.id, spanId)\n const ctx = { logger, trace: span }\n\n return withContext(async () => await handler(input), ctx)\n }),\n )\n }\n\n // Fallback without tracing\n const traceId = crypto.randomUUID()\n const logger = new Logger(traceId, message.id)\n const ctx = { logger }\n\n return withContext(async () => await handler(input), ctx)\n },\n })\n\n return {\n id: message.id,\n unregister: () => {\n this.sendMessage(MessageType.UnregisterFunction, { id: message.id }, true)\n this.functions.delete(message.id)\n },\n }\n }\n\n registerService = (message: Omit<RegisterServiceMessage, 'message_type'>): void => {\n this.sendMessage(MessageType.RegisterService, message, true)\n this.services.set(message.id, { ...message, message_type: MessageType.RegisterService })\n }\n\n trigger = async <TInput, TOutput>(\n function_id: string,\n data: TInput,\n timeoutMs?: number,\n ): Promise<TOutput> => {\n const invocation_id = crypto.randomUUID()\n const traceparent = injectTraceparent()\n const baggage = injectBaggage()\n const effectiveTimeout = timeoutMs ?? this.invocationTimeoutMs\n\n return new Promise<TOutput>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const invocation = this.invocations.get(invocation_id)\n if (invocation) {\n this.invocations.delete(invocation_id)\n reject(new Error(`Invocation timeout after ${effectiveTimeout}ms: ${function_id}`))\n }\n }, effectiveTimeout)\n\n this.invocations.set(invocation_id, {\n resolve: (result: TOutput) => {\n clearTimeout(timeout)\n resolve(result)\n },\n reject: (error: unknown) => {\n clearTimeout(timeout)\n reject(error)\n },\n timeout,\n })\n\n this.sendMessage(MessageType.InvokeFunction, {\n invocation_id,\n function_id,\n data,\n traceparent,\n baggage,\n })\n })\n }\n\n triggerVoid = <TInput>(function_id: string, data: TInput): void => {\n const traceparent = injectTraceparent()\n const baggage = injectBaggage()\n this.sendMessage(MessageType.InvokeFunction, { function_id, data, traceparent, baggage })\n }\n\n call = async <TInput, TOutput>(\n function_id: string,\n data: TInput,\n timeoutMs?: number,\n ): Promise<TOutput> => this.trigger<TInput, TOutput>(function_id, data, timeoutMs)\n\n callVoid = <TInput>(function_id: string, data: TInput): void =>\n this.triggerVoid(function_id, data)\n\n listFunctions = async (): Promise<FunctionInfo[]> => {\n const result = await this.trigger<Record<string, never>, { functions: FunctionInfo[] }>(\n EngineFunctions.LIST_FUNCTIONS,\n {},\n )\n return result.functions\n }\n\n listWorkers = async (): Promise<WorkerInfo[]> => {\n const result = await this.trigger<Record<string, never>, { workers: WorkerInfo[] }>(\n EngineFunctions.LIST_WORKERS,\n {},\n )\n return result.workers\n }\n\n private registerWorkerMetadata(): void {\n this.triggerVoid(EngineFunctions.REGISTER_WORKER, {\n runtime: 'node',\n version: SDK_VERSION,\n name: this.workerName,\n os: getOsInfo(),\n })\n }\n\n createStream = <TData>(streamName: string, stream: IStream<TData>): void => {\n this.registerFunction({ id: `stream::get(${streamName})` }, stream.get.bind(stream))\n this.registerFunction({ id: `stream::set(${streamName})` }, stream.set.bind(stream))\n this.registerFunction({ id: `stream::delete(${streamName})` }, stream.delete.bind(stream))\n this.registerFunction({ id: `stream::list(${streamName})` }, stream.list.bind(stream))\n this.registerFunction(\n { id: `stream::list_groups(${streamName})` },\n stream.listGroups.bind(stream),\n )\n }\n\n onFunctionsAvailable = (callback: FunctionsAvailableCallback): (() => void) => {\n this.functionsAvailableCallbacks.add(callback)\n\n if (!this.functionsAvailableTrigger) {\n if (!this.functionsAvailableFunctionPath) {\n this.functionsAvailableFunctionPath = `engine.on_functions_available.${crypto.randomUUID()}`\n }\n\n const function_id = this.functionsAvailableFunctionPath\n if (!this.functions.has(function_id)) {\n this.registerFunction(\n { id: function_id },\n async ({ functions }: { functions: FunctionInfo[] }) => {\n this.functionsAvailableCallbacks.forEach(handler => {\n handler(functions)\n })\n return null\n },\n )\n }\n\n this.functionsAvailableTrigger = this.registerTrigger({\n type: EngineTriggers.FUNCTIONS_AVAILABLE,\n function_id,\n config: {},\n })\n }\n\n return () => {\n this.functionsAvailableCallbacks.delete(callback)\n if (this.functionsAvailableCallbacks.size === 0 && this.functionsAvailableTrigger) {\n this.functionsAvailableTrigger.unregister()\n this.functionsAvailableTrigger = undefined\n }\n }\n }\n\n onLog = (callback: LogCallback, config?: LogConfig): (() => void) => {\n const effectiveConfig = config ?? { level: 'all' }\n this.logCallbacks.set(callback, effectiveConfig)\n\n if (!this.logTrigger) {\n if (!this.logFunctionPath) {\n this.logFunctionPath = `engine.on_log.${crypto.randomUUID()}`\n }\n\n const function_id = this.logFunctionPath\n if (!this.functions.has(function_id)) {\n this.registerFunction({ id: function_id }, async (log: OtelLogEvent) => {\n this.logCallbacks.forEach((cfg, handler) => {\n try {\n const minSeverity = this.severityTextToNumber(cfg.level ?? 'all')\n if (cfg.level === 'all' || log.severity_number >= minSeverity) {\n handler(log)\n }\n } catch (error) {\n this.logError('Log callback handler threw an exception', error)\n }\n })\n return null\n })\n }\n\n this.logTrigger = this.registerTrigger({\n type: EngineTriggers.LOG,\n function_id,\n config: { level: 'all', severity_min: 0 },\n })\n }\n\n return () => {\n this.logCallbacks.delete(callback)\n if (this.logCallbacks.size === 0 && this.logTrigger) {\n this.logTrigger.unregister()\n this.logTrigger = undefined\n }\n }\n }\n\n /**\n * Get the current connection state.\n */\n getConnectionState = (): IIIConnectionState => {\n return this.connectionState\n }\n\n /**\n * Register a callback to be notified of connection state changes.\n * @returns A function to unregister the callback\n */\n onConnectionStateChange = (callback: ConnectionStateCallback): (() => void) => {\n this.stateCallbacks.add(callback)\n // Immediately notify of current state\n callback(this.connectionState)\n return () => this.stateCallbacks.delete(callback)\n }\n\n /**\n * Gracefully shutdown the iii, cleaning up all resources.\n */\n shutdown = async (): Promise<void> => {\n this.isShuttingDown = true\n\n this.stopMetricsReporting()\n\n // Shutdown OpenTelemetry\n await shutdownOtel()\n\n // Clear reconnection timeout\n this.clearReconnectTimeout()\n\n // Reject all pending invocations\n for (const [_id, invocation] of this.invocations) {\n if (invocation.timeout) {\n clearTimeout(invocation.timeout)\n }\n invocation.reject(new Error('iii is shutting down'))\n }\n this.invocations.clear()\n\n // Close WebSocket\n if (this.ws) {\n this.ws.removeAllListeners()\n this.ws.close()\n this.ws = undefined\n }\n\n // Clear callbacks\n this.stateCallbacks.clear()\n\n this.setConnectionState('disconnected')\n }\n\n // private methods\n\n private setConnectionState(state: IIIConnectionState): void {\n if (this.connectionState !== state) {\n this.connectionState = state\n for (const callback of this.stateCallbacks) {\n try {\n callback(state)\n } catch (error) {\n this.logError('Error in connection state callback', error)\n }\n }\n }\n }\n\n private connect(): void {\n if (this.isShuttingDown) {\n return\n }\n\n this.setConnectionState('connecting')\n this.ws = new WebSocket(this.address)\n this.ws.on('open', this.onSocketOpen.bind(this))\n this.ws.on('close', this.onSocketClose.bind(this))\n this.ws.on('error', this.onSocketError.bind(this))\n }\n\n private clearReconnectTimeout(): void {\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout)\n this.reconnectTimeout = undefined\n }\n }\n\n private scheduleReconnect(): void {\n if (this.isShuttingDown) {\n return\n }\n\n const { maxRetries, initialDelayMs, backoffMultiplier, maxDelayMs, jitterFactor } =\n this.reconnectionConfig\n\n if (maxRetries !== -1 && this.reconnectAttempt >= maxRetries) {\n this.setConnectionState('failed')\n this.logError(`Max reconnection retries (${maxRetries}) reached, giving up`)\n return\n }\n\n if (this.reconnectTimeout) {\n return // Already scheduled\n }\n\n const exponentialDelay = initialDelayMs * backoffMultiplier ** this.reconnectAttempt\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs)\n const jitter = cappedDelay * jitterFactor * (2 * Math.random() - 1)\n const delay = Math.floor(cappedDelay + jitter)\n\n this.setConnectionState('reconnecting')\n console.debug(`[iii] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempt + 1})...`)\n\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectTimeout = undefined\n this.reconnectAttempt++\n this.connect()\n }, delay)\n }\n\n private onSocketError(error: Error): void {\n this.logError('WebSocket error', error)\n }\n\n private startMetricsReporting(): void {\n if (!this.metricsReportingEnabled || !this.workerId) {\n return\n }\n\n const meter = getMeter()\n if (!meter) {\n console.warn(\n '[iii] Worker metrics disabled: OpenTelemetry not initialized. Call initOtel() with metricsEnabled: true before creating the iii.',\n )\n return\n }\n\n registerWorkerGauges(meter, {\n workerId: this.workerId,\n workerName: this.workerName,\n })\n }\n\n private stopMetricsReporting(): void {\n stopWorkerGauges()\n }\n\n private onSocketClose(): void {\n this.ws?.removeAllListeners()\n this.ws?.terminate()\n this.ws = undefined\n\n this.setConnectionState('disconnected')\n this.stopMetricsReporting()\n this.scheduleReconnect()\n }\n\n private onSocketOpen(): void {\n this.clearReconnectTimeout()\n this.reconnectAttempt = 0\n this.setConnectionState('connected')\n\n this.ws?.on('message', this.onMessage.bind(this))\n\n this.triggerTypes.forEach(({ message }) => {\n this.sendMessage(MessageType.RegisterTriggerType, message, true)\n })\n this.services.forEach(service => {\n this.sendMessage(MessageType.RegisterService, service, true)\n })\n this.functions.forEach(({ message }) => {\n this.sendMessage(MessageType.RegisterFunction, message, true)\n })\n this.triggers.forEach(trigger => {\n this.sendMessage(MessageType.RegisterTrigger, trigger, true)\n })\n\n // Optimized: swap with empty array instead of splice\n const pending = this.messagesToSend\n this.messagesToSend = []\n for (const message of pending) {\n if (\n message.type === MessageType.InvokeFunction &&\n typeof message.invocation_id === 'string' &&\n !this.invocations.has(message.invocation_id)\n ) {\n continue\n }\n this.sendMessageRaw(JSON.stringify(message))\n }\n\n this.registerWorkerMetadata()\n }\n\n private isOpen(): boolean {\n return this.ws?.readyState === WebSocket.OPEN\n }\n\n private sendMessageRaw(data: string): void {\n if (this.ws && this.isOpen()) {\n try {\n this.ws.send(data, err => {\n if (err) {\n this.logError('Failed to send message', err)\n }\n })\n } catch (error) {\n this.logError('Exception while sending message', error)\n }\n }\n }\n\n private toWireFormat(\n messageType: MessageType,\n message: Omit<IIIMessage, 'message_type'>,\n ): Record<string, unknown> {\n const { message_type: _, ...rest } = message as Record<string, unknown>\n if (messageType === MessageType.RegisterTrigger && 'type' in message) {\n const { type: triggerType, ...triggerRest } = message as RegisterTriggerMessage\n return { type: messageType, ...triggerRest, trigger_type: triggerType }\n }\n if (messageType === MessageType.UnregisterTrigger && 'type' in message) {\n const { type: triggerType, ...triggerRest } = message as RegisterTriggerMessage\n return { type: messageType, ...triggerRest, trigger_type: triggerType }\n }\n if (messageType === MessageType.TriggerRegistrationResult && 'type' in message) {\n const { type: triggerType, ...resultRest } = message as TriggerRegistrationResultMessage\n return { type: messageType, ...resultRest, trigger_type: triggerType }\n }\n return { type: messageType, ...rest } as Record<string, unknown>\n }\n\n private sendMessage(\n messageType: MessageType,\n message: Omit<IIIMessage, 'message_type'>,\n skipIfClosed = false,\n ): void {\n const wireMessage = this.toWireFormat(messageType, message)\n if (this.isOpen()) {\n this.sendMessageRaw(JSON.stringify(wireMessage))\n } else if (!skipIfClosed) {\n this.messagesToSend.push(wireMessage)\n }\n }\n\n private logError(message: string, error?: unknown): void {\n const otelLogger = getLogger()\n const errorMessage = error instanceof Error ? error.message : String(error ?? '')\n\n if (otelLogger) {\n otelLogger.emit({\n severityNumber: SeverityNumber.ERROR,\n body: `[iii] ${message}${errorMessage ? `: ${errorMessage}` : ''}`,\n })\n } else {\n console.error(`[iii] ${message}`, error ?? '')\n }\n }\n\n private severityTextToNumber(level: LogSeverityLevel): number {\n switch (level) {\n case 'trace':\n return 1\n case 'debug':\n return 5\n case 'info':\n return 9\n case 'warn':\n return 13\n case 'error':\n return 17\n case 'fatal':\n return 21\n case 'all':\n return 0\n default:\n return 0\n }\n }\n\n private onInvocationResult(invocation_id: string, result: unknown, error: unknown): void {\n const invocation = this.invocations.get(invocation_id)\n\n if (invocation) {\n if (invocation.timeout) {\n clearTimeout(invocation.timeout)\n }\n error ? invocation.reject(error) : invocation.resolve(result)\n }\n\n this.invocations.delete(invocation_id)\n }\n\n private async onInvokeFunction<TInput>(\n invocation_id: string | undefined,\n function_id: string,\n input: TInput,\n traceparent?: string,\n baggage?: string,\n ): Promise<unknown> {\n const fn = this.functions.get(function_id)\n // Get response traceparent/baggage after handler runs (will be current span's context)\n const getResponseTraceparent = () => injectTraceparent() ?? traceparent\n const getResponseBaggage = () => injectBaggage() ?? baggage\n\n if (fn) {\n if (!invocation_id) {\n try {\n await fn.handler(input, traceparent, baggage)\n } catch (error) {\n this.logError(`Error invoking function ${function_id}`, error)\n }\n return\n }\n\n try {\n const result = await fn.handler(input, traceparent, baggage)\n this.sendMessage(MessageType.InvocationResult, {\n invocation_id,\n function_id,\n result,\n traceparent: getResponseTraceparent(),\n baggage: getResponseBaggage(),\n })\n } catch (error) {\n this.sendMessage(MessageType.InvocationResult, {\n invocation_id,\n function_id,\n error: { code: 'invocation_failed', message: (error as Error).message },\n traceparent: getResponseTraceparent(),\n baggage: getResponseBaggage(),\n })\n }\n } else {\n this.sendMessage(MessageType.InvocationResult, {\n invocation_id,\n function_id,\n error: { code: 'function_not_found', message: 'Function not found' },\n traceparent,\n baggage,\n })\n }\n }\n\n private async onRegisterTrigger(message: {\n trigger_type: string\n id: string\n function_id: string\n config: unknown\n }) {\n const { trigger_type, id, function_id, config } = message\n const triggerTypeData = this.triggerTypes.get(trigger_type)\n\n if (triggerTypeData) {\n try {\n await triggerTypeData.handler.registerTrigger({ id, function_id, config })\n this.sendMessage(MessageType.TriggerRegistrationResult, {\n id,\n message_type: MessageType.TriggerRegistrationResult,\n type: trigger_type,\n function_id,\n })\n } catch (error) {\n this.sendMessage(MessageType.TriggerRegistrationResult, {\n id,\n message_type: MessageType.TriggerRegistrationResult,\n type: trigger_type,\n function_id,\n error: { code: 'trigger_registration_failed', message: (error as Error).message },\n })\n }\n } else {\n this.sendMessage(MessageType.TriggerRegistrationResult, {\n id,\n message_type: MessageType.TriggerRegistrationResult,\n type: trigger_type,\n function_id,\n error: { code: 'trigger_type_not_found', message: 'Trigger type not found' },\n })\n }\n }\n\n private onMessage(socketMessage: Data): void {\n let msgType: MessageType\n let message: Record<string, unknown>\n\n try {\n const parsed = JSON.parse(socketMessage.toString()) as Record<string, unknown>\n msgType = parsed.type as MessageType\n const { type: _, ...rest } = parsed\n message = rest\n } catch (error) {\n this.logError('Failed to parse incoming message', error)\n return\n }\n\n if (msgType === MessageType.InvocationResult) {\n const { invocation_id, result, error } = message as InvocationResultMessage\n this.onInvocationResult(invocation_id, result, error)\n } else if (msgType === MessageType.InvokeFunction) {\n const { invocation_id, function_id, data, traceparent, baggage } =\n message as InvokeFunctionMessage\n this.onInvokeFunction(invocation_id, function_id, data, traceparent, baggage)\n } else if (msgType === MessageType.RegisterTrigger) {\n this.onRegisterTrigger(\n message as { trigger_type: string; id: string; function_id: string; config: unknown },\n )\n } else if (msgType === MessageType.WorkerRegistered) {\n const { worker_id } = message as WorkerRegisteredMessage\n this.workerId = worker_id\n console.debug('[iii] Worker registered with ID:', worker_id)\n this.startMetricsReporting()\n }\n }\n}\n\nexport const init = (address: string, options?: InitOptions): ISdk => new Sdk(address, options)\n"],"mappings":"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"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
1
|
+
import { SpanKind, SpanKind as SpanKind$1, SpanStatusCode, SpanStatusCode as SpanStatusCode$1, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
2
2
|
import { WebSocket } from "ws";
|
|
3
3
|
import { SeverityNumber as SeverityNumber$1 } from "@opentelemetry/api-logs";
|
|
4
4
|
import { Resource } from "@opentelemetry/resources";
|
|
5
5
|
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
-
import {
|
|
7
|
+
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
8
8
|
import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
9
9
|
import { CompositePropagator, ExportResultCode, W3CBaggagePropagator, W3CTraceContextPropagator } from "@opentelemetry/core";
|
|
10
10
|
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
11
11
|
import { registerInstrumentations } from "@opentelemetry/instrumentation";
|
|
12
|
-
import {
|
|
12
|
+
import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
|
|
13
13
|
import { JsonLogsSerializer, JsonMetricsSerializer, JsonTraceSerializer } from "@opentelemetry/otlp-transformer";
|
|
14
14
|
import { monitorEventLoopDelay, performance } from "node:perf_hooks";
|
|
15
15
|
|
|
@@ -70,7 +70,8 @@ const DEFAULT_OTEL_CONFIG = {
|
|
|
70
70
|
serviceVersion: "unknown",
|
|
71
71
|
engineWsUrl: "ws://localhost:49134",
|
|
72
72
|
metricsEnabled: true,
|
|
73
|
-
metricsExportIntervalMs: 6e4
|
|
73
|
+
metricsExportIntervalMs: 6e4,
|
|
74
|
+
fetchInstrumentationEnabled: true
|
|
74
75
|
};
|
|
75
76
|
/** Parse a boolean environment variable, recognizing 'false', '0', 'no', 'off' as false. */
|
|
76
77
|
function parseBoolEnv(value, defaultValue) {
|
|
@@ -537,6 +538,121 @@ function getAllBaggage() {
|
|
|
537
538
|
return entries;
|
|
538
539
|
}
|
|
539
540
|
|
|
541
|
+
//#endregion
|
|
542
|
+
//#region src/telemetry-system/fetch-instrumentation.ts
|
|
543
|
+
/**
|
|
544
|
+
* Global fetch auto-instrumentation for the III Node SDK.
|
|
545
|
+
*
|
|
546
|
+
* Patches globalThis.fetch to create OTel CLIENT spans for every HTTP request.
|
|
547
|
+
* Works on all runtimes (Bun, Node.js, Deno) unlike UndiciInstrumentation
|
|
548
|
+
* which only works when fetch is backed by Node.js's undici.
|
|
549
|
+
*/
|
|
550
|
+
const textEncoder = new TextEncoder();
|
|
551
|
+
function getBodyByteSize(body) {
|
|
552
|
+
if (body == null) return void 0;
|
|
553
|
+
if (typeof body === "string") return textEncoder.encode(body).byteLength;
|
|
554
|
+
if (body instanceof ArrayBuffer) return body.byteLength;
|
|
555
|
+
if (ArrayBuffer.isView(body)) return body.byteLength;
|
|
556
|
+
if (body instanceof Blob) return body.size;
|
|
557
|
+
if (body instanceof URLSearchParams) return new TextEncoder().encode(body.toString()).byteLength;
|
|
558
|
+
}
|
|
559
|
+
const SAFE_REQUEST_HEADERS = ["content-type", "accept"];
|
|
560
|
+
const SAFE_RESPONSE_HEADERS = ["content-type"];
|
|
561
|
+
let originalFetch = null;
|
|
562
|
+
/**
|
|
563
|
+
* Patch globalThis.fetch to create OTel CLIENT spans for every HTTP request.
|
|
564
|
+
*/
|
|
565
|
+
function patchGlobalFetch(tracer$1) {
|
|
566
|
+
if (originalFetch) return;
|
|
567
|
+
originalFetch = globalThis.fetch;
|
|
568
|
+
const capturedFetch = originalFetch;
|
|
569
|
+
globalThis.fetch = async (input, init) => {
|
|
570
|
+
const url = input instanceof Request ? input.url : String(input);
|
|
571
|
+
const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
|
|
572
|
+
let host;
|
|
573
|
+
let scheme;
|
|
574
|
+
let path;
|
|
575
|
+
let port;
|
|
576
|
+
let query;
|
|
577
|
+
try {
|
|
578
|
+
const parsed = new URL(url);
|
|
579
|
+
host = parsed.hostname;
|
|
580
|
+
scheme = parsed.protocol.replace(":", "");
|
|
581
|
+
path = parsed.pathname;
|
|
582
|
+
port = parsed.port ? parseInt(parsed.port, 10) : void 0;
|
|
583
|
+
query = parsed.search ? parsed.search.slice(1) : void 0;
|
|
584
|
+
} catch {}
|
|
585
|
+
const spanAttributes = {
|
|
586
|
+
"http.request.method": method,
|
|
587
|
+
"url.full": url
|
|
588
|
+
};
|
|
589
|
+
if (host) spanAttributes["server.address"] = host;
|
|
590
|
+
if (scheme) {
|
|
591
|
+
spanAttributes["url.scheme"] = scheme;
|
|
592
|
+
spanAttributes["network.protocol.name"] = "http";
|
|
593
|
+
}
|
|
594
|
+
if (path) spanAttributes["url.path"] = path;
|
|
595
|
+
if (port) spanAttributes["server.port"] = port;
|
|
596
|
+
if (query) spanAttributes["url.query"] = query;
|
|
597
|
+
const spanName = path ? `${method} ${path}` : method;
|
|
598
|
+
return tracer$1.startActiveSpan(spanName, {
|
|
599
|
+
kind: SpanKind.CLIENT,
|
|
600
|
+
attributes: spanAttributes
|
|
601
|
+
}, context.active(), async (span) => {
|
|
602
|
+
try {
|
|
603
|
+
const carrier = {};
|
|
604
|
+
propagation.inject(context.active(), carrier);
|
|
605
|
+
const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : void 0));
|
|
606
|
+
for (const [key, value] of Object.entries(carrier)) headers.set(key, value);
|
|
607
|
+
for (const name of SAFE_REQUEST_HEADERS) {
|
|
608
|
+
const value = headers.get(name);
|
|
609
|
+
if (value !== null) span.setAttribute(`http.request.header.${name}`, value);
|
|
610
|
+
}
|
|
611
|
+
const requestBodySize = getBodyByteSize(init?.body ?? (input instanceof Request ? input.body : void 0));
|
|
612
|
+
if (requestBodySize !== void 0) span.setAttribute("http.request.body.size", requestBodySize);
|
|
613
|
+
const response = await capturedFetch(input, {
|
|
614
|
+
...init,
|
|
615
|
+
headers
|
|
616
|
+
});
|
|
617
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
618
|
+
const contentLength = response.headers.get("content-length");
|
|
619
|
+
if (contentLength !== null) {
|
|
620
|
+
const size = parseInt(contentLength, 10);
|
|
621
|
+
if (!Number.isNaN(size)) span.setAttribute("http.response.body.size", size);
|
|
622
|
+
}
|
|
623
|
+
for (const name of SAFE_RESPONSE_HEADERS) {
|
|
624
|
+
const value = response.headers.get(name);
|
|
625
|
+
if (value !== null) span.setAttribute(`http.response.header.${name}`, value);
|
|
626
|
+
}
|
|
627
|
+
if (response.status >= 400) {
|
|
628
|
+
span.setAttribute("error.type", String(response.status));
|
|
629
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
630
|
+
} else span.setStatus({ code: SpanStatusCode.OK });
|
|
631
|
+
return response;
|
|
632
|
+
} catch (error) {
|
|
633
|
+
span.setAttribute("error.type", error.name ?? "Error");
|
|
634
|
+
span.setStatus({
|
|
635
|
+
code: SpanStatusCode.ERROR,
|
|
636
|
+
message: error.message
|
|
637
|
+
});
|
|
638
|
+
span.recordException(error);
|
|
639
|
+
throw error;
|
|
640
|
+
} finally {
|
|
641
|
+
span.end();
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Restore globalThis.fetch to its original implementation.
|
|
648
|
+
*/
|
|
649
|
+
function unpatchGlobalFetch() {
|
|
650
|
+
if (originalFetch) {
|
|
651
|
+
globalThis.fetch = originalFetch;
|
|
652
|
+
originalFetch = null;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
540
656
|
//#endregion
|
|
541
657
|
//#region src/telemetry-system/index.ts
|
|
542
658
|
/**
|
|
@@ -562,7 +678,6 @@ function initOtel(config = {}) {
|
|
|
562
678
|
console.debug("[OTel] OpenTelemetry is disabled. To enable, remove OTEL_ENABLED=false or set enabled: true in config.");
|
|
563
679
|
return;
|
|
564
680
|
}
|
|
565
|
-
if (config.instrumentations?.length) registerInstrumentations({ instrumentations: config.instrumentations });
|
|
566
681
|
serviceName = config.serviceName ?? process.env.OTEL_SERVICE_NAME ?? DEFAULT_OTEL_CONFIG.serviceName;
|
|
567
682
|
const serviceVersion = config.serviceVersion ?? process.env.SERVICE_VERSION ?? DEFAULT_OTEL_CONFIG.serviceVersion;
|
|
568
683
|
const serviceNamespace = config.serviceNamespace ?? process.env.SERVICE_NAMESPACE;
|
|
@@ -578,7 +693,7 @@ function initOtel(config = {}) {
|
|
|
578
693
|
sharedConnection = new SharedEngineConnection(engineWsUrl, config.reconnectionConfig);
|
|
579
694
|
tracerProvider = new NodeTracerProvider({
|
|
580
695
|
resource,
|
|
581
|
-
spanProcessors: [new
|
|
696
|
+
spanProcessors: [new BatchSpanProcessor(new EngineSpanExporter(sharedConnection))]
|
|
582
697
|
});
|
|
583
698
|
propagation.setGlobalPropagator(new CompositePropagator({ propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()] }));
|
|
584
699
|
tracerProvider.register();
|
|
@@ -598,9 +713,22 @@ function initOtel(config = {}) {
|
|
|
598
713
|
meter = meterProvider.getMeter(serviceName);
|
|
599
714
|
console.debug(`[OTel] Metrics initialized: interval=${exportIntervalMs}ms`);
|
|
600
715
|
}
|
|
716
|
+
const instrumentations = [...config.instrumentations ?? []];
|
|
717
|
+
if (instrumentations.length > 0) {
|
|
718
|
+
registerInstrumentations({
|
|
719
|
+
instrumentations,
|
|
720
|
+
tracerProvider,
|
|
721
|
+
meterProvider: meterProvider ?? void 0
|
|
722
|
+
});
|
|
723
|
+
console.debug(`[OTel] Instrumentations registered: ${instrumentations.length} total`);
|
|
724
|
+
}
|
|
725
|
+
if (config.fetchInstrumentationEnabled ?? DEFAULT_OTEL_CONFIG.fetchInstrumentationEnabled) {
|
|
726
|
+
patchGlobalFetch(tracer);
|
|
727
|
+
console.debug("[OTel] Global fetch instrumentation enabled");
|
|
728
|
+
}
|
|
601
729
|
const logExporter = new EngineLogExporter(sharedConnection);
|
|
602
730
|
loggerProvider = new LoggerProvider({ resource });
|
|
603
|
-
loggerProvider.addLogRecordProcessor(new
|
|
731
|
+
loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));
|
|
604
732
|
logger = loggerProvider.getLogger(serviceName);
|
|
605
733
|
console.debug("[OTel] Logs initialized");
|
|
606
734
|
}
|
|
@@ -609,14 +737,17 @@ function initOtel(config = {}) {
|
|
|
609
737
|
*/
|
|
610
738
|
async function shutdownOtel() {
|
|
611
739
|
if (tracerProvider) {
|
|
740
|
+
await tracerProvider.forceFlush();
|
|
612
741
|
await tracerProvider.shutdown();
|
|
613
742
|
tracerProvider = null;
|
|
614
743
|
}
|
|
615
744
|
if (meterProvider) {
|
|
745
|
+
await meterProvider.forceFlush();
|
|
616
746
|
await meterProvider.shutdown();
|
|
617
747
|
meterProvider = null;
|
|
618
748
|
}
|
|
619
749
|
if (loggerProvider) {
|
|
750
|
+
await loggerProvider.forceFlush();
|
|
620
751
|
await loggerProvider.shutdown();
|
|
621
752
|
loggerProvider = null;
|
|
622
753
|
}
|
|
@@ -624,6 +755,7 @@ async function shutdownOtel() {
|
|
|
624
755
|
await sharedConnection.shutdown();
|
|
625
756
|
sharedConnection = null;
|
|
626
757
|
}
|
|
758
|
+
unpatchGlobalFetch();
|
|
627
759
|
tracer = null;
|
|
628
760
|
meter = null;
|
|
629
761
|
logger = null;
|
|
@@ -671,14 +803,14 @@ async function withSpan(name, options, fn) {
|
|
|
671
803
|
return fn(noopSpan);
|
|
672
804
|
}
|
|
673
805
|
const parentContext = options.traceparent ? extractTraceparent(options.traceparent) : context.active();
|
|
674
|
-
return tracer.startActiveSpan(name, { kind: options.kind ?? SpanKind.INTERNAL }, parentContext, async (span) => {
|
|
806
|
+
return tracer.startActiveSpan(name, { kind: options.kind ?? SpanKind$1.INTERNAL }, parentContext, async (span) => {
|
|
675
807
|
try {
|
|
676
808
|
const result = await fn(span);
|
|
677
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
809
|
+
span.setStatus({ code: SpanStatusCode$1.OK });
|
|
678
810
|
return result;
|
|
679
811
|
} catch (error) {
|
|
680
812
|
span.setStatus({
|
|
681
|
-
code: SpanStatusCode.ERROR,
|
|
813
|
+
code: SpanStatusCode$1.ERROR,
|
|
682
814
|
message: error.message
|
|
683
815
|
});
|
|
684
816
|
span.recordException(error);
|
|
@@ -919,5 +1051,5 @@ function stopWorkerGauges() {
|
|
|
919
1051
|
}
|
|
920
1052
|
|
|
921
1053
|
//#endregion
|
|
922
|
-
export { removeBaggageEntry as C, EngineFunctions as D, DEFAULT_INVOCATION_TIMEOUT_MS as E, EngineTriggers as O, injectTraceparent as S, DEFAULT_BRIDGE_RECONNECTION_CONFIG as T, extractContext as _, SeverityNumber$1 as a, getBaggageEntry as b, getLogger as c, initOtel as d, shutdownOtel as f, extractBaggage as g, currentTraceId as h, safeStringify as i, LogFunctions as k, getMeter as l, currentSpanId as m, stopWorkerGauges as n, SpanKind as o, withSpan as p, WorkerMetricsCollector as r, SpanStatusCode as s, registerWorkerGauges as t, getTracer as u, extractTraceparent as v, setBaggageEntry as w, injectBaggage as x, getAllBaggage as y };
|
|
923
|
-
//# sourceMappingURL=otel-worker-gauges-
|
|
1054
|
+
export { removeBaggageEntry as C, EngineFunctions as D, DEFAULT_INVOCATION_TIMEOUT_MS as E, EngineTriggers as O, injectTraceparent as S, DEFAULT_BRIDGE_RECONNECTION_CONFIG as T, extractContext as _, SeverityNumber$1 as a, getBaggageEntry as b, getLogger as c, initOtel as d, shutdownOtel as f, extractBaggage as g, currentTraceId as h, safeStringify as i, LogFunctions as k, getMeter as l, currentSpanId as m, stopWorkerGauges as n, SpanKind$1 as o, withSpan as p, WorkerMetricsCollector as r, SpanStatusCode$1 as s, registerWorkerGauges as t, getTracer as u, extractTraceparent as v, setBaggageEntry as w, injectBaggage as x, getAllBaggage as y };
|
|
1055
|
+
//# sourceMappingURL=otel-worker-gauges-CHooGOLC.mjs.map
|