kafka-crab-js 4.0.0 → 4.1.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/README.md +5 -5
- package/dist/{base-kafka-stream-readable-I1xda63L.d.cts → base-kafka-stream-readable-D9sZX4xL.d.cts} +1 -1
- package/dist/{base-kafka-stream-readable-BokUK06Z.d.ts → base-kafka-stream-readable-D9sZX4xL.d.ts} +1 -1
- package/dist/{channels-QBobKRC2.d.ts → channels-CtCeIPbt.d.ts} +1 -1
- package/dist/{channels-CYQ4ni8K.d.cts → channels-DpT3Ilp7.d.cts} +1 -1
- package/dist/diagnostics/channels.cjs.map +1 -1
- package/dist/diagnostics/channels.d.cts +1 -1
- package/dist/diagnostics/channels.d.ts +1 -1
- package/dist/diagnostics/channels.js.map +1 -1
- package/dist/diagnostics/index.d.cts +2 -2
- package/dist/diagnostics/index.d.ts +2 -2
- package/dist/diagnostics/instrumentation.cjs.map +1 -1
- package/dist/diagnostics/instrumentation.d.cts +1 -1
- package/dist/diagnostics/instrumentation.d.ts +1 -1
- package/dist/diagnostics/instrumentation.js.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/{instrumentation-BiIPAe1B.d.cts → instrumentation-CGxc_url.d.cts} +1 -1
- package/dist/{instrumentation-CwoJPHwZ.d.ts → instrumentation-CGxc_url.d.ts} +1 -1
- package/dist/kafka-client.cjs.map +1 -1
- package/dist/kafka-client.js.map +1 -1
- package/dist/streams/base-kafka-stream-readable.cjs.map +1 -1
- package/dist/streams/base-kafka-stream-readable.d.cts +1 -1
- package/dist/streams/base-kafka-stream-readable.d.ts +1 -1
- package/dist/streams/base-kafka-stream-readable.js.map +1 -1
- package/dist/streams/kafka-batch-stream-readable.cjs.map +1 -1
- package/dist/streams/kafka-batch-stream-readable.d.cts +1 -1
- package/dist/streams/kafka-batch-stream-readable.d.ts +1 -1
- package/dist/streams/kafka-batch-stream-readable.js.map +1 -1
- package/dist/streams/kafka-stream-readable.cjs.map +1 -1
- package/dist/streams/kafka-stream-readable.d.cts +1 -1
- package/dist/streams/kafka-stream-readable.d.ts +1 -1
- package/dist/streams/kafka-stream-readable.js.map +1 -1
- package/js-binding.cjs +66 -56
- package/js-binding.js +66 -56
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -4,13 +4,13 @@ Kafka Crab JS is a native Kafka client for Node.js and TypeScript. It uses Rust,
|
|
|
4
4
|
JavaScript heap pressure, expose Kafka's mature native client behavior, and push high-throughput consumer workloads
|
|
5
5
|
through a small TypeScript-friendly API.
|
|
6
6
|
|
|
7
|
-
[](https://www.npmjs.com/package/kafka-crab-js)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
10
|
## Version 4
|
|
11
11
|
|
|
12
|
-
`kafka-crab-js` v4 is the current
|
|
13
|
-
and a cleaner monorepo release model under [`flash-tecnologia/crab-js`](https://github.com/flash-tecnologia/crab-js).
|
|
12
|
+
`kafka-crab-js` v4 is the current stable release line. It focuses on high-throughput consumers, lower JavaScript heap
|
|
13
|
+
pressure, and a cleaner monorepo release model under [`flash-tecnologia/crab-js`](https://github.com/flash-tecnologia/crab-js).
|
|
14
14
|
|
|
15
15
|
The main v4 additions are:
|
|
16
16
|
|
|
@@ -24,8 +24,8 @@ The main v4 additions are:
|
|
|
24
24
|
- Updated TypeScript exports where runtime enum-like values are now string literal types, avoiding missing runtime
|
|
25
25
|
exports in ESM/CommonJS consumers.
|
|
26
26
|
|
|
27
|
-
For production adoption,
|
|
28
|
-
|
|
27
|
+
For production adoption, validate v4 with your broker settings, payload sizes, partition count, commit strategy, and
|
|
28
|
+
shutdown path before replacing an existing Kafka client.
|
|
29
29
|
|
|
30
30
|
## Why Kafka Crab JS?
|
|
31
31
|
|
package/dist/{base-kafka-stream-readable-I1xda63L.d.cts → base-kafka-stream-readable-D9sZX4xL.d.cts}
RENAMED
|
@@ -66,4 +66,4 @@ declare abstract class BaseKafkaStreamReadable extends Readable {
|
|
|
66
66
|
}
|
|
67
67
|
//#endregion
|
|
68
68
|
export { KafkaStreamReadableOptions as n, BaseKafkaStreamReadable as t };
|
|
69
|
-
//# sourceMappingURL=base-kafka-stream-readable-
|
|
69
|
+
//# sourceMappingURL=base-kafka-stream-readable-D9sZX4xL.d.cts.map
|
package/dist/{base-kafka-stream-readable-BokUK06Z.d.ts → base-kafka-stream-readable-D9sZX4xL.d.ts}
RENAMED
|
@@ -66,4 +66,4 @@ declare abstract class BaseKafkaStreamReadable extends Readable {
|
|
|
66
66
|
}
|
|
67
67
|
//#endregion
|
|
68
68
|
export { KafkaStreamReadableOptions as n, BaseKafkaStreamReadable as t };
|
|
69
|
-
//# sourceMappingURL=base-kafka-stream-readable-
|
|
69
|
+
//# sourceMappingURL=base-kafka-stream-readable-D9sZX4xL.d.ts.map
|
|
@@ -130,4 +130,4 @@ declare const channels: {
|
|
|
130
130
|
};
|
|
131
131
|
//#endregion
|
|
132
132
|
export { consumerProcessStartChannel as C, producerSendErrorChannel as D, producerSendEndChannel as E, producerSendStartChannel as O, consumerProcessEndChannel as S, consumerReceiveStartChannel as T, batchProcessEndChannel as _, BatchReceiveStartEvent as a, batchReceiveStartChannel as b, ConsumerProcessEndEvent as c, ConsumerReceiveStartEvent as d, KafkaEvent as f, TypedChannel as g, ProducerSendStartEvent as h, BatchReceiveEndEvent as i, ConsumerProcessStartEvent as l, ProducerSendErrorEvent as m, BatchProcessEndEvent as n, CHANNEL_NAMES as o, ProducerSendEndEvent as p, BatchProcessStartEvent as r, ChannelName as s, BaseEvent as t, ConsumerReceiveEndEvent as u, batchProcessStartChannel as v, consumerReceiveEndChannel as w, channels as x, batchReceiveEndChannel as y };
|
|
133
|
-
//# sourceMappingURL=channels-
|
|
133
|
+
//# sourceMappingURL=channels-CtCeIPbt.d.ts.map
|
|
@@ -130,4 +130,4 @@ declare const channels: {
|
|
|
130
130
|
};
|
|
131
131
|
//#endregion
|
|
132
132
|
export { consumerProcessStartChannel as C, producerSendErrorChannel as D, producerSendEndChannel as E, producerSendStartChannel as O, consumerProcessEndChannel as S, consumerReceiveStartChannel as T, batchProcessEndChannel as _, BatchReceiveStartEvent as a, batchReceiveStartChannel as b, ConsumerProcessEndEvent as c, ConsumerReceiveStartEvent as d, KafkaEvent as f, TypedChannel as g, ProducerSendStartEvent as h, BatchReceiveEndEvent as i, ConsumerProcessStartEvent as l, ProducerSendErrorEvent as m, BatchProcessEndEvent as n, CHANNEL_NAMES as o, ProducerSendEndEvent as p, BatchProcessStartEvent as r, ChannelName as s, BaseEvent as t, ConsumerReceiveEndEvent as u, batchProcessStartChannel as v, consumerReceiveEndChannel as w, channels as x, batchReceiveEndChannel as y };
|
|
133
|
-
//# sourceMappingURL=channels-
|
|
133
|
+
//# sourceMappingURL=channels-DpT3Ilp7.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.cjs","names":[],"sources":["../../js-src/diagnostics/channels.ts"],"sourcesContent":["/**\n * Kafka Diagnostic Channels\n *\n * This module provides Node.js diagnostic channels for Kafka operations.\n * External observability tools (like OpenTelemetry adapters) can subscribe\n * to these channels to receive events without coupling to any specific\n * tracing/metrics implementation.\n *\n * @see https://nodejs.org/api/diagnostics_channel.html\n */\nimport { type Channel, channel } from 'node:diagnostics_channel'\nimport type { Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\n\n// -----------------------------------------------------------------------------\n// Channel Names\n// -----------------------------------------------------------------------------\n\nexport const CHANNEL_NAMES = {\n // Producer channels\n PRODUCER_SEND_START: 'kafka-crab:producer:send:start',\n PRODUCER_SEND_END: 'kafka-crab:producer:send:end',\n PRODUCER_SEND_ERROR: 'kafka-crab:producer:send:error',\n\n // Consumer channels\n CONSUMER_RECEIVE_START: 'kafka-crab:consumer:receive:start',\n CONSUMER_RECEIVE_END: 'kafka-crab:consumer:receive:end',\n CONSUMER_PROCESS_START: 'kafka-crab:consumer:process:start',\n CONSUMER_PROCESS_END: 'kafka-crab:consumer:process:end',\n\n // Batch channels\n BATCH_RECEIVE_START: 'kafka-crab:batch:receive:start',\n BATCH_RECEIVE_END: 'kafka-crab:batch:receive:end',\n BATCH_PROCESS_START: 'kafka-crab:batch:process:start',\n BATCH_PROCESS_END: 'kafka-crab:batch:process:end',\n} as const\n\nexport type ChannelName = (typeof CHANNEL_NAMES)[keyof typeof CHANNEL_NAMES]\n\n// -----------------------------------------------------------------------------\n// Event Payload Types\n// -----------------------------------------------------------------------------\n\n/**\n * Base event interface with common fields\n */\nexport interface BaseEvent {\n /** Timestamp when the event occurred (ms since epoch) */\n timestamp: number\n /** Client ID if available */\n clientId?: string\n /** Server address if configured */\n serverAddress?: string\n /** Server port if configured */\n serverPort?: number\n /**\n * Context object for adapters to attach data (e.g., spans).\n * Subscribers can mutate this to pass data between start/end events.\n */\n context: Record<PropertyKey, unknown>\n}\n\n// Producer Events\nexport interface ProducerSendStartEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n messageCount: number\n}\n\nexport interface ProducerSendEndEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n metadata?: RecordMetadata[]\n durationMs: number\n error?: Error\n}\n\nexport interface ProducerSendErrorEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n durationMs: number\n error: Error\n}\n\n// Consumer Events\nexport interface ConsumerReceiveStartEvent extends BaseEvent {\n groupId?: string\n}\n\nexport interface ConsumerReceiveEndEvent extends BaseEvent {\n message: Message | null\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface ConsumerProcessStartEvent extends BaseEvent {\n message: Message\n groupId?: string\n}\n\nexport interface ConsumerProcessEndEvent extends BaseEvent {\n message: Message\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Batch Events\nexport interface BatchReceiveStartEvent extends BaseEvent {\n groupId?: string\n requestedSize: number\n timeoutMs: number\n}\n\nexport interface BatchReceiveEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface BatchProcessStartEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n}\n\nexport interface BatchProcessEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Union type for all events\nexport type KafkaEvent =\n | ProducerSendStartEvent\n | ProducerSendEndEvent\n | ConsumerReceiveStartEvent\n | ConsumerReceiveEndEvent\n | ConsumerProcessStartEvent\n | ConsumerProcessEndEvent\n | BatchReceiveStartEvent\n | BatchReceiveEndEvent\n | BatchProcessStartEvent\n | BatchProcessEndEvent\n\n// -----------------------------------------------------------------------------\n// Channel Instances (Typed)\n// -----------------------------------------------------------------------------\n\n/**\n * Typed channel wrapper for type-safe publish/subscribe\n */\nexport interface TypedChannel<TEvent> {\n readonly name: string\n readonly channel: Channel\n hasSubscribers: boolean\n publish(event: TEvent): void\n subscribe(handler: (event: TEvent, name: string | symbol) => void): void\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void): void\n}\n\nfunction createTypedChannel<TEvent>(name: string): TypedChannel<TEvent> {\n const ch = channel(name)\n return {\n name,\n channel: ch,\n get hasSubscribers() {\n return ch.hasSubscribers\n },\n publish(event: TEvent) {\n ch.publish(event)\n },\n subscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.subscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.unsubscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n }\n}\n\n// Producer channels\nexport const producerSendStartChannel = createTypedChannel<ProducerSendStartEvent>(CHANNEL_NAMES.PRODUCER_SEND_START)\nexport const producerSendEndChannel = createTypedChannel<ProducerSendEndEvent>(CHANNEL_NAMES.PRODUCER_SEND_END)\nexport const producerSendErrorChannel = createTypedChannel<ProducerSendErrorEvent>(CHANNEL_NAMES.PRODUCER_SEND_ERROR)\n\n// Consumer channels\nexport const consumerReceiveStartChannel = createTypedChannel<ConsumerReceiveStartEvent>(\n CHANNEL_NAMES.CONSUMER_RECEIVE_START,\n)\nexport const consumerReceiveEndChannel = createTypedChannel<ConsumerReceiveEndEvent>(CHANNEL_NAMES.CONSUMER_RECEIVE_END)\nexport const consumerProcessStartChannel = createTypedChannel<ConsumerProcessStartEvent>(\n CHANNEL_NAMES.CONSUMER_PROCESS_START,\n)\nexport const consumerProcessEndChannel = createTypedChannel<ConsumerProcessEndEvent>(CHANNEL_NAMES.CONSUMER_PROCESS_END)\n\n// Batch channels\nexport const batchReceiveStartChannel = createTypedChannel<BatchReceiveStartEvent>(CHANNEL_NAMES.BATCH_RECEIVE_START)\nexport const batchReceiveEndChannel = createTypedChannel<BatchReceiveEndEvent>(CHANNEL_NAMES.BATCH_RECEIVE_END)\nexport const batchProcessStartChannel = createTypedChannel<BatchProcessStartEvent>(CHANNEL_NAMES.BATCH_PROCESS_START)\nexport const batchProcessEndChannel = createTypedChannel<BatchProcessEndEvent>(CHANNEL_NAMES.BATCH_PROCESS_END)\n\n// All channels exported as a single object for convenience\nexport const channels = {\n producerSendStart: producerSendStartChannel,\n producerSendEnd: producerSendEndChannel,\n producerSendError: producerSendErrorChannel,\n consumerReceiveStart: consumerReceiveStartChannel,\n consumerReceiveEnd: consumerReceiveEndChannel,\n consumerProcessStart: consumerProcessStartChannel,\n consumerProcessEnd: consumerProcessEndChannel,\n batchReceiveStart: batchReceiveStartChannel,\n batchReceiveEnd: batchReceiveEndChannel,\n batchProcessStart: batchProcessStartChannel,\n batchProcessEnd: batchProcessEndChannel,\n} as const\n"],"mappings":";;;;;;;;;;;;;AAiBA,MAAa,gBAAgB;CAE3B,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CAGrB,wBAAwB;CACxB,sBAAsB;CACtB,wBAAwB;CACxB,sBAAsB;CAGtB,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CACrB,mBAAmB;
|
|
1
|
+
{"version":3,"file":"channels.cjs","names":[],"sources":["../../js-src/diagnostics/channels.ts"],"sourcesContent":["/**\n * Kafka Diagnostic Channels\n *\n * This module provides Node.js diagnostic channels for Kafka operations.\n * External observability tools (like OpenTelemetry adapters) can subscribe\n * to these channels to receive events without coupling to any specific\n * tracing/metrics implementation.\n *\n * @see https://nodejs.org/api/diagnostics_channel.html\n */\nimport { type Channel, channel } from 'node:diagnostics_channel'\nimport type { Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\n\n// -----------------------------------------------------------------------------\n// Channel Names\n// -----------------------------------------------------------------------------\n\nexport const CHANNEL_NAMES = {\n // Producer channels\n PRODUCER_SEND_START: 'kafka-crab:producer:send:start',\n PRODUCER_SEND_END: 'kafka-crab:producer:send:end',\n PRODUCER_SEND_ERROR: 'kafka-crab:producer:send:error',\n\n // Consumer channels\n CONSUMER_RECEIVE_START: 'kafka-crab:consumer:receive:start',\n CONSUMER_RECEIVE_END: 'kafka-crab:consumer:receive:end',\n CONSUMER_PROCESS_START: 'kafka-crab:consumer:process:start',\n CONSUMER_PROCESS_END: 'kafka-crab:consumer:process:end',\n\n // Batch channels\n BATCH_RECEIVE_START: 'kafka-crab:batch:receive:start',\n BATCH_RECEIVE_END: 'kafka-crab:batch:receive:end',\n BATCH_PROCESS_START: 'kafka-crab:batch:process:start',\n BATCH_PROCESS_END: 'kafka-crab:batch:process:end',\n} as const\n\nexport type ChannelName = (typeof CHANNEL_NAMES)[keyof typeof CHANNEL_NAMES]\n\n// -----------------------------------------------------------------------------\n// Event Payload Types\n// -----------------------------------------------------------------------------\n\n/**\n * Base event interface with common fields\n */\nexport interface BaseEvent {\n /** Timestamp when the event occurred (ms since epoch) */\n timestamp: number\n /** Client ID if available */\n clientId?: string\n /** Server address if configured */\n serverAddress?: string\n /** Server port if configured */\n serverPort?: number\n /**\n * Context object for adapters to attach data (e.g., spans).\n * Subscribers can mutate this to pass data between start/end events.\n */\n context: Record<PropertyKey, unknown>\n}\n\n// Producer Events\nexport interface ProducerSendStartEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n messageCount: number\n}\n\nexport interface ProducerSendEndEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n metadata?: RecordMetadata[]\n durationMs: number\n error?: Error\n}\n\nexport interface ProducerSendErrorEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n durationMs: number\n error: Error\n}\n\n// Consumer Events\nexport interface ConsumerReceiveStartEvent extends BaseEvent {\n groupId?: string\n}\n\nexport interface ConsumerReceiveEndEvent extends BaseEvent {\n message: Message | null\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface ConsumerProcessStartEvent extends BaseEvent {\n message: Message\n groupId?: string\n}\n\nexport interface ConsumerProcessEndEvent extends BaseEvent {\n message: Message\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Batch Events\nexport interface BatchReceiveStartEvent extends BaseEvent {\n groupId?: string\n requestedSize: number\n timeoutMs: number\n}\n\nexport interface BatchReceiveEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface BatchProcessStartEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n}\n\nexport interface BatchProcessEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Union type for all events\nexport type KafkaEvent =\n | ProducerSendStartEvent\n | ProducerSendEndEvent\n | ConsumerReceiveStartEvent\n | ConsumerReceiveEndEvent\n | ConsumerProcessStartEvent\n | ConsumerProcessEndEvent\n | BatchReceiveStartEvent\n | BatchReceiveEndEvent\n | BatchProcessStartEvent\n | BatchProcessEndEvent\n\n// -----------------------------------------------------------------------------\n// Channel Instances (Typed)\n// -----------------------------------------------------------------------------\n\n/**\n * Typed channel wrapper for type-safe publish/subscribe\n */\nexport interface TypedChannel<TEvent> {\n readonly name: string\n readonly channel: Channel\n hasSubscribers: boolean\n publish(event: TEvent): void\n subscribe(handler: (event: TEvent, name: string | symbol) => void): void\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void): void\n}\n\nfunction createTypedChannel<TEvent>(name: string): TypedChannel<TEvent> {\n const ch = channel(name)\n return {\n name,\n channel: ch,\n get hasSubscribers() {\n return ch.hasSubscribers\n },\n publish(event: TEvent) {\n ch.publish(event)\n },\n subscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.subscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.unsubscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n }\n}\n\n// Producer channels\nexport const producerSendStartChannel = createTypedChannel<ProducerSendStartEvent>(CHANNEL_NAMES.PRODUCER_SEND_START)\nexport const producerSendEndChannel = createTypedChannel<ProducerSendEndEvent>(CHANNEL_NAMES.PRODUCER_SEND_END)\nexport const producerSendErrorChannel = createTypedChannel<ProducerSendErrorEvent>(CHANNEL_NAMES.PRODUCER_SEND_ERROR)\n\n// Consumer channels\nexport const consumerReceiveStartChannel = createTypedChannel<ConsumerReceiveStartEvent>(\n CHANNEL_NAMES.CONSUMER_RECEIVE_START,\n)\nexport const consumerReceiveEndChannel = createTypedChannel<ConsumerReceiveEndEvent>(CHANNEL_NAMES.CONSUMER_RECEIVE_END)\nexport const consumerProcessStartChannel = createTypedChannel<ConsumerProcessStartEvent>(\n CHANNEL_NAMES.CONSUMER_PROCESS_START,\n)\nexport const consumerProcessEndChannel = createTypedChannel<ConsumerProcessEndEvent>(CHANNEL_NAMES.CONSUMER_PROCESS_END)\n\n// Batch channels\nexport const batchReceiveStartChannel = createTypedChannel<BatchReceiveStartEvent>(CHANNEL_NAMES.BATCH_RECEIVE_START)\nexport const batchReceiveEndChannel = createTypedChannel<BatchReceiveEndEvent>(CHANNEL_NAMES.BATCH_RECEIVE_END)\nexport const batchProcessStartChannel = createTypedChannel<BatchProcessStartEvent>(CHANNEL_NAMES.BATCH_PROCESS_START)\nexport const batchProcessEndChannel = createTypedChannel<BatchProcessEndEvent>(CHANNEL_NAMES.BATCH_PROCESS_END)\n\n// All channels exported as a single object for convenience\nexport const channels = {\n producerSendStart: producerSendStartChannel,\n producerSendEnd: producerSendEndChannel,\n producerSendError: producerSendErrorChannel,\n consumerReceiveStart: consumerReceiveStartChannel,\n consumerReceiveEnd: consumerReceiveEndChannel,\n consumerProcessStart: consumerProcessStartChannel,\n consumerProcessEnd: consumerProcessEndChannel,\n batchReceiveStart: batchReceiveStartChannel,\n batchReceiveEnd: batchReceiveEndChannel,\n batchProcessStart: batchProcessStartChannel,\n batchProcessEnd: batchProcessEndChannel,\n} as const\n"],"mappings":";;;;;;;;;;;;;AAiBA,MAAa,gBAAgB;CAE3B,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CAGrB,wBAAwB;CACxB,sBAAsB;CACtB,wBAAwB;CACxB,sBAAsB;CAGtB,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CACrB,mBAAmB;AACrB;AAgIA,SAAS,mBAA2B,MAAoC;CACtE,MAAM,MAAA,GAAA,yBAAA,SAAa,IAAI;CACvB,OAAO;EACL;EACA,SAAS;EACT,IAAI,iBAAiB;GACnB,OAAO,GAAG;EACZ;EACA,QAAQ,OAAe;GACrB,GAAG,QAAQ,KAAK;EAClB;EACA,UAAU,SAAyD;GACjE,GAAG,UAAU,OAA4D;EAC3E;EACA,YAAY,SAAyD;GACnE,GAAG,YAAY,OAA4D;EAC7E;CACF;AACF;AAGA,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AACpH,MAAa,yBAAyB,mBAAyC,cAAc,iBAAiB;AAC9G,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AAGpH,MAAa,8BAA8B,mBACzC,cAAc,sBAChB;AACA,MAAa,4BAA4B,mBAA4C,cAAc,oBAAoB;AACvH,MAAa,8BAA8B,mBACzC,cAAc,sBAChB;AACA,MAAa,4BAA4B,mBAA4C,cAAc,oBAAoB;AAGvH,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AACpH,MAAa,yBAAyB,mBAAyC,cAAc,iBAAiB;AAC9G,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AACpH,MAAa,yBAAyB,mBAAyC,cAAc,iBAAiB;AAG9G,MAAa,WAAW;CACtB,mBAAmB;CACnB,iBAAiB;CACjB,mBAAmB;CACnB,sBAAsB;CACtB,oBAAoB;CACpB,sBAAsB;CACtB,oBAAoB;CACpB,mBAAmB;CACnB,iBAAiB;CACjB,mBAAmB;CACnB,iBAAiB;AACnB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-
|
|
1
|
+
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-DpT3Ilp7.cjs";
|
|
2
2
|
export { BaseEvent, BatchProcessEndEvent, BatchProcessStartEvent, BatchReceiveEndEvent, BatchReceiveStartEvent, CHANNEL_NAMES, ChannelName, ConsumerProcessEndEvent, ConsumerProcessStartEvent, ConsumerReceiveEndEvent, ConsumerReceiveStartEvent, KafkaEvent, ProducerSendEndEvent, ProducerSendErrorEvent, ProducerSendStartEvent, TypedChannel, batchProcessEndChannel, batchProcessStartChannel, batchReceiveEndChannel, batchReceiveStartChannel, channels, consumerProcessEndChannel, consumerProcessStartChannel, consumerReceiveEndChannel, consumerReceiveStartChannel, producerSendEndChannel, producerSendErrorChannel, producerSendStartChannel };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-
|
|
1
|
+
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-CtCeIPbt.js";
|
|
2
2
|
export { BaseEvent, BatchProcessEndEvent, BatchProcessStartEvent, BatchReceiveEndEvent, BatchReceiveStartEvent, CHANNEL_NAMES, ChannelName, ConsumerProcessEndEvent, ConsumerProcessStartEvent, ConsumerReceiveEndEvent, ConsumerReceiveStartEvent, KafkaEvent, ProducerSendEndEvent, ProducerSendErrorEvent, ProducerSendStartEvent, TypedChannel, batchProcessEndChannel, batchProcessStartChannel, batchReceiveEndChannel, batchReceiveStartChannel, channels, consumerProcessEndChannel, consumerProcessStartChannel, consumerReceiveEndChannel, consumerReceiveStartChannel, producerSendEndChannel, producerSendErrorChannel, producerSendStartChannel };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.js","names":[],"sources":["../../js-src/diagnostics/channels.ts"],"sourcesContent":["/**\n * Kafka Diagnostic Channels\n *\n * This module provides Node.js diagnostic channels for Kafka operations.\n * External observability tools (like OpenTelemetry adapters) can subscribe\n * to these channels to receive events without coupling to any specific\n * tracing/metrics implementation.\n *\n * @see https://nodejs.org/api/diagnostics_channel.html\n */\nimport { type Channel, channel } from 'node:diagnostics_channel'\nimport type { Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\n\n// -----------------------------------------------------------------------------\n// Channel Names\n// -----------------------------------------------------------------------------\n\nexport const CHANNEL_NAMES = {\n // Producer channels\n PRODUCER_SEND_START: 'kafka-crab:producer:send:start',\n PRODUCER_SEND_END: 'kafka-crab:producer:send:end',\n PRODUCER_SEND_ERROR: 'kafka-crab:producer:send:error',\n\n // Consumer channels\n CONSUMER_RECEIVE_START: 'kafka-crab:consumer:receive:start',\n CONSUMER_RECEIVE_END: 'kafka-crab:consumer:receive:end',\n CONSUMER_PROCESS_START: 'kafka-crab:consumer:process:start',\n CONSUMER_PROCESS_END: 'kafka-crab:consumer:process:end',\n\n // Batch channels\n BATCH_RECEIVE_START: 'kafka-crab:batch:receive:start',\n BATCH_RECEIVE_END: 'kafka-crab:batch:receive:end',\n BATCH_PROCESS_START: 'kafka-crab:batch:process:start',\n BATCH_PROCESS_END: 'kafka-crab:batch:process:end',\n} as const\n\nexport type ChannelName = (typeof CHANNEL_NAMES)[keyof typeof CHANNEL_NAMES]\n\n// -----------------------------------------------------------------------------\n// Event Payload Types\n// -----------------------------------------------------------------------------\n\n/**\n * Base event interface with common fields\n */\nexport interface BaseEvent {\n /** Timestamp when the event occurred (ms since epoch) */\n timestamp: number\n /** Client ID if available */\n clientId?: string\n /** Server address if configured */\n serverAddress?: string\n /** Server port if configured */\n serverPort?: number\n /**\n * Context object for adapters to attach data (e.g., spans).\n * Subscribers can mutate this to pass data between start/end events.\n */\n context: Record<PropertyKey, unknown>\n}\n\n// Producer Events\nexport interface ProducerSendStartEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n messageCount: number\n}\n\nexport interface ProducerSendEndEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n metadata?: RecordMetadata[]\n durationMs: number\n error?: Error\n}\n\nexport interface ProducerSendErrorEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n durationMs: number\n error: Error\n}\n\n// Consumer Events\nexport interface ConsumerReceiveStartEvent extends BaseEvent {\n groupId?: string\n}\n\nexport interface ConsumerReceiveEndEvent extends BaseEvent {\n message: Message | null\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface ConsumerProcessStartEvent extends BaseEvent {\n message: Message\n groupId?: string\n}\n\nexport interface ConsumerProcessEndEvent extends BaseEvent {\n message: Message\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Batch Events\nexport interface BatchReceiveStartEvent extends BaseEvent {\n groupId?: string\n requestedSize: number\n timeoutMs: number\n}\n\nexport interface BatchReceiveEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface BatchProcessStartEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n}\n\nexport interface BatchProcessEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Union type for all events\nexport type KafkaEvent =\n | ProducerSendStartEvent\n | ProducerSendEndEvent\n | ConsumerReceiveStartEvent\n | ConsumerReceiveEndEvent\n | ConsumerProcessStartEvent\n | ConsumerProcessEndEvent\n | BatchReceiveStartEvent\n | BatchReceiveEndEvent\n | BatchProcessStartEvent\n | BatchProcessEndEvent\n\n// -----------------------------------------------------------------------------\n// Channel Instances (Typed)\n// -----------------------------------------------------------------------------\n\n/**\n * Typed channel wrapper for type-safe publish/subscribe\n */\nexport interface TypedChannel<TEvent> {\n readonly name: string\n readonly channel: Channel\n hasSubscribers: boolean\n publish(event: TEvent): void\n subscribe(handler: (event: TEvent, name: string | symbol) => void): void\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void): void\n}\n\nfunction createTypedChannel<TEvent>(name: string): TypedChannel<TEvent> {\n const ch = channel(name)\n return {\n name,\n channel: ch,\n get hasSubscribers() {\n return ch.hasSubscribers\n },\n publish(event: TEvent) {\n ch.publish(event)\n },\n subscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.subscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.unsubscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n }\n}\n\n// Producer channels\nexport const producerSendStartChannel = createTypedChannel<ProducerSendStartEvent>(CHANNEL_NAMES.PRODUCER_SEND_START)\nexport const producerSendEndChannel = createTypedChannel<ProducerSendEndEvent>(CHANNEL_NAMES.PRODUCER_SEND_END)\nexport const producerSendErrorChannel = createTypedChannel<ProducerSendErrorEvent>(CHANNEL_NAMES.PRODUCER_SEND_ERROR)\n\n// Consumer channels\nexport const consumerReceiveStartChannel = createTypedChannel<ConsumerReceiveStartEvent>(\n CHANNEL_NAMES.CONSUMER_RECEIVE_START,\n)\nexport const consumerReceiveEndChannel = createTypedChannel<ConsumerReceiveEndEvent>(CHANNEL_NAMES.CONSUMER_RECEIVE_END)\nexport const consumerProcessStartChannel = createTypedChannel<ConsumerProcessStartEvent>(\n CHANNEL_NAMES.CONSUMER_PROCESS_START,\n)\nexport const consumerProcessEndChannel = createTypedChannel<ConsumerProcessEndEvent>(CHANNEL_NAMES.CONSUMER_PROCESS_END)\n\n// Batch channels\nexport const batchReceiveStartChannel = createTypedChannel<BatchReceiveStartEvent>(CHANNEL_NAMES.BATCH_RECEIVE_START)\nexport const batchReceiveEndChannel = createTypedChannel<BatchReceiveEndEvent>(CHANNEL_NAMES.BATCH_RECEIVE_END)\nexport const batchProcessStartChannel = createTypedChannel<BatchProcessStartEvent>(CHANNEL_NAMES.BATCH_PROCESS_START)\nexport const batchProcessEndChannel = createTypedChannel<BatchProcessEndEvent>(CHANNEL_NAMES.BATCH_PROCESS_END)\n\n// All channels exported as a single object for convenience\nexport const channels = {\n producerSendStart: producerSendStartChannel,\n producerSendEnd: producerSendEndChannel,\n producerSendError: producerSendErrorChannel,\n consumerReceiveStart: consumerReceiveStartChannel,\n consumerReceiveEnd: consumerReceiveEndChannel,\n consumerProcessStart: consumerProcessStartChannel,\n consumerProcessEnd: consumerProcessEndChannel,\n batchReceiveStart: batchReceiveStartChannel,\n batchReceiveEnd: batchReceiveEndChannel,\n batchProcessStart: batchProcessStartChannel,\n batchProcessEnd: batchProcessEndChannel,\n} as const\n"],"mappings":";;;;;;;;;;;;AAiBA,MAAa,gBAAgB;CAE3B,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CAGrB,wBAAwB;CACxB,sBAAsB;CACtB,wBAAwB;CACxB,sBAAsB;CAGtB,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CACrB,mBAAmB;
|
|
1
|
+
{"version":3,"file":"channels.js","names":[],"sources":["../../js-src/diagnostics/channels.ts"],"sourcesContent":["/**\n * Kafka Diagnostic Channels\n *\n * This module provides Node.js diagnostic channels for Kafka operations.\n * External observability tools (like OpenTelemetry adapters) can subscribe\n * to these channels to receive events without coupling to any specific\n * tracing/metrics implementation.\n *\n * @see https://nodejs.org/api/diagnostics_channel.html\n */\nimport { type Channel, channel } from 'node:diagnostics_channel'\nimport type { Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\n\n// -----------------------------------------------------------------------------\n// Channel Names\n// -----------------------------------------------------------------------------\n\nexport const CHANNEL_NAMES = {\n // Producer channels\n PRODUCER_SEND_START: 'kafka-crab:producer:send:start',\n PRODUCER_SEND_END: 'kafka-crab:producer:send:end',\n PRODUCER_SEND_ERROR: 'kafka-crab:producer:send:error',\n\n // Consumer channels\n CONSUMER_RECEIVE_START: 'kafka-crab:consumer:receive:start',\n CONSUMER_RECEIVE_END: 'kafka-crab:consumer:receive:end',\n CONSUMER_PROCESS_START: 'kafka-crab:consumer:process:start',\n CONSUMER_PROCESS_END: 'kafka-crab:consumer:process:end',\n\n // Batch channels\n BATCH_RECEIVE_START: 'kafka-crab:batch:receive:start',\n BATCH_RECEIVE_END: 'kafka-crab:batch:receive:end',\n BATCH_PROCESS_START: 'kafka-crab:batch:process:start',\n BATCH_PROCESS_END: 'kafka-crab:batch:process:end',\n} as const\n\nexport type ChannelName = (typeof CHANNEL_NAMES)[keyof typeof CHANNEL_NAMES]\n\n// -----------------------------------------------------------------------------\n// Event Payload Types\n// -----------------------------------------------------------------------------\n\n/**\n * Base event interface with common fields\n */\nexport interface BaseEvent {\n /** Timestamp when the event occurred (ms since epoch) */\n timestamp: number\n /** Client ID if available */\n clientId?: string\n /** Server address if configured */\n serverAddress?: string\n /** Server port if configured */\n serverPort?: number\n /**\n * Context object for adapters to attach data (e.g., spans).\n * Subscribers can mutate this to pass data between start/end events.\n */\n context: Record<PropertyKey, unknown>\n}\n\n// Producer Events\nexport interface ProducerSendStartEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n messageCount: number\n}\n\nexport interface ProducerSendEndEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n metadata?: RecordMetadata[]\n durationMs: number\n error?: Error\n}\n\nexport interface ProducerSendErrorEvent extends BaseEvent {\n topic: string\n record: ProducerRecord\n durationMs: number\n error: Error\n}\n\n// Consumer Events\nexport interface ConsumerReceiveStartEvent extends BaseEvent {\n groupId?: string\n}\n\nexport interface ConsumerReceiveEndEvent extends BaseEvent {\n message: Message | null\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface ConsumerProcessStartEvent extends BaseEvent {\n message: Message\n groupId?: string\n}\n\nexport interface ConsumerProcessEndEvent extends BaseEvent {\n message: Message\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Batch Events\nexport interface BatchReceiveStartEvent extends BaseEvent {\n groupId?: string\n requestedSize: number\n timeoutMs: number\n}\n\nexport interface BatchReceiveEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\nexport interface BatchProcessStartEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n}\n\nexport interface BatchProcessEndEvent extends BaseEvent {\n messages: Message[]\n groupId?: string\n durationMs: number\n error?: Error\n}\n\n// Union type for all events\nexport type KafkaEvent =\n | ProducerSendStartEvent\n | ProducerSendEndEvent\n | ConsumerReceiveStartEvent\n | ConsumerReceiveEndEvent\n | ConsumerProcessStartEvent\n | ConsumerProcessEndEvent\n | BatchReceiveStartEvent\n | BatchReceiveEndEvent\n | BatchProcessStartEvent\n | BatchProcessEndEvent\n\n// -----------------------------------------------------------------------------\n// Channel Instances (Typed)\n// -----------------------------------------------------------------------------\n\n/**\n * Typed channel wrapper for type-safe publish/subscribe\n */\nexport interface TypedChannel<TEvent> {\n readonly name: string\n readonly channel: Channel\n hasSubscribers: boolean\n publish(event: TEvent): void\n subscribe(handler: (event: TEvent, name: string | symbol) => void): void\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void): void\n}\n\nfunction createTypedChannel<TEvent>(name: string): TypedChannel<TEvent> {\n const ch = channel(name)\n return {\n name,\n channel: ch,\n get hasSubscribers() {\n return ch.hasSubscribers\n },\n publish(event: TEvent) {\n ch.publish(event)\n },\n subscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.subscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n unsubscribe(handler: (event: TEvent, name: string | symbol) => void) {\n ch.unsubscribe(handler as (message: unknown, name: string | symbol) => void)\n },\n }\n}\n\n// Producer channels\nexport const producerSendStartChannel = createTypedChannel<ProducerSendStartEvent>(CHANNEL_NAMES.PRODUCER_SEND_START)\nexport const producerSendEndChannel = createTypedChannel<ProducerSendEndEvent>(CHANNEL_NAMES.PRODUCER_SEND_END)\nexport const producerSendErrorChannel = createTypedChannel<ProducerSendErrorEvent>(CHANNEL_NAMES.PRODUCER_SEND_ERROR)\n\n// Consumer channels\nexport const consumerReceiveStartChannel = createTypedChannel<ConsumerReceiveStartEvent>(\n CHANNEL_NAMES.CONSUMER_RECEIVE_START,\n)\nexport const consumerReceiveEndChannel = createTypedChannel<ConsumerReceiveEndEvent>(CHANNEL_NAMES.CONSUMER_RECEIVE_END)\nexport const consumerProcessStartChannel = createTypedChannel<ConsumerProcessStartEvent>(\n CHANNEL_NAMES.CONSUMER_PROCESS_START,\n)\nexport const consumerProcessEndChannel = createTypedChannel<ConsumerProcessEndEvent>(CHANNEL_NAMES.CONSUMER_PROCESS_END)\n\n// Batch channels\nexport const batchReceiveStartChannel = createTypedChannel<BatchReceiveStartEvent>(CHANNEL_NAMES.BATCH_RECEIVE_START)\nexport const batchReceiveEndChannel = createTypedChannel<BatchReceiveEndEvent>(CHANNEL_NAMES.BATCH_RECEIVE_END)\nexport const batchProcessStartChannel = createTypedChannel<BatchProcessStartEvent>(CHANNEL_NAMES.BATCH_PROCESS_START)\nexport const batchProcessEndChannel = createTypedChannel<BatchProcessEndEvent>(CHANNEL_NAMES.BATCH_PROCESS_END)\n\n// All channels exported as a single object for convenience\nexport const channels = {\n producerSendStart: producerSendStartChannel,\n producerSendEnd: producerSendEndChannel,\n producerSendError: producerSendErrorChannel,\n consumerReceiveStart: consumerReceiveStartChannel,\n consumerReceiveEnd: consumerReceiveEndChannel,\n consumerProcessStart: consumerProcessStartChannel,\n consumerProcessEnd: consumerProcessEndChannel,\n batchReceiveStart: batchReceiveStartChannel,\n batchReceiveEnd: batchReceiveEndChannel,\n batchProcessStart: batchProcessStartChannel,\n batchProcessEnd: batchProcessEndChannel,\n} as const\n"],"mappings":";;;;;;;;;;;;AAiBA,MAAa,gBAAgB;CAE3B,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CAGrB,wBAAwB;CACxB,sBAAsB;CACtB,wBAAwB;CACxB,sBAAsB;CAGtB,qBAAqB;CACrB,mBAAmB;CACnB,qBAAqB;CACrB,mBAAmB;AACrB;AAgIA,SAAS,mBAA2B,MAAoC;CACtE,MAAM,KAAK,QAAQ,IAAI;CACvB,OAAO;EACL;EACA,SAAS;EACT,IAAI,iBAAiB;GACnB,OAAO,GAAG;EACZ;EACA,QAAQ,OAAe;GACrB,GAAG,QAAQ,KAAK;EAClB;EACA,UAAU,SAAyD;GACjE,GAAG,UAAU,OAA4D;EAC3E;EACA,YAAY,SAAyD;GACnE,GAAG,YAAY,OAA4D;EAC7E;CACF;AACF;AAGA,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AACpH,MAAa,yBAAyB,mBAAyC,cAAc,iBAAiB;AAC9G,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AAGpH,MAAa,8BAA8B,mBACzC,cAAc,sBAChB;AACA,MAAa,4BAA4B,mBAA4C,cAAc,oBAAoB;AACvH,MAAa,8BAA8B,mBACzC,cAAc,sBAChB;AACA,MAAa,4BAA4B,mBAA4C,cAAc,oBAAoB;AAGvH,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AACpH,MAAa,yBAAyB,mBAAyC,cAAc,iBAAiB;AAC9G,MAAa,2BAA2B,mBAA2C,cAAc,mBAAmB;AACpH,MAAa,yBAAyB,mBAAyC,cAAc,iBAAiB;AAG9G,MAAa,WAAW;CACtB,mBAAmB;CACnB,iBAAiB;CACjB,mBAAmB;CACnB,sBAAsB;CACtB,oBAAoB;CACpB,sBAAsB;CACtB,oBAAoB;CACpB,mBAAmB;CACnB,iBAAiB;CACjB,mBAAmB;CACnB,iBAAiB;AACnB"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-
|
|
2
|
-
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-
|
|
1
|
+
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-DpT3Ilp7.cjs";
|
|
2
|
+
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-CGxc_url.cjs";
|
|
3
3
|
export { type BaseEvent, type BatchProcessEndEvent, type BatchProcessStartEvent, type BatchReceiveEndEvent, type BatchReceiveStartEvent, CHANNEL_NAMES, type ChannelName, type ConsumerProcessEndEvent, type ConsumerProcessStartEvent, type ConsumerReceiveEndEvent, type ConsumerReceiveStartEvent, type DiagnosticInstrumentationConfig, type KafkaEvent, type ProducerSendEndEvent, type ProducerSendErrorEvent, type ProducerSendStartEvent, type TypedChannel, batchProcessEndChannel, batchProcessStartChannel, batchReceiveEndChannel, batchReceiveStartChannel, channels, consumerProcessEndChannel, consumerProcessStartChannel, consumerReceiveEndChannel, consumerReceiveStartChannel, instrumentBatchReadableStream, instrumentBatchReceive, instrumentConsumerReadableStream, instrumentConsumerReceive, instrumentProducerSend, producerSendEndChannel, producerSendErrorChannel, producerSendStartChannel };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-
|
|
2
|
-
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-
|
|
1
|
+
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, f as KafkaEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "../channels-CtCeIPbt.js";
|
|
2
|
+
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-CGxc_url.js";
|
|
3
3
|
export { type BaseEvent, type BatchProcessEndEvent, type BatchProcessStartEvent, type BatchReceiveEndEvent, type BatchReceiveStartEvent, CHANNEL_NAMES, type ChannelName, type ConsumerProcessEndEvent, type ConsumerProcessStartEvent, type ConsumerReceiveEndEvent, type ConsumerReceiveStartEvent, type DiagnosticInstrumentationConfig, type KafkaEvent, type ProducerSendEndEvent, type ProducerSendErrorEvent, type ProducerSendStartEvent, type TypedChannel, batchProcessEndChannel, batchProcessStartChannel, batchReceiveEndChannel, batchReceiveStartChannel, channels, consumerProcessEndChannel, consumerProcessStartChannel, consumerReceiveEndChannel, consumerReceiveStartChannel, instrumentBatchReadableStream, instrumentBatchReceive, instrumentConsumerReadableStream, instrumentConsumerReceive, instrumentProducerSend, producerSendEndChannel, producerSendErrorChannel, producerSendStartChannel };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.cjs","names":["producerSendStartChannel","producerSendEndChannel","producerSendErrorChannel","consumerReceiveStartChannel","consumerReceiveEndChannel","consumerProcessStartChannel","consumerProcessEndChannel","batchReceiveStartChannel","batchReceiveEndChannel","batchProcessStartChannel","batchProcessEndChannel"],"sources":["../../js-src/diagnostics/instrumentation.ts"],"sourcesContent":["/**\n * Diagnostic Channel-based Kafka Instrumentation\n *\n * This module provides instrumentation that publishes events to Node.js\n * diagnostic channels instead of directly calling OpenTelemetry APIs.\n * Observability tools can subscribe to these channels to receive events.\n */\nimport type { KafkaConsumer, KafkaProducer, Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\nimport {\n batchProcessEndChannel,\n type BatchProcessEndEvent,\n batchProcessStartChannel,\n type BatchProcessStartEvent,\n batchReceiveEndChannel,\n type BatchReceiveEndEvent,\n batchReceiveStartChannel,\n type BatchReceiveStartEvent,\n consumerProcessEndChannel,\n type ConsumerProcessEndEvent,\n consumerProcessStartChannel,\n type ConsumerProcessStartEvent,\n consumerReceiveEndChannel,\n type ConsumerReceiveEndEvent,\n consumerReceiveStartChannel,\n type ConsumerReceiveStartEvent,\n producerSendEndChannel,\n type ProducerSendEndEvent,\n producerSendErrorChannel,\n type ProducerSendErrorEvent,\n producerSendStartChannel,\n type ProducerSendStartEvent,\n} from './channels.js'\n\n/**\n * Configuration for diagnostic channel instrumentation\n */\nexport interface DiagnosticInstrumentationConfig {\n /** Client ID for attribution */\n clientId?: string\n /** Server address for attribution */\n serverAddress?: string\n /** Server port for attribution */\n serverPort?: number\n}\n\n/**\n * Instruments a producer send method to publish diagnostic events\n */\nexport function instrumentProducerSend(\n originalSend: (record: ProducerRecord) => Promise<RecordMetadata[]>,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaProducer, record: ProducerRecord) => Promise<RecordMetadata[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedSend(this: KafkaProducer, record: ProducerRecord) {\n // Fast path: if no subscribers, just call original\n if (\n !producerSendStartChannel.hasSubscribers &&\n !producerSendEndChannel.hasSubscribers &&\n !producerSendErrorChannel.hasSubscribers\n ) {\n return originalSend.call(this, record)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n const startEvent: ProducerSendStartEvent = {\n timestamp,\n topic: record.topic,\n record,\n messageCount: record.messages?.length ?? 0,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n\n // Publish start event - subscribers can inject trace headers here\n if (producerSendStartChannel.hasSubscribers) {\n producerSendStartChannel.publish(startEvent)\n }\n\n let sendError: Error | undefined\n let metadata: RecordMetadata[] | undefined\n\n try {\n metadata = await originalSend.call(this, record)\n return metadata\n } catch (error) {\n sendError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n const durationMs = Date.now() - timestamp\n\n if (sendError && producerSendErrorChannel.hasSubscribers) {\n const errorEvent: ProducerSendErrorEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendErrorChannel.publish(errorEvent)\n }\n\n // Publish end event\n if (producerSendEndChannel.hasSubscribers) {\n const endEvent: ProducerSendEndEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n metadata,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendEndChannel.publish(endEvent)\n }\n }\n }\n}\n\n/**\n * Instruments a consumer receive method to publish diagnostic events\n */\nexport function instrumentConsumerReceive(\n originalReceive: () => Promise<Message | null>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer) => Promise<Message | null> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedReceive(this: KafkaConsumer) {\n // Fast path: if no subscribers at all, just call original\n const hasReceiveSubscribers = consumerReceiveStartChannel.hasSubscribers || consumerReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = consumerProcessStartChannel.hasSubscribers || consumerProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalReceive.call(this)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish receive start\n if (consumerReceiveStartChannel.hasSubscribers) {\n const startEvent: ConsumerReceiveStartEvent = {\n timestamp,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveStartChannel.publish(startEvent)\n }\n\n let receiveError: Error | undefined\n let message: Message | null = null\n\n try {\n message = await originalReceive.call(this)\n return message\n } catch (error) {\n receiveError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish receive end\n if (consumerReceiveEndChannel.hasSubscribers) {\n const endEvent: ConsumerReceiveEndEvent = {\n timestamp: Date.now(),\n message,\n groupId,\n durationMs: Date.now() - timestamp,\n error: receiveError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveEndChannel.publish(endEvent)\n }\n\n // If message exists and process channels have subscribers, set up process tracking\n if (message && hasProcessSubscribers) {\n const processingMessage = message\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n\n // Publish process start\n if (consumerProcessStartChannel.hasSubscribers) {\n const processStartEvent: ConsumerProcessStartEvent = {\n timestamp: processStartTime,\n message,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to message for user to call when processing completes\n let ended = false\n const endProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (consumerProcessEndChannel.hasSubscribers) {\n const processEndEvent: ConsumerProcessEndEvent = {\n timestamp: Date.now(),\n message: processingMessage,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessEndChannel.publish(processEndEvent)\n }\n }\n\n // Add endSpan to message\n Object.defineProperty(message, 'endSpan', {\n value: endProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n}\n\n/**\n * Instruments a consumer batch receive method to publish diagnostic events\n */\nexport function instrumentBatchReceive(\n originalBatchReceive: (size: number, timeoutMs: number) => Promise<Message[]>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer, size: number, timeoutMs: number) => Promise<Message[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedBatchReceive(this: KafkaConsumer, size: number, timeoutMs: number) {\n // Fast path: if no subscribers, just call original\n const hasReceiveSubscribers = batchReceiveStartChannel.hasSubscribers || batchReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = batchProcessStartChannel.hasSubscribers || batchProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalBatchReceive.call(this, size, timeoutMs)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish batch receive start\n if (batchReceiveStartChannel.hasSubscribers) {\n const startEvent: BatchReceiveStartEvent = {\n timestamp,\n groupId,\n requestedSize: size,\n timeoutMs,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveStartChannel.publish(startEvent)\n }\n\n let batchError: Error | undefined\n let messages: Message[] = []\n\n try {\n messages = await originalBatchReceive.call(this, size, timeoutMs)\n return messages\n } catch (error) {\n batchError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish batch receive end\n if (batchReceiveEndChannel.hasSubscribers) {\n const endEvent: BatchReceiveEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - timestamp,\n error: batchError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveEndChannel.publish(endEvent)\n }\n\n // If messages exist and process channels have subscribers, set up batch process tracking\n if (messages.length > 0 && hasProcessSubscribers) {\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n let firstProcessError: Error | undefined\n let remainingMessages = messages.length\n\n // Publish batch process start\n if (batchProcessStartChannel.hasSubscribers) {\n // Surface headers from the first message for downstream context extraction\n if (messages[0]?.headers) {\n processContext.parentHeaders = messages[0].headers\n }\n\n const processStartEvent: BatchProcessStartEvent = {\n timestamp: processStartTime,\n messages,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to batch array\n let ended = false\n const endBatchProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n\n if (batchProcessEndChannel.hasSubscribers) {\n const processEndEvent: BatchProcessEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError ?? firstProcessError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessEndChannel.publish(processEndEvent)\n }\n }\n\n const makeMessageEnder = () => {\n let messageEnded = false\n return (processError?: Error) => {\n if (messageEnded || ended) {\n return\n }\n messageEnded = true\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n remainingMessages -= 1\n if (remainingMessages <= 0) {\n endBatchProcessing(firstProcessError)\n }\n }\n }\n\n Object.defineProperty(messages, 'endSpan', {\n value: endBatchProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n\n for (const message of messages) {\n Object.defineProperty(message, 'endSpan', {\n value: makeMessageEnder(),\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n }\n}\n\n/**\n * Instruments a ReadableStream of single messages with consumer diagnostic events.\n */\nexport function instrumentConsumerReadableStream<StreamMessage extends Message>(\n originalStream: ReadableStream<StreamMessage>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamMessage> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedReceive = instrumentConsumerReceive(\n async () => {\n if (done) {\n return null\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return null\n }\n\n return chunk.value ?? null\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as () => Promise<StreamMessage | null>\n\n return new ReadableStream<StreamMessage>({\n async pull(controller) {\n const message = await instrumentedReceive()\n if (!message) {\n controller.close()\n return\n }\n\n controller.enqueue(message)\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n\n/**\n * Instruments a ReadableStream of message batches with batch diagnostic events.\n */\nexport function instrumentBatchReadableStream<StreamBatch extends Message[]>(\n originalStream: ReadableStream<StreamBatch>,\n groupId: string | undefined,\n size: number,\n timeoutMs: number,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamBatch> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedBatchReceive = instrumentBatchReceive(\n async () => {\n if (done) {\n return []\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return []\n }\n\n return chunk.value ?? []\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as (size: number, timeoutMs: number) => Promise<StreamBatch>\n\n return new ReadableStream<StreamBatch>({\n async pull(controller) {\n const messages = await instrumentedBatchReceive(size, timeoutMs)\n if (done) {\n controller.close()\n return\n }\n\n if (messages.length > 0) {\n controller.enqueue(messages)\n }\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"instrumentation.cjs","names":["producerSendStartChannel","producerSendEndChannel","producerSendErrorChannel","consumerReceiveStartChannel","consumerReceiveEndChannel","consumerProcessStartChannel","consumerProcessEndChannel","batchReceiveStartChannel","batchReceiveEndChannel","batchProcessStartChannel","batchProcessEndChannel"],"sources":["../../js-src/diagnostics/instrumentation.ts"],"sourcesContent":["/**\n * Diagnostic Channel-based Kafka Instrumentation\n *\n * This module provides instrumentation that publishes events to Node.js\n * diagnostic channels instead of directly calling OpenTelemetry APIs.\n * Observability tools can subscribe to these channels to receive events.\n */\nimport type { KafkaConsumer, KafkaProducer, Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\nimport {\n batchProcessEndChannel,\n type BatchProcessEndEvent,\n batchProcessStartChannel,\n type BatchProcessStartEvent,\n batchReceiveEndChannel,\n type BatchReceiveEndEvent,\n batchReceiveStartChannel,\n type BatchReceiveStartEvent,\n consumerProcessEndChannel,\n type ConsumerProcessEndEvent,\n consumerProcessStartChannel,\n type ConsumerProcessStartEvent,\n consumerReceiveEndChannel,\n type ConsumerReceiveEndEvent,\n consumerReceiveStartChannel,\n type ConsumerReceiveStartEvent,\n producerSendEndChannel,\n type ProducerSendEndEvent,\n producerSendErrorChannel,\n type ProducerSendErrorEvent,\n producerSendStartChannel,\n type ProducerSendStartEvent,\n} from './channels.js'\n\n/**\n * Configuration for diagnostic channel instrumentation\n */\nexport interface DiagnosticInstrumentationConfig {\n /** Client ID for attribution */\n clientId?: string\n /** Server address for attribution */\n serverAddress?: string\n /** Server port for attribution */\n serverPort?: number\n}\n\n/**\n * Instruments a producer send method to publish diagnostic events\n */\nexport function instrumentProducerSend(\n originalSend: (record: ProducerRecord) => Promise<RecordMetadata[]>,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaProducer, record: ProducerRecord) => Promise<RecordMetadata[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedSend(this: KafkaProducer, record: ProducerRecord) {\n // Fast path: if no subscribers, just call original\n if (\n !producerSendStartChannel.hasSubscribers &&\n !producerSendEndChannel.hasSubscribers &&\n !producerSendErrorChannel.hasSubscribers\n ) {\n return originalSend.call(this, record)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n const startEvent: ProducerSendStartEvent = {\n timestamp,\n topic: record.topic,\n record,\n messageCount: record.messages?.length ?? 0,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n\n // Publish start event - subscribers can inject trace headers here\n if (producerSendStartChannel.hasSubscribers) {\n producerSendStartChannel.publish(startEvent)\n }\n\n let sendError: Error | undefined\n let metadata: RecordMetadata[] | undefined\n\n try {\n metadata = await originalSend.call(this, record)\n return metadata\n } catch (error) {\n sendError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n const durationMs = Date.now() - timestamp\n\n if (sendError && producerSendErrorChannel.hasSubscribers) {\n const errorEvent: ProducerSendErrorEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendErrorChannel.publish(errorEvent)\n }\n\n // Publish end event\n if (producerSendEndChannel.hasSubscribers) {\n const endEvent: ProducerSendEndEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n metadata,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendEndChannel.publish(endEvent)\n }\n }\n }\n}\n\n/**\n * Instruments a consumer receive method to publish diagnostic events\n */\nexport function instrumentConsumerReceive(\n originalReceive: () => Promise<Message | null>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer) => Promise<Message | null> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedReceive(this: KafkaConsumer) {\n // Fast path: if no subscribers at all, just call original\n const hasReceiveSubscribers = consumerReceiveStartChannel.hasSubscribers || consumerReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = consumerProcessStartChannel.hasSubscribers || consumerProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalReceive.call(this)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish receive start\n if (consumerReceiveStartChannel.hasSubscribers) {\n const startEvent: ConsumerReceiveStartEvent = {\n timestamp,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveStartChannel.publish(startEvent)\n }\n\n let receiveError: Error | undefined\n let message: Message | null = null\n\n try {\n message = await originalReceive.call(this)\n return message\n } catch (error) {\n receiveError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish receive end\n if (consumerReceiveEndChannel.hasSubscribers) {\n const endEvent: ConsumerReceiveEndEvent = {\n timestamp: Date.now(),\n message,\n groupId,\n durationMs: Date.now() - timestamp,\n error: receiveError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveEndChannel.publish(endEvent)\n }\n\n // If message exists and process channels have subscribers, set up process tracking\n if (message && hasProcessSubscribers) {\n const processingMessage = message\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n\n // Publish process start\n if (consumerProcessStartChannel.hasSubscribers) {\n const processStartEvent: ConsumerProcessStartEvent = {\n timestamp: processStartTime,\n message,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to message for user to call when processing completes\n let ended = false\n const endProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (consumerProcessEndChannel.hasSubscribers) {\n const processEndEvent: ConsumerProcessEndEvent = {\n timestamp: Date.now(),\n message: processingMessage,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessEndChannel.publish(processEndEvent)\n }\n }\n\n // Add endSpan to message\n Object.defineProperty(message, 'endSpan', {\n value: endProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n}\n\n/**\n * Instruments a consumer batch receive method to publish diagnostic events\n */\nexport function instrumentBatchReceive(\n originalBatchReceive: (size: number, timeoutMs: number) => Promise<Message[]>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer, size: number, timeoutMs: number) => Promise<Message[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedBatchReceive(this: KafkaConsumer, size: number, timeoutMs: number) {\n // Fast path: if no subscribers, just call original\n const hasReceiveSubscribers = batchReceiveStartChannel.hasSubscribers || batchReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = batchProcessStartChannel.hasSubscribers || batchProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalBatchReceive.call(this, size, timeoutMs)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish batch receive start\n if (batchReceiveStartChannel.hasSubscribers) {\n const startEvent: BatchReceiveStartEvent = {\n timestamp,\n groupId,\n requestedSize: size,\n timeoutMs,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveStartChannel.publish(startEvent)\n }\n\n let batchError: Error | undefined\n let messages: Message[] = []\n\n try {\n messages = await originalBatchReceive.call(this, size, timeoutMs)\n return messages\n } catch (error) {\n batchError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish batch receive end\n if (batchReceiveEndChannel.hasSubscribers) {\n const endEvent: BatchReceiveEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - timestamp,\n error: batchError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveEndChannel.publish(endEvent)\n }\n\n // If messages exist and process channels have subscribers, set up batch process tracking\n if (messages.length > 0 && hasProcessSubscribers) {\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n let firstProcessError: Error | undefined\n let remainingMessages = messages.length\n\n // Publish batch process start\n if (batchProcessStartChannel.hasSubscribers) {\n // Surface headers from the first message for downstream context extraction\n if (messages[0]?.headers) {\n processContext.parentHeaders = messages[0].headers\n }\n\n const processStartEvent: BatchProcessStartEvent = {\n timestamp: processStartTime,\n messages,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to batch array\n let ended = false\n const endBatchProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n\n if (batchProcessEndChannel.hasSubscribers) {\n const processEndEvent: BatchProcessEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError ?? firstProcessError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessEndChannel.publish(processEndEvent)\n }\n }\n\n const makeMessageEnder = () => {\n let messageEnded = false\n return (processError?: Error) => {\n if (messageEnded || ended) {\n return\n }\n messageEnded = true\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n remainingMessages -= 1\n if (remainingMessages <= 0) {\n endBatchProcessing(firstProcessError)\n }\n }\n }\n\n Object.defineProperty(messages, 'endSpan', {\n value: endBatchProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n\n for (const message of messages) {\n Object.defineProperty(message, 'endSpan', {\n value: makeMessageEnder(),\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n }\n}\n\n/**\n * Instruments a ReadableStream of single messages with consumer diagnostic events.\n */\nexport function instrumentConsumerReadableStream<StreamMessage extends Message>(\n originalStream: ReadableStream<StreamMessage>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamMessage> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedReceive = instrumentConsumerReceive(\n async () => {\n if (done) {\n return null\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return null\n }\n\n return chunk.value ?? null\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as () => Promise<StreamMessage | null>\n\n return new ReadableStream<StreamMessage>({\n async pull(controller) {\n const message = await instrumentedReceive()\n if (!message) {\n controller.close()\n return\n }\n\n controller.enqueue(message)\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n\n/**\n * Instruments a ReadableStream of message batches with batch diagnostic events.\n */\nexport function instrumentBatchReadableStream<StreamBatch extends Message[]>(\n originalStream: ReadableStream<StreamBatch>,\n groupId: string | undefined,\n size: number,\n timeoutMs: number,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamBatch> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedBatchReceive = instrumentBatchReceive(\n async () => {\n if (done) {\n return []\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return []\n }\n\n return chunk.value ?? []\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as (size: number, timeoutMs: number) => Promise<StreamBatch>\n\n return new ReadableStream<StreamBatch>({\n async pull(controller) {\n const messages = await instrumentedBatchReceive(size, timeoutMs)\n if (done) {\n controller.close()\n return\n }\n\n if (messages.length > 0) {\n controller.enqueue(messages)\n }\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-
|
|
1
|
+
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-CGxc_url.cjs";
|
|
2
2
|
export { DiagnosticInstrumentationConfig, instrumentBatchReadableStream, instrumentBatchReceive, instrumentConsumerReadableStream, instrumentConsumerReceive, instrumentProducerSend };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-
|
|
1
|
+
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "../instrumentation-CGxc_url.js";
|
|
2
2
|
export { DiagnosticInstrumentationConfig, instrumentBatchReadableStream, instrumentBatchReceive, instrumentConsumerReadableStream, instrumentConsumerReceive, instrumentProducerSend };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","names":[],"sources":["../../js-src/diagnostics/instrumentation.ts"],"sourcesContent":["/**\n * Diagnostic Channel-based Kafka Instrumentation\n *\n * This module provides instrumentation that publishes events to Node.js\n * diagnostic channels instead of directly calling OpenTelemetry APIs.\n * Observability tools can subscribe to these channels to receive events.\n */\nimport type { KafkaConsumer, KafkaProducer, Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\nimport {\n batchProcessEndChannel,\n type BatchProcessEndEvent,\n batchProcessStartChannel,\n type BatchProcessStartEvent,\n batchReceiveEndChannel,\n type BatchReceiveEndEvent,\n batchReceiveStartChannel,\n type BatchReceiveStartEvent,\n consumerProcessEndChannel,\n type ConsumerProcessEndEvent,\n consumerProcessStartChannel,\n type ConsumerProcessStartEvent,\n consumerReceiveEndChannel,\n type ConsumerReceiveEndEvent,\n consumerReceiveStartChannel,\n type ConsumerReceiveStartEvent,\n producerSendEndChannel,\n type ProducerSendEndEvent,\n producerSendErrorChannel,\n type ProducerSendErrorEvent,\n producerSendStartChannel,\n type ProducerSendStartEvent,\n} from './channels.js'\n\n/**\n * Configuration for diagnostic channel instrumentation\n */\nexport interface DiagnosticInstrumentationConfig {\n /** Client ID for attribution */\n clientId?: string\n /** Server address for attribution */\n serverAddress?: string\n /** Server port for attribution */\n serverPort?: number\n}\n\n/**\n * Instruments a producer send method to publish diagnostic events\n */\nexport function instrumentProducerSend(\n originalSend: (record: ProducerRecord) => Promise<RecordMetadata[]>,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaProducer, record: ProducerRecord) => Promise<RecordMetadata[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedSend(this: KafkaProducer, record: ProducerRecord) {\n // Fast path: if no subscribers, just call original\n if (\n !producerSendStartChannel.hasSubscribers &&\n !producerSendEndChannel.hasSubscribers &&\n !producerSendErrorChannel.hasSubscribers\n ) {\n return originalSend.call(this, record)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n const startEvent: ProducerSendStartEvent = {\n timestamp,\n topic: record.topic,\n record,\n messageCount: record.messages?.length ?? 0,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n\n // Publish start event - subscribers can inject trace headers here\n if (producerSendStartChannel.hasSubscribers) {\n producerSendStartChannel.publish(startEvent)\n }\n\n let sendError: Error | undefined\n let metadata: RecordMetadata[] | undefined\n\n try {\n metadata = await originalSend.call(this, record)\n return metadata\n } catch (error) {\n sendError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n const durationMs = Date.now() - timestamp\n\n if (sendError && producerSendErrorChannel.hasSubscribers) {\n const errorEvent: ProducerSendErrorEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendErrorChannel.publish(errorEvent)\n }\n\n // Publish end event\n if (producerSendEndChannel.hasSubscribers) {\n const endEvent: ProducerSendEndEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n metadata,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendEndChannel.publish(endEvent)\n }\n }\n }\n}\n\n/**\n * Instruments a consumer receive method to publish diagnostic events\n */\nexport function instrumentConsumerReceive(\n originalReceive: () => Promise<Message | null>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer) => Promise<Message | null> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedReceive(this: KafkaConsumer) {\n // Fast path: if no subscribers at all, just call original\n const hasReceiveSubscribers = consumerReceiveStartChannel.hasSubscribers || consumerReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = consumerProcessStartChannel.hasSubscribers || consumerProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalReceive.call(this)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish receive start\n if (consumerReceiveStartChannel.hasSubscribers) {\n const startEvent: ConsumerReceiveStartEvent = {\n timestamp,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveStartChannel.publish(startEvent)\n }\n\n let receiveError: Error | undefined\n let message: Message | null = null\n\n try {\n message = await originalReceive.call(this)\n return message\n } catch (error) {\n receiveError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish receive end\n if (consumerReceiveEndChannel.hasSubscribers) {\n const endEvent: ConsumerReceiveEndEvent = {\n timestamp: Date.now(),\n message,\n groupId,\n durationMs: Date.now() - timestamp,\n error: receiveError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveEndChannel.publish(endEvent)\n }\n\n // If message exists and process channels have subscribers, set up process tracking\n if (message && hasProcessSubscribers) {\n const processingMessage = message\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n\n // Publish process start\n if (consumerProcessStartChannel.hasSubscribers) {\n const processStartEvent: ConsumerProcessStartEvent = {\n timestamp: processStartTime,\n message,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to message for user to call when processing completes\n let ended = false\n const endProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (consumerProcessEndChannel.hasSubscribers) {\n const processEndEvent: ConsumerProcessEndEvent = {\n timestamp: Date.now(),\n message: processingMessage,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessEndChannel.publish(processEndEvent)\n }\n }\n\n // Add endSpan to message\n Object.defineProperty(message, 'endSpan', {\n value: endProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n}\n\n/**\n * Instruments a consumer batch receive method to publish diagnostic events\n */\nexport function instrumentBatchReceive(\n originalBatchReceive: (size: number, timeoutMs: number) => Promise<Message[]>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer, size: number, timeoutMs: number) => Promise<Message[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedBatchReceive(this: KafkaConsumer, size: number, timeoutMs: number) {\n // Fast path: if no subscribers, just call original\n const hasReceiveSubscribers = batchReceiveStartChannel.hasSubscribers || batchReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = batchProcessStartChannel.hasSubscribers || batchProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalBatchReceive.call(this, size, timeoutMs)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish batch receive start\n if (batchReceiveStartChannel.hasSubscribers) {\n const startEvent: BatchReceiveStartEvent = {\n timestamp,\n groupId,\n requestedSize: size,\n timeoutMs,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveStartChannel.publish(startEvent)\n }\n\n let batchError: Error | undefined\n let messages: Message[] = []\n\n try {\n messages = await originalBatchReceive.call(this, size, timeoutMs)\n return messages\n } catch (error) {\n batchError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish batch receive end\n if (batchReceiveEndChannel.hasSubscribers) {\n const endEvent: BatchReceiveEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - timestamp,\n error: batchError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveEndChannel.publish(endEvent)\n }\n\n // If messages exist and process channels have subscribers, set up batch process tracking\n if (messages.length > 0 && hasProcessSubscribers) {\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n let firstProcessError: Error | undefined\n let remainingMessages = messages.length\n\n // Publish batch process start\n if (batchProcessStartChannel.hasSubscribers) {\n // Surface headers from the first message for downstream context extraction\n if (messages[0]?.headers) {\n processContext.parentHeaders = messages[0].headers\n }\n\n const processStartEvent: BatchProcessStartEvent = {\n timestamp: processStartTime,\n messages,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to batch array\n let ended = false\n const endBatchProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n\n if (batchProcessEndChannel.hasSubscribers) {\n const processEndEvent: BatchProcessEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError ?? firstProcessError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessEndChannel.publish(processEndEvent)\n }\n }\n\n const makeMessageEnder = () => {\n let messageEnded = false\n return (processError?: Error) => {\n if (messageEnded || ended) {\n return\n }\n messageEnded = true\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n remainingMessages -= 1\n if (remainingMessages <= 0) {\n endBatchProcessing(firstProcessError)\n }\n }\n }\n\n Object.defineProperty(messages, 'endSpan', {\n value: endBatchProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n\n for (const message of messages) {\n Object.defineProperty(message, 'endSpan', {\n value: makeMessageEnder(),\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n }\n}\n\n/**\n * Instruments a ReadableStream of single messages with consumer diagnostic events.\n */\nexport function instrumentConsumerReadableStream<StreamMessage extends Message>(\n originalStream: ReadableStream<StreamMessage>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamMessage> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedReceive = instrumentConsumerReceive(\n async () => {\n if (done) {\n return null\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return null\n }\n\n return chunk.value ?? null\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as () => Promise<StreamMessage | null>\n\n return new ReadableStream<StreamMessage>({\n async pull(controller) {\n const message = await instrumentedReceive()\n if (!message) {\n controller.close()\n return\n }\n\n controller.enqueue(message)\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n\n/**\n * Instruments a ReadableStream of message batches with batch diagnostic events.\n */\nexport function instrumentBatchReadableStream<StreamBatch extends Message[]>(\n originalStream: ReadableStream<StreamBatch>,\n groupId: string | undefined,\n size: number,\n timeoutMs: number,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamBatch> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedBatchReceive = instrumentBatchReceive(\n async () => {\n if (done) {\n return []\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return []\n }\n\n return chunk.value ?? []\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as (size: number, timeoutMs: number) => Promise<StreamBatch>\n\n return new ReadableStream<StreamBatch>({\n async pull(controller) {\n const messages = await instrumentedBatchReceive(size, timeoutMs)\n if (done) {\n controller.close()\n return\n }\n\n if (messages.length > 0) {\n controller.enqueue(messages)\n }\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"instrumentation.js","names":[],"sources":["../../js-src/diagnostics/instrumentation.ts"],"sourcesContent":["/**\n * Diagnostic Channel-based Kafka Instrumentation\n *\n * This module provides instrumentation that publishes events to Node.js\n * diagnostic channels instead of directly calling OpenTelemetry APIs.\n * Observability tools can subscribe to these channels to receive events.\n */\nimport type { KafkaConsumer, KafkaProducer, Message, ProducerRecord, RecordMetadata } from '../../js-binding.js'\nimport {\n batchProcessEndChannel,\n type BatchProcessEndEvent,\n batchProcessStartChannel,\n type BatchProcessStartEvent,\n batchReceiveEndChannel,\n type BatchReceiveEndEvent,\n batchReceiveStartChannel,\n type BatchReceiveStartEvent,\n consumerProcessEndChannel,\n type ConsumerProcessEndEvent,\n consumerProcessStartChannel,\n type ConsumerProcessStartEvent,\n consumerReceiveEndChannel,\n type ConsumerReceiveEndEvent,\n consumerReceiveStartChannel,\n type ConsumerReceiveStartEvent,\n producerSendEndChannel,\n type ProducerSendEndEvent,\n producerSendErrorChannel,\n type ProducerSendErrorEvent,\n producerSendStartChannel,\n type ProducerSendStartEvent,\n} from './channels.js'\n\n/**\n * Configuration for diagnostic channel instrumentation\n */\nexport interface DiagnosticInstrumentationConfig {\n /** Client ID for attribution */\n clientId?: string\n /** Server address for attribution */\n serverAddress?: string\n /** Server port for attribution */\n serverPort?: number\n}\n\n/**\n * Instruments a producer send method to publish diagnostic events\n */\nexport function instrumentProducerSend(\n originalSend: (record: ProducerRecord) => Promise<RecordMetadata[]>,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaProducer, record: ProducerRecord) => Promise<RecordMetadata[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedSend(this: KafkaProducer, record: ProducerRecord) {\n // Fast path: if no subscribers, just call original\n if (\n !producerSendStartChannel.hasSubscribers &&\n !producerSendEndChannel.hasSubscribers &&\n !producerSendErrorChannel.hasSubscribers\n ) {\n return originalSend.call(this, record)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n const startEvent: ProducerSendStartEvent = {\n timestamp,\n topic: record.topic,\n record,\n messageCount: record.messages?.length ?? 0,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n\n // Publish start event - subscribers can inject trace headers here\n if (producerSendStartChannel.hasSubscribers) {\n producerSendStartChannel.publish(startEvent)\n }\n\n let sendError: Error | undefined\n let metadata: RecordMetadata[] | undefined\n\n try {\n metadata = await originalSend.call(this, record)\n return metadata\n } catch (error) {\n sendError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n const durationMs = Date.now() - timestamp\n\n if (sendError && producerSendErrorChannel.hasSubscribers) {\n const errorEvent: ProducerSendErrorEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendErrorChannel.publish(errorEvent)\n }\n\n // Publish end event\n if (producerSendEndChannel.hasSubscribers) {\n const endEvent: ProducerSendEndEvent = {\n timestamp: Date.now(),\n topic: record.topic,\n record,\n metadata,\n durationMs,\n error: sendError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n producerSendEndChannel.publish(endEvent)\n }\n }\n }\n}\n\n/**\n * Instruments a consumer receive method to publish diagnostic events\n */\nexport function instrumentConsumerReceive(\n originalReceive: () => Promise<Message | null>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer) => Promise<Message | null> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedReceive(this: KafkaConsumer) {\n // Fast path: if no subscribers at all, just call original\n const hasReceiveSubscribers = consumerReceiveStartChannel.hasSubscribers || consumerReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = consumerProcessStartChannel.hasSubscribers || consumerProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalReceive.call(this)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish receive start\n if (consumerReceiveStartChannel.hasSubscribers) {\n const startEvent: ConsumerReceiveStartEvent = {\n timestamp,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveStartChannel.publish(startEvent)\n }\n\n let receiveError: Error | undefined\n let message: Message | null = null\n\n try {\n message = await originalReceive.call(this)\n return message\n } catch (error) {\n receiveError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish receive end\n if (consumerReceiveEndChannel.hasSubscribers) {\n const endEvent: ConsumerReceiveEndEvent = {\n timestamp: Date.now(),\n message,\n groupId,\n durationMs: Date.now() - timestamp,\n error: receiveError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n consumerReceiveEndChannel.publish(endEvent)\n }\n\n // If message exists and process channels have subscribers, set up process tracking\n if (message && hasProcessSubscribers) {\n const processingMessage = message\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n\n // Publish process start\n if (consumerProcessStartChannel.hasSubscribers) {\n const processStartEvent: ConsumerProcessStartEvent = {\n timestamp: processStartTime,\n message,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to message for user to call when processing completes\n let ended = false\n const endProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (consumerProcessEndChannel.hasSubscribers) {\n const processEndEvent: ConsumerProcessEndEvent = {\n timestamp: Date.now(),\n message: processingMessage,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n consumerProcessEndChannel.publish(processEndEvent)\n }\n }\n\n // Add endSpan to message\n Object.defineProperty(message, 'endSpan', {\n value: endProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n}\n\n/**\n * Instruments a consumer batch receive method to publish diagnostic events\n */\nexport function instrumentBatchReceive(\n originalBatchReceive: (size: number, timeoutMs: number) => Promise<Message[]>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): (this: KafkaConsumer, size: number, timeoutMs: number) => Promise<Message[]> {\n const { clientId, serverAddress, serverPort } = config\n\n return async function instrumentedBatchReceive(this: KafkaConsumer, size: number, timeoutMs: number) {\n // Fast path: if no subscribers, just call original\n const hasReceiveSubscribers = batchReceiveStartChannel.hasSubscribers || batchReceiveEndChannel.hasSubscribers\n const hasProcessSubscribers = batchProcessStartChannel.hasSubscribers || batchProcessEndChannel.hasSubscribers\n\n if (!hasReceiveSubscribers && !hasProcessSubscribers) {\n return originalBatchReceive.call(this, size, timeoutMs)\n }\n\n const timestamp = Date.now()\n const context: Record<PropertyKey, unknown> = {}\n\n // Publish batch receive start\n if (batchReceiveStartChannel.hasSubscribers) {\n const startEvent: BatchReceiveStartEvent = {\n timestamp,\n groupId,\n requestedSize: size,\n timeoutMs,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveStartChannel.publish(startEvent)\n }\n\n let batchError: Error | undefined\n let messages: Message[] = []\n\n try {\n messages = await originalBatchReceive.call(this, size, timeoutMs)\n return messages\n } catch (error) {\n batchError = error instanceof Error ? error : new Error(String(error))\n throw error\n } finally {\n // Publish batch receive end\n if (batchReceiveEndChannel.hasSubscribers) {\n const endEvent: BatchReceiveEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - timestamp,\n error: batchError,\n clientId,\n serverAddress,\n serverPort,\n context,\n }\n batchReceiveEndChannel.publish(endEvent)\n }\n\n // If messages exist and process channels have subscribers, set up batch process tracking\n if (messages.length > 0 && hasProcessSubscribers) {\n const processContext: Record<PropertyKey, unknown> = {}\n const processStartTime = Date.now()\n let firstProcessError: Error | undefined\n let remainingMessages = messages.length\n\n // Publish batch process start\n if (batchProcessStartChannel.hasSubscribers) {\n // Surface headers from the first message for downstream context extraction\n if (messages[0]?.headers) {\n processContext.parentHeaders = messages[0].headers\n }\n\n const processStartEvent: BatchProcessStartEvent = {\n timestamp: processStartTime,\n messages,\n groupId,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessStartChannel.publish(processStartEvent)\n }\n\n // Attach endSpan helper to batch array\n let ended = false\n const endBatchProcessing = (processError?: Error) => {\n if (ended) {\n return\n }\n ended = true\n\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n\n if (batchProcessEndChannel.hasSubscribers) {\n const processEndEvent: BatchProcessEndEvent = {\n timestamp: Date.now(),\n messages,\n groupId,\n durationMs: Date.now() - processStartTime,\n error: processError ?? firstProcessError,\n clientId,\n serverAddress,\n serverPort,\n context: processContext,\n }\n batchProcessEndChannel.publish(processEndEvent)\n }\n }\n\n const makeMessageEnder = () => {\n let messageEnded = false\n return (processError?: Error) => {\n if (messageEnded || ended) {\n return\n }\n messageEnded = true\n if (!firstProcessError && processError) {\n firstProcessError = processError\n }\n remainingMessages -= 1\n if (remainingMessages <= 0) {\n endBatchProcessing(firstProcessError)\n }\n }\n }\n\n Object.defineProperty(messages, 'endSpan', {\n value: endBatchProcessing,\n writable: false,\n configurable: true,\n enumerable: false,\n })\n\n for (const message of messages) {\n Object.defineProperty(message, 'endSpan', {\n value: makeMessageEnder(),\n writable: false,\n configurable: true,\n enumerable: false,\n })\n }\n }\n }\n }\n}\n\n/**\n * Instruments a ReadableStream of single messages with consumer diagnostic events.\n */\nexport function instrumentConsumerReadableStream<StreamMessage extends Message>(\n originalStream: ReadableStream<StreamMessage>,\n groupId?: string,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamMessage> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedReceive = instrumentConsumerReceive(\n async () => {\n if (done) {\n return null\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return null\n }\n\n return chunk.value ?? null\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as () => Promise<StreamMessage | null>\n\n return new ReadableStream<StreamMessage>({\n async pull(controller) {\n const message = await instrumentedReceive()\n if (!message) {\n controller.close()\n return\n }\n\n controller.enqueue(message)\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n\n/**\n * Instruments a ReadableStream of message batches with batch diagnostic events.\n */\nexport function instrumentBatchReadableStream<StreamBatch extends Message[]>(\n originalStream: ReadableStream<StreamBatch>,\n groupId: string | undefined,\n size: number,\n timeoutMs: number,\n config: DiagnosticInstrumentationConfig = {},\n): ReadableStream<StreamBatch> {\n const reader = originalStream.getReader()\n let done = false\n\n const instrumentedBatchReceive = instrumentBatchReceive(\n async () => {\n if (done) {\n return []\n }\n\n const chunk = await reader.read()\n if (chunk.done) {\n done = true\n return []\n }\n\n return chunk.value ?? []\n },\n groupId,\n config,\n ).bind({} as KafkaConsumer) as (size: number, timeoutMs: number) => Promise<StreamBatch>\n\n return new ReadableStream<StreamBatch>({\n async pull(controller) {\n const messages = await instrumentedBatchReceive(size, timeoutMs)\n if (done) {\n controller.close()\n return\n }\n\n if (messages.length > 0) {\n controller.enqueue(messages)\n }\n },\n async cancel(reason) {\n done = true\n await reader.cancel(reason)\n },\n })\n}\n"],"mappings":";;;;;AAgDA,SAAgB,uBACd,cACA,SAA0C,CAAC,GACiC;CAC5E,MAAM,EAAE,UAAU,eAAe,eAAe;CAEhD,OAAO,eAAe,iBAAsC,QAAwB;EAElF,IACE,CAAC,yBAAyB,kBAC1B,CAAC,uBAAuB,kBACxB,CAAC,yBAAyB,gBAE1B,OAAO,aAAa,KAAK,MAAM,MAAM;EAGvC,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,UAAwC,CAAC;EAE/C,MAAM,aAAqC;GACzC;GACA,OAAO,OAAO;GACd;GACA,cAAc,OAAO,UAAU,UAAU;GACzC;GACA;GACA;GACA;EACF;EAGA,IAAI,yBAAyB,gBAC3B,yBAAyB,QAAQ,UAAU;EAG7C,IAAI;EACJ,IAAI;EAEJ,IAAI;GACF,WAAW,MAAM,aAAa,KAAK,MAAM,MAAM;GAC/C,OAAO;EACT,SAAS,OAAO;GACd,YAAY,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;GACpE,MAAM;EACR,UAAU;GACR,MAAM,aAAa,KAAK,IAAI,IAAI;GAEhC,IAAI,aAAa,yBAAyB,gBAAgB;IACxD,MAAM,aAAqC;KACzC,WAAW,KAAK,IAAI;KACpB,OAAO,OAAO;KACd;KACA;KACA,OAAO;KACP;KACA;KACA;KACA;IACF;IACA,yBAAyB,QAAQ,UAAU;GAC7C;GAGA,IAAI,uBAAuB,gBAAgB;IACzC,MAAM,WAAiC;KACrC,WAAW,KAAK,IAAI;KACpB,OAAO,OAAO;KACd;KACA;KACA;KACA,OAAO;KACP;KACA;KACA;KACA;IACF;IACA,uBAAuB,QAAQ,QAAQ;GACzC;EACF;CACF;AACF;;;;AAKA,SAAgB,0BACd,iBACA,SACA,SAA0C,CAAC,GACO;CAClD,MAAM,EAAE,UAAU,eAAe,eAAe;CAEhD,OAAO,eAAe,sBAAyC;EAE7D,MAAM,wBAAwB,4BAA4B,kBAAkB,0BAA0B;EACtG,MAAM,wBAAwB,4BAA4B,kBAAkB,0BAA0B;EAEtG,IAAI,CAAC,yBAAyB,CAAC,uBAC7B,OAAO,gBAAgB,KAAK,IAAI;EAGlC,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,UAAwC,CAAC;EAG/C,IAAI,4BAA4B,gBAAgB;GAC9C,MAAM,aAAwC;IAC5C;IACA;IACA;IACA;IACA;IACA;GACF;GACA,4BAA4B,QAAQ,UAAU;EAChD;EAEA,IAAI;EACJ,IAAI,UAA0B;EAE9B,IAAI;GACF,UAAU,MAAM,gBAAgB,KAAK,IAAI;GACzC,OAAO;EACT,SAAS,OAAO;GACd,eAAe,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;GACvE,MAAM;EACR,UAAU;GAER,IAAI,0BAA0B,gBAAgB;IAC5C,MAAM,WAAoC;KACxC,WAAW,KAAK,IAAI;KACpB;KACA;KACA,YAAY,KAAK,IAAI,IAAI;KACzB,OAAO;KACP;KACA;KACA;KACA;IACF;IACA,0BAA0B,QAAQ,QAAQ;GAC5C;GAGA,IAAI,WAAW,uBAAuB;IACpC,MAAM,oBAAoB;IAC1B,MAAM,iBAA+C,CAAC;IACtD,MAAM,mBAAmB,KAAK,IAAI;IAGlC,IAAI,4BAA4B,gBAAgB;KAC9C,MAAM,oBAA+C;MACnD,WAAW;MACX;MACA;MACA;MACA;MACA;MACA,SAAS;KACX;KACA,4BAA4B,QAAQ,iBAAiB;IACvD;IAGA,IAAI,QAAQ;IACZ,MAAM,iBAAiB,iBAAyB;KAC9C,IAAI,OACF;KAEF,QAAQ;KAER,IAAI,0BAA0B,gBAAgB;MAC5C,MAAM,kBAA2C;OAC/C,WAAW,KAAK,IAAI;OACpB,SAAS;OACT;OACA,YAAY,KAAK,IAAI,IAAI;OACzB,OAAO;OACP;OACA;OACA;OACA,SAAS;MACX;MACA,0BAA0B,QAAQ,eAAe;KACnD;IACF;IAGA,OAAO,eAAe,SAAS,WAAW;KACxC,OAAO;KACP,UAAU;KACV,cAAc;KACd,YAAY;IACd,CAAC;GACH;EACF;CACF;AACF;;;;AAKA,SAAgB,uBACd,sBACA,SACA,SAA0C,CAAC,GACmC;CAC9E,MAAM,EAAE,UAAU,eAAe,eAAe;CAEhD,OAAO,eAAe,yBAA8C,MAAc,WAAmB;EAEnG,MAAM,wBAAwB,yBAAyB,kBAAkB,uBAAuB;EAChG,MAAM,wBAAwB,yBAAyB,kBAAkB,uBAAuB;EAEhG,IAAI,CAAC,yBAAyB,CAAC,uBAC7B,OAAO,qBAAqB,KAAK,MAAM,MAAM,SAAS;EAGxD,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,UAAwC,CAAC;EAG/C,IAAI,yBAAyB,gBAAgB;GAC3C,MAAM,aAAqC;IACzC;IACA;IACA,eAAe;IACf;IACA;IACA;IACA;IACA;GACF;GACA,yBAAyB,QAAQ,UAAU;EAC7C;EAEA,IAAI;EACJ,IAAI,WAAsB,CAAC;EAE3B,IAAI;GACF,WAAW,MAAM,qBAAqB,KAAK,MAAM,MAAM,SAAS;GAChE,OAAO;EACT,SAAS,OAAO;GACd,aAAa,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;GACrE,MAAM;EACR,UAAU;GAER,IAAI,uBAAuB,gBAAgB;IACzC,MAAM,WAAiC;KACrC,WAAW,KAAK,IAAI;KACpB;KACA;KACA,YAAY,KAAK,IAAI,IAAI;KACzB,OAAO;KACP;KACA;KACA;KACA;IACF;IACA,uBAAuB,QAAQ,QAAQ;GACzC;GAGA,IAAI,SAAS,SAAS,KAAK,uBAAuB;IAChD,MAAM,iBAA+C,CAAC;IACtD,MAAM,mBAAmB,KAAK,IAAI;IAClC,IAAI;IACJ,IAAI,oBAAoB,SAAS;IAGjC,IAAI,yBAAyB,gBAAgB;KAE3C,IAAI,SAAS,IAAI,SACf,eAAe,gBAAgB,SAAS,GAAG;KAG7C,MAAM,oBAA4C;MAChD,WAAW;MACX;MACA;MACA;MACA;MACA;MACA,SAAS;KACX;KACA,yBAAyB,QAAQ,iBAAiB;IACpD;IAGA,IAAI,QAAQ;IACZ,MAAM,sBAAsB,iBAAyB;KACnD,IAAI,OACF;KAEF,QAAQ;KAER,IAAI,CAAC,qBAAqB,cACxB,oBAAoB;KAGtB,IAAI,uBAAuB,gBAAgB;MACzC,MAAM,kBAAwC;OAC5C,WAAW,KAAK,IAAI;OACpB;OACA;OACA,YAAY,KAAK,IAAI,IAAI;OACzB,OAAO,gBAAgB;OACvB;OACA;OACA;OACA,SAAS;MACX;MACA,uBAAuB,QAAQ,eAAe;KAChD;IACF;IAEA,MAAM,yBAAyB;KAC7B,IAAI,eAAe;KACnB,QAAQ,iBAAyB;MAC/B,IAAI,gBAAgB,OAClB;MAEF,eAAe;MACf,IAAI,CAAC,qBAAqB,cACxB,oBAAoB;MAEtB,qBAAqB;MACrB,IAAI,qBAAqB,GACvB,mBAAmB,iBAAiB;KAExC;IACF;IAEA,OAAO,eAAe,UAAU,WAAW;KACzC,OAAO;KACP,UAAU;KACV,cAAc;KACd,YAAY;IACd,CAAC;IAED,KAAK,MAAM,WAAW,UACpB,OAAO,eAAe,SAAS,WAAW;KACxC,OAAO,iBAAiB;KACxB,UAAU;KACV,cAAc;KACd,YAAY;IACd,CAAC;GAEL;EACF;CACF;AACF;;;;AAKA,SAAgB,iCACd,gBACA,SACA,SAA0C,CAAC,GACZ;CAC/B,MAAM,SAAS,eAAe,UAAU;CACxC,IAAI,OAAO;CAEX,MAAM,sBAAsB,0BAC1B,YAAY;EACV,IAAI,MACF,OAAO;EAGT,MAAM,QAAQ,MAAM,OAAO,KAAK;EAChC,IAAI,MAAM,MAAM;GACd,OAAO;GACP,OAAO;EACT;EAEA,OAAO,MAAM,SAAS;CACxB,GACA,SACA,MACF,EAAE,KAAK,CAAC,CAAkB;CAE1B,OAAO,IAAI,eAA8B;EACvC,MAAM,KAAK,YAAY;GACrB,MAAM,UAAU,MAAM,oBAAoB;GAC1C,IAAI,CAAC,SAAS;IACZ,WAAW,MAAM;IACjB;GACF;GAEA,WAAW,QAAQ,OAAO;EAC5B;EACA,MAAM,OAAO,QAAQ;GACnB,OAAO;GACP,MAAM,OAAO,OAAO,MAAM;EAC5B;CACF,CAAC;AACH;;;;AAKA,SAAgB,8BACd,gBACA,SACA,MACA,WACA,SAA0C,CAAC,GACd;CAC7B,MAAM,SAAS,eAAe,UAAU;CACxC,IAAI,OAAO;CAEX,MAAM,2BAA2B,uBAC/B,YAAY;EACV,IAAI,MACF,OAAO,CAAC;EAGV,MAAM,QAAQ,MAAM,OAAO,KAAK;EAChC,IAAI,MAAM,MAAM;GACd,OAAO;GACP,OAAO,CAAC;EACV;EAEA,OAAO,MAAM,SAAS,CAAC;CACzB,GACA,SACA,MACF,EAAE,KAAK,CAAC,CAAkB;CAE1B,OAAO,IAAI,eAA4B;EACrC,MAAM,KAAK,YAAY;GACrB,MAAM,WAAW,MAAM,yBAAyB,MAAM,SAAS;GAC/D,IAAI,MAAM;IACR,WAAW,MAAM;IACjB;GACF;GAEA,IAAI,SAAS,SAAS,GACpB,WAAW,QAAQ,QAAQ;EAE/B;EACA,MAAM,OAAO,QAAQ;GACnB,OAAO;GACP,MAAM,OAAO,OAAO,MAAM;EAC5B;CACF,CAAC;AACH"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "./channels-
|
|
2
|
-
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "./instrumentation-
|
|
3
|
-
import { t as BaseKafkaStreamReadable } from "./base-kafka-stream-readable-
|
|
1
|
+
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "./channels-DpT3Ilp7.cjs";
|
|
2
|
+
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "./instrumentation-CGxc_url.cjs";
|
|
3
|
+
import { t as BaseKafkaStreamReadable } from "./base-kafka-stream-readable-D9sZX4xL.cjs";
|
|
4
4
|
import { KafkaBatchStreamReadable } from "./streams/kafka-batch-stream-readable.cjs";
|
|
5
5
|
import { KafkaStreamReadable } from "./streams/kafka-stream-readable.cjs";
|
|
6
6
|
import { KafkaClient, KafkaClientConfiguration, StreamConsumerConfiguration, WebStreamConsumer, WebStreamConsumerConfiguration } from "./kafka-client.cjs";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "./channels-
|
|
2
|
-
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "./instrumentation-
|
|
3
|
-
import { t as BaseKafkaStreamReadable } from "./base-kafka-stream-readable-
|
|
1
|
+
import { C as consumerProcessStartChannel, D as producerSendErrorChannel, E as producerSendEndChannel, O as producerSendStartChannel, S as consumerProcessEndChannel, T as consumerReceiveStartChannel, _ as batchProcessEndChannel, a as BatchReceiveStartEvent, b as batchReceiveStartChannel, c as ConsumerProcessEndEvent, d as ConsumerReceiveStartEvent, g as TypedChannel, h as ProducerSendStartEvent, i as BatchReceiveEndEvent, l as ConsumerProcessStartEvent, m as ProducerSendErrorEvent, n as BatchProcessEndEvent, o as CHANNEL_NAMES, p as ProducerSendEndEvent, r as BatchProcessStartEvent, s as ChannelName, t as BaseEvent, u as ConsumerReceiveEndEvent, v as batchProcessStartChannel, w as consumerReceiveEndChannel, x as channels, y as batchReceiveEndChannel } from "./channels-CtCeIPbt.js";
|
|
2
|
+
import { a as instrumentConsumerReceive, i as instrumentConsumerReadableStream, n as instrumentBatchReadableStream, o as instrumentProducerSend, r as instrumentBatchReceive, t as DiagnosticInstrumentationConfig } from "./instrumentation-CGxc_url.js";
|
|
3
|
+
import { t as BaseKafkaStreamReadable } from "./base-kafka-stream-readable-D9sZX4xL.js";
|
|
4
4
|
import { KafkaBatchStreamReadable } from "./streams/kafka-batch-stream-readable.js";
|
|
5
5
|
import { KafkaStreamReadable } from "./streams/kafka-stream-readable.js";
|
|
6
6
|
import { KafkaClient, KafkaClientConfiguration, StreamConsumerConfiguration, WebStreamConsumer, WebStreamConsumerConfiguration } from "./kafka-client.js";
|
|
@@ -34,4 +34,4 @@ declare function instrumentConsumerReadableStream<StreamMessage extends Message>
|
|
|
34
34
|
declare function instrumentBatchReadableStream<StreamBatch extends Message[]>(originalStream: ReadableStream<StreamBatch>, groupId: string | undefined, size: number, timeoutMs: number, config?: DiagnosticInstrumentationConfig): ReadableStream<StreamBatch>;
|
|
35
35
|
//#endregion
|
|
36
36
|
export { instrumentConsumerReceive as a, instrumentConsumerReadableStream as i, instrumentBatchReadableStream as n, instrumentProducerSend as o, instrumentBatchReceive as r, DiagnosticInstrumentationConfig as t };
|
|
37
|
-
//# sourceMappingURL=instrumentation-
|
|
37
|
+
//# sourceMappingURL=instrumentation-CGxc_url.d.cts.map
|
|
@@ -34,4 +34,4 @@ declare function instrumentConsumerReadableStream<StreamMessage extends Message>
|
|
|
34
34
|
declare function instrumentBatchReadableStream<StreamBatch extends Message[]>(originalStream: ReadableStream<StreamBatch>, groupId: string | undefined, size: number, timeoutMs: number, config?: DiagnosticInstrumentationConfig): ReadableStream<StreamBatch>;
|
|
35
35
|
//#endregion
|
|
36
36
|
export { instrumentConsumerReceive as a, instrumentConsumerReadableStream as i, instrumentBatchReadableStream as n, instrumentProducerSend as o, instrumentBatchReceive as r, DiagnosticInstrumentationConfig as t };
|
|
37
|
-
//# sourceMappingURL=instrumentation-
|
|
37
|
+
//# sourceMappingURL=instrumentation-CGxc_url.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kafka-client.cjs","names":["KafkaClientConfig","KafkaBatchStreamReadable","instrumentBatchReadableStream","KafkaStreamReadable","instrumentConsumerReadableStream","instrumentProducerSend","instrumentConsumerReceive","instrumentBatchReceive"],"sources":["../js-src/kafka-client.ts"],"sourcesContent":["import type { ReadableOptions } from 'node:stream'\nimport {\n type CompactMessageBatch,\n type ConsumerConfiguration,\n KafkaClientConfig,\n type KafkaConfiguration,\n type KafkaConsumer,\n type KafkaProducer,\n type Message,\n type ProducerConfiguration,\n} from '../js-binding.js'\n\nimport {\n instrumentBatchReadableStream,\n instrumentBatchReceive,\n instrumentConsumerReadableStream,\n instrumentConsumerReceive,\n instrumentProducerSend,\n} from './diagnostics/instrumentation.js'\nimport { KafkaBatchStreamReadable } from './streams/kafka-batch-stream-readable.js'\nimport { KafkaStreamReadable } from './streams/kafka-stream-readable.js'\n\nconst DEFAULT_WEB_STREAM_BATCH_TIMEOUT = 1000\nconst DEFAULT_WEB_STREAM_SERIAL_PREFETCH_SIZE = 64\nconst DEFAULT_WEB_STREAM_SERIAL_PREFETCH_TIMEOUT = 1\nconst LEGACY_STREAM_SERIAL_COLLECTOR_SIZE = 1\nconst LEGACY_STREAM_SERIAL_COLLECTOR_TIMEOUT = 1000\n\ntype KafkaConsumerWithWebStream = KafkaConsumer & {\n recvStream(prefetchSize?: number, prefetchTimeoutMs?: number): ReadableStream<Message>\n recvBatchStream(size: number, timeoutMs: number): ReadableStream<Message[]>\n recvBatchStreamCompact(size: number, timeoutMs: number): ReadableStream<CompactMessageBatch>\n}\n\nexport interface StreamConsumerConfiguration extends ConsumerConfiguration {\n batchSize?: number // Default 1 (single mode), > 1 enables batch mode\n batchTimeout?: number // Default 100ms, only used when batchSize > 1\n streamOptions?: ReadableOptions\n}\n\nexport interface WebStreamConsumerConfiguration extends ConsumerConfiguration {\n batchSize?: number // Default 1 (single mode), > 1 enables batch mode\n batchTimeout?: number // Default 1000ms\n serialPrefetchSize?: number // Default 64, only used in serial mode\n serialPrefetchTimeout?: number // Default 1ms, only used in serial mode\n}\n\nexport type WebStreamConsumer =\n | {\n mode: 'serial'\n consumer: KafkaConsumer\n stream: ReadableStream<Message>\n }\n | {\n mode: 'batch'\n consumer: KafkaConsumer\n stream: ReadableStream<Message[]>\n }\n\ntype SerialBatchSize = 0 | 1 | undefined\ntype NumericLiteral<BatchSizeValue extends number> = number extends BatchSizeValue ? never : BatchSizeValue\ntype BatchLiteralSize<BatchSizeValue extends number> = BatchSizeValue extends 0 | 1\n ? never\n : NumericLiteral<BatchSizeValue>\n\ntype SerialWebStreamConsumer = Extract<WebStreamConsumer, { mode: 'serial' }>\ntype BatchWebStreamConsumer = Extract<WebStreamConsumer, { mode: 'batch' }>\n\ntype SerialWebStreamConsumerConfiguration = Omit<WebStreamConsumerConfiguration, 'batchSize'> & {\n batchSize?: SerialBatchSize\n}\n\ntype BatchLiteralWebStreamConsumerConfiguration<BatchSizeValue extends number> = Omit<\n WebStreamConsumerConfiguration,\n 'batchSize'\n> & {\n batchSize: BatchLiteralSize<BatchSizeValue>\n}\n\ntype DynamicBatchWebStreamConsumerConfiguration = Omit<WebStreamConsumerConfiguration, 'batchSize'> & {\n batchSize: number\n}\n\nfunction flattenBatchStream(batchStream: ReadableStream<Message[]>): ReadableStream<Message> {\n const reader = batchStream.getReader()\n let currentBatch: Message[] = []\n let currentIndex = 0\n let closed = false\n\n return new ReadableStream<Message>({\n async pull(controller) {\n if (currentIndex < currentBatch.length) {\n controller.enqueue(currentBatch[currentIndex]!)\n currentIndex += 1\n return\n }\n\n if (closed) {\n controller.close()\n return\n }\n\n while (true) {\n const { value, done } = await reader.read()\n if (done || !value) {\n closed = true\n controller.close()\n return\n }\n\n if (value.length === 0) {\n continue\n }\n\n currentBatch = value\n currentIndex = 1\n controller.enqueue(currentBatch[0]!)\n return\n }\n },\n cancel(reason) {\n closed = true\n currentBatch = []\n currentIndex = 0\n // Avoid blocking downstream cancellation on the upstream batch reader.\n void reader.cancel(reason).catch(() => undefined)\n },\n })\n}\n\nfunction expandCompactBatch(batch: CompactMessageBatch): Message[] {\n const {\n payloads,\n keys,\n sharedKey,\n keyDictionary,\n keyDictionaryIndexes,\n topic,\n topics,\n partitions,\n offsets,\n sharedHeaderKey,\n sharedHeaderValue,\n sharedHeaderValues,\n headers,\n } = batch\n\n if (\n topic !== undefined &&\n topics === undefined &&\n keyDictionary !== undefined &&\n keyDictionaryIndexes !== undefined &&\n sharedHeaderKey !== undefined &&\n sharedHeaderValue !== undefined &&\n sharedHeaderValues === undefined &&\n headers === undefined\n ) {\n return expandCompactBatchSharedTopicWithKeyDictionaryAndSharedHeaderValue(\n payloads,\n keyDictionary,\n keyDictionaryIndexes,\n topic,\n partitions,\n offsets,\n sharedHeaderKey,\n sharedHeaderValue,\n )\n }\n\n if (\n topic !== undefined &&\n topics === undefined &&\n sharedKey !== undefined &&\n sharedHeaderKey !== undefined &&\n sharedHeaderValue !== undefined &&\n sharedHeaderValues === undefined &&\n headers === undefined\n ) {\n return expandCompactBatchSharedTopicWithSharedKeyAndSharedHeaderValue(\n payloads,\n sharedKey,\n topic,\n partitions,\n offsets,\n sharedHeaderKey,\n sharedHeaderValue,\n )\n }\n\n const messages = new Array<Message>(payloads.length)\n\n for (let index = 0; index < payloads.length; index += 1) {\n const payload = payloads[index]!\n const dictionaryIndex = keyDictionaryIndexes?.[index]\n const key =\n sharedKey ?? keys?.[index] ?? (dictionaryIndex === undefined ? undefined : keyDictionary?.[dictionaryIndex])\n const sharedValue = sharedHeaderValue ?? sharedHeaderValues?.[index]\n const messageHeaders =\n headers?.[index] ??\n (sharedHeaderKey !== undefined && sharedValue !== undefined ? { [sharedHeaderKey]: sharedValue } : undefined)\n const messageTopic = (topic ?? topics?.[index])!\n const partition = partitions[index]!\n const offset = offsets[index]!\n\n messages[index] = createCompactMessage(payload, key, messageHeaders, messageTopic, partition, offset)\n }\n\n return messages\n}\n\nfunction expandCompactBatchSharedTopicWithKeyDictionaryAndSharedHeaderValue(\n payloads: Buffer[],\n keyDictionary: Buffer[],\n keyDictionaryIndexes: number[],\n topic: string,\n partitions: number[],\n offsets: number[],\n sharedHeaderKey: string,\n sharedHeaderValue: Buffer,\n): Message[] {\n const messages = new Array<Message>(payloads.length)\n\n for (let index = 0; index < payloads.length; index += 1) {\n messages[index] = {\n payload: payloads[index]!,\n key: keyDictionary[keyDictionaryIndexes[index]!]!,\n headers: {\n [sharedHeaderKey]: sharedHeaderValue,\n },\n topic,\n partition: partitions[index]!,\n offset: offsets[index]!,\n }\n }\n\n return messages\n}\n\nfunction expandCompactBatchSharedTopicWithSharedKeyAndSharedHeaderValue(\n payloads: Buffer[],\n sharedKey: Buffer,\n topic: string,\n partitions: number[],\n offsets: number[],\n sharedHeaderKey: string,\n sharedHeaderValue: Buffer,\n): Message[] {\n const messages = new Array<Message>(payloads.length)\n\n for (let index = 0; index < payloads.length; index += 1) {\n messages[index] = {\n payload: payloads[index]!,\n key: sharedKey,\n headers: {\n [sharedHeaderKey]: sharedHeaderValue,\n },\n topic,\n partition: partitions[index]!,\n offset: offsets[index]!,\n }\n }\n\n return messages\n}\n\nfunction createCompactMessage(\n payload: Buffer,\n key: Buffer | undefined,\n headers: Record<string, Buffer> | undefined,\n topic: string,\n partition: number,\n offset: number,\n): Message {\n return {\n payload,\n ...(key === undefined ? {} : { key }),\n ...(headers === undefined ? {} : { headers }),\n topic,\n partition,\n offset,\n }\n}\n\nfunction expandCompactBatchStream(compactStream: ReadableStream<CompactMessageBatch>): ReadableStream<Message[]> {\n const reader = compactStream.getReader()\n let closed = false\n\n return new ReadableStream<Message[]>({\n async pull(controller) {\n if (closed) {\n controller.close()\n return\n }\n\n const { value, done } = await reader.read()\n if (done || !value) {\n closed = true\n controller.close()\n return\n }\n\n controller.enqueue(expandCompactBatch(value))\n },\n async cancel(reason) {\n closed = true\n await reader.cancel(reason)\n },\n })\n}\n\nfunction createMetadataBatchStream(\n consumer: KafkaConsumerWithWebStream,\n batchSize: number,\n batchTimeout: number,\n): ReadableStream<Message[]> {\n return expandCompactBatchStream(consumer.recvBatchStreamCompact(batchSize, batchTimeout))\n}\n\nexport interface KafkaClientConfiguration extends Omit<KafkaConfiguration, 'clientId'> {\n /**\n * Optional client id; defaults to librdkafka's default (`rdkafka`).\n *\n * See: https://github.com/confluentinc/librdkafka/blob/master/CONFIGURATION.md\n */\n clientId?: string\n /**\n * Enable diagnostic channel instrumentation. Defaults to true.\n * Set to false to disable all diagnostic channel events.\n */\n diagnostics?: boolean\n}\n\n/**\n * KafkaClient class\n *\n * Core Kafka client that emits events via diagnostic channels.\n * For OpenTelemetry support, install kafka-crab-js-otel and call enableOtelInstrumentation().\n */\nexport class KafkaClient {\n private readonly kafkaClientConfig: KafkaClientConfig\n private readonly kafkaConfiguration: KafkaClientConfiguration & { clientId: string }\n private readonly _diagnosticsEnabled: boolean\n private readonly _diagnosticsConfig: {\n clientId?: string\n serverAddress?: string\n serverPort?: number\n }\n\n /**\n * Creates a KafkaClient instance\n * @throws {Error} If the configuration is invalid\n */\n public constructor(kafkaConfiguration: KafkaClientConfiguration) {\n const resolvedClientId = kafkaConfiguration.clientId ?? 'rdkafka'\n this.kafkaConfiguration = { ...kafkaConfiguration, clientId: resolvedClientId }\n\n // Extract configuration\n const { diagnostics, ...kafkaConfig } = this.kafkaConfiguration\n this.kafkaClientConfig = new KafkaClientConfig(kafkaConfig as KafkaConfiguration)\n\n // Diagnostics defaults to true\n this._diagnosticsEnabled = diagnostics !== false\n\n // Extract broker info for diagnostics\n const firstBroker = this.kafkaConfiguration.brokers.split(',')[0]?.trim()\n const [brokerHostRaw, brokerPortRaw] = firstBroker ? firstBroker.split(':') : [undefined, undefined]\n const brokerHost = brokerHostRaw?.trim()\n const brokerPort = brokerPortRaw ? Number(brokerPortRaw) : undefined\n\n this._diagnosticsConfig = {\n clientId: this.kafkaConfiguration.clientId,\n ...(brokerHost ? { serverAddress: brokerHost } : {}),\n ...(Number.isFinite(brokerPort) ? { serverPort: brokerPort } : {}),\n }\n }\n\n /**\n * Creates a KafkaProducer instance\n * @param {ProducerConfiguration} [producerConfiguration] - Optional producer configuration\n * @returns {KafkaProducer} A KafkaProducer instance\n */\n public createProducer(producerConfiguration?: ProducerConfiguration) {\n const producer = producerConfiguration\n ? this.kafkaClientConfig.createProducer(producerConfiguration)\n : this.kafkaClientConfig.createProducer({})\n\n // Instrument producer for diagnostic channels if enabled\n if (this._diagnosticsEnabled) {\n return this._instrumentProducer(producer)\n }\n\n return producer\n }\n\n /**\n * Creates a KafkaConsumer instance\n * @param {ConsumerConfiguration} consumerConfiguration - Consumer configuration\n * @returns {KafkaConsumer} A KafkaConsumer instance\n * @throws {Error} If the configuration is invalid\n */\n public createConsumer(consumerConfiguration: ConsumerConfiguration) {\n const consumer = this.kafkaClientConfig.createConsumer(consumerConfiguration)\n\n // Instrument consumer for diagnostic channels if enabled\n if (this._diagnosticsEnabled) {\n return this._instrumentConsumer(consumer, consumerConfiguration.groupId)\n }\n\n return consumer\n }\n\n /**\n * Creates a stream consumer instance\n * @param {StreamConsumerConfiguration} streamConfiguration - Stream consumer configuration including batch mode and stream options\n * @returns {KafkaStreamReadable | KafkaBatchStreamReadable} A stream consumer instance\n * @throws {Error} If the configuration is invalid\n */\n public createStreamConsumer(\n streamConfiguration: StreamConsumerConfiguration,\n ): KafkaStreamReadable | KafkaBatchStreamReadable {\n const { batchSize, batchTimeout, streamOptions, ...consumerConfiguration } = streamConfiguration\n const kafkaConsumer = this.kafkaClientConfig.createConsumer(consumerConfiguration)\n const instrumentedConsumer = this._diagnosticsEnabled\n ? this._instrumentConsumer(kafkaConsumer, consumerConfiguration.groupId)\n : kafkaConsumer\n const webStreamConsumer = instrumentedConsumer as KafkaConsumerWithWebStream\n const opts = streamOptions ?? { objectMode: true }\n\n if (batchSize && batchSize > 1) {\n const resolvedBatchTimeout = batchTimeout ?? DEFAULT_WEB_STREAM_BATCH_TIMEOUT\n const batchStream = createMetadataBatchStream(webStreamConsumer, batchSize, resolvedBatchTimeout)\n const instrumentedBatchStream = this._diagnosticsEnabled\n ? instrumentBatchReadableStream(\n batchStream,\n consumerConfiguration.groupId,\n batchSize,\n resolvedBatchTimeout,\n this._diagnosticsConfig,\n )\n : batchStream\n\n return new KafkaBatchStreamReadable({\n kafkaConsumer: instrumentedConsumer,\n batchSize,\n batchTimeout: resolvedBatchTimeout,\n sourceStream: instrumentedBatchStream,\n ...opts,\n })\n }\n\n const serialBatchStream = createMetadataBatchStream(\n webStreamConsumer,\n LEGACY_STREAM_SERIAL_COLLECTOR_SIZE,\n LEGACY_STREAM_SERIAL_COLLECTOR_TIMEOUT,\n )\n const serialStream = flattenBatchStream(serialBatchStream)\n const instrumentedSerialStream = this._diagnosticsEnabled\n ? instrumentConsumerReadableStream(serialStream, consumerConfiguration.groupId, this._diagnosticsConfig)\n : serialStream\n\n return new KafkaStreamReadable({\n kafkaConsumer: instrumentedConsumer,\n sourceStream: instrumentedSerialStream,\n ...opts,\n })\n }\n\n /**\n * Creates a native WebStream consumer.\n * @param {WebStreamConsumerConfiguration} streamConfiguration - Stream consumer configuration\n * @returns {WebStreamConsumer} Native WebStream consumer and raw consumer pair\n */\n public createWebStreamConsumer(streamConfiguration: SerialWebStreamConsumerConfiguration): SerialWebStreamConsumer\n public createWebStreamConsumer<const BatchSizeValue extends number>(\n streamConfiguration: BatchLiteralWebStreamConsumerConfiguration<BatchSizeValue>,\n ): BatchWebStreamConsumer\n public createWebStreamConsumer(streamConfiguration: DynamicBatchWebStreamConsumerConfiguration): WebStreamConsumer\n public createWebStreamConsumer(streamConfiguration: WebStreamConsumerConfiguration): WebStreamConsumer {\n const { batchSize, batchTimeout, serialPrefetchSize, serialPrefetchTimeout, ...consumerConfiguration } =\n streamConfiguration\n\n const kafkaConsumer = this.kafkaClientConfig.createConsumer(consumerConfiguration)\n const instrumentedConsumer = this._diagnosticsEnabled\n ? this._instrumentConsumer(kafkaConsumer, consumerConfiguration.groupId)\n : kafkaConsumer\n const webStreamConsumer = instrumentedConsumer as KafkaConsumerWithWebStream\n\n if (batchSize && batchSize > 1) {\n const resolvedBatchTimeout = batchTimeout ?? DEFAULT_WEB_STREAM_BATCH_TIMEOUT\n const stream = createMetadataBatchStream(webStreamConsumer, batchSize, resolvedBatchTimeout)\n const instrumentedStream = this._diagnosticsEnabled\n ? instrumentBatchReadableStream(\n stream,\n consumerConfiguration.groupId,\n batchSize,\n resolvedBatchTimeout,\n this._diagnosticsConfig,\n )\n : stream\n\n return {\n mode: 'batch',\n consumer: instrumentedConsumer,\n stream: instrumentedStream,\n }\n }\n\n const resolvedPrefetchSize =\n serialPrefetchSize && serialPrefetchSize > 1 ? serialPrefetchSize : DEFAULT_WEB_STREAM_SERIAL_PREFETCH_SIZE\n const resolvedPrefetchTimeout = serialPrefetchTimeout ?? DEFAULT_WEB_STREAM_SERIAL_PREFETCH_TIMEOUT\n const serialStream = flattenBatchStream(\n createMetadataBatchStream(webStreamConsumer, resolvedPrefetchSize, resolvedPrefetchTimeout),\n )\n const instrumentedStream = this._diagnosticsEnabled\n ? instrumentConsumerReadableStream(serialStream, consumerConfiguration.groupId, this._diagnosticsConfig)\n : serialStream\n\n return {\n mode: 'serial',\n consumer: instrumentedConsumer,\n stream: instrumentedStream,\n }\n }\n\n private _instrumentProducer(producer: KafkaProducer) {\n const originalSend = producer.send.bind(producer)\n\n // Use diagnostic channel-based instrumentation for near-zero overhead when no subscribers\n producer.send = instrumentProducerSend(originalSend, this._diagnosticsConfig)\n\n return producer\n }\n\n private _instrumentConsumer(consumer: KafkaConsumer, groupId?: string) {\n const originalRecv = consumer.recv.bind(consumer)\n const originalRecvBatch = consumer.recvBatch.bind(consumer)\n\n // Use diagnostic channel-based instrumentation for near-zero overhead when no subscribers\n consumer.recv = instrumentConsumerReceive(originalRecv, groupId, this._diagnosticsConfig)\n consumer.recvBatch = instrumentBatchReceive(originalRecvBatch, groupId, this._diagnosticsConfig)\n\n return consumer\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"kafka-client.cjs","names":["KafkaClientConfig","KafkaBatchStreamReadable","instrumentBatchReadableStream","KafkaStreamReadable","instrumentConsumerReadableStream","instrumentProducerSend","instrumentConsumerReceive","instrumentBatchReceive"],"sources":["../js-src/kafka-client.ts"],"sourcesContent":["import type { ReadableOptions } from 'node:stream'\nimport {\n type CompactMessageBatch,\n type ConsumerConfiguration,\n KafkaClientConfig,\n type KafkaConfiguration,\n type KafkaConsumer,\n type KafkaProducer,\n type Message,\n type ProducerConfiguration,\n} from '../js-binding.js'\n\nimport {\n instrumentBatchReadableStream,\n instrumentBatchReceive,\n instrumentConsumerReadableStream,\n instrumentConsumerReceive,\n instrumentProducerSend,\n} from './diagnostics/instrumentation.js'\nimport { KafkaBatchStreamReadable } from './streams/kafka-batch-stream-readable.js'\nimport { KafkaStreamReadable } from './streams/kafka-stream-readable.js'\n\nconst DEFAULT_WEB_STREAM_BATCH_TIMEOUT = 1000\nconst DEFAULT_WEB_STREAM_SERIAL_PREFETCH_SIZE = 64\nconst DEFAULT_WEB_STREAM_SERIAL_PREFETCH_TIMEOUT = 1\nconst LEGACY_STREAM_SERIAL_COLLECTOR_SIZE = 1\nconst LEGACY_STREAM_SERIAL_COLLECTOR_TIMEOUT = 1000\n\ntype KafkaConsumerWithWebStream = KafkaConsumer & {\n recvStream(prefetchSize?: number, prefetchTimeoutMs?: number): ReadableStream<Message>\n recvBatchStream(size: number, timeoutMs: number): ReadableStream<Message[]>\n recvBatchStreamCompact(size: number, timeoutMs: number): ReadableStream<CompactMessageBatch>\n}\n\nexport interface StreamConsumerConfiguration extends ConsumerConfiguration {\n batchSize?: number // Default 1 (single mode), > 1 enables batch mode\n batchTimeout?: number // Default 100ms, only used when batchSize > 1\n streamOptions?: ReadableOptions\n}\n\nexport interface WebStreamConsumerConfiguration extends ConsumerConfiguration {\n batchSize?: number // Default 1 (single mode), > 1 enables batch mode\n batchTimeout?: number // Default 1000ms\n serialPrefetchSize?: number // Default 64, only used in serial mode\n serialPrefetchTimeout?: number // Default 1ms, only used in serial mode\n}\n\nexport type WebStreamConsumer =\n | {\n mode: 'serial'\n consumer: KafkaConsumer\n stream: ReadableStream<Message>\n }\n | {\n mode: 'batch'\n consumer: KafkaConsumer\n stream: ReadableStream<Message[]>\n }\n\ntype SerialBatchSize = 0 | 1 | undefined\ntype NumericLiteral<BatchSizeValue extends number> = number extends BatchSizeValue ? never : BatchSizeValue\ntype BatchLiteralSize<BatchSizeValue extends number> = BatchSizeValue extends 0 | 1\n ? never\n : NumericLiteral<BatchSizeValue>\n\ntype SerialWebStreamConsumer = Extract<WebStreamConsumer, { mode: 'serial' }>\ntype BatchWebStreamConsumer = Extract<WebStreamConsumer, { mode: 'batch' }>\n\ntype SerialWebStreamConsumerConfiguration = Omit<WebStreamConsumerConfiguration, 'batchSize'> & {\n batchSize?: SerialBatchSize\n}\n\ntype BatchLiteralWebStreamConsumerConfiguration<BatchSizeValue extends number> = Omit<\n WebStreamConsumerConfiguration,\n 'batchSize'\n> & {\n batchSize: BatchLiteralSize<BatchSizeValue>\n}\n\ntype DynamicBatchWebStreamConsumerConfiguration = Omit<WebStreamConsumerConfiguration, 'batchSize'> & {\n batchSize: number\n}\n\nfunction flattenBatchStream(batchStream: ReadableStream<Message[]>): ReadableStream<Message> {\n const reader = batchStream.getReader()\n let currentBatch: Message[] = []\n let currentIndex = 0\n let closed = false\n\n return new ReadableStream<Message>({\n async pull(controller) {\n if (currentIndex < currentBatch.length) {\n controller.enqueue(currentBatch[currentIndex]!)\n currentIndex += 1\n return\n }\n\n if (closed) {\n controller.close()\n return\n }\n\n while (true) {\n const { value, done } = await reader.read()\n if (done || !value) {\n closed = true\n controller.close()\n return\n }\n\n if (value.length === 0) {\n continue\n }\n\n currentBatch = value\n currentIndex = 1\n controller.enqueue(currentBatch[0]!)\n return\n }\n },\n cancel(reason) {\n closed = true\n currentBatch = []\n currentIndex = 0\n // Avoid blocking downstream cancellation on the upstream batch reader.\n void reader.cancel(reason).catch(() => undefined)\n },\n })\n}\n\nfunction expandCompactBatch(batch: CompactMessageBatch): Message[] {\n const {\n payloads,\n keys,\n sharedKey,\n keyDictionary,\n keyDictionaryIndexes,\n topic,\n topics,\n partitions,\n offsets,\n sharedHeaderKey,\n sharedHeaderValue,\n sharedHeaderValues,\n headers,\n } = batch\n\n if (\n topic !== undefined &&\n topics === undefined &&\n keyDictionary !== undefined &&\n keyDictionaryIndexes !== undefined &&\n sharedHeaderKey !== undefined &&\n sharedHeaderValue !== undefined &&\n sharedHeaderValues === undefined &&\n headers === undefined\n ) {\n return expandCompactBatchSharedTopicWithKeyDictionaryAndSharedHeaderValue(\n payloads,\n keyDictionary,\n keyDictionaryIndexes,\n topic,\n partitions,\n offsets,\n sharedHeaderKey,\n sharedHeaderValue,\n )\n }\n\n if (\n topic !== undefined &&\n topics === undefined &&\n sharedKey !== undefined &&\n sharedHeaderKey !== undefined &&\n sharedHeaderValue !== undefined &&\n sharedHeaderValues === undefined &&\n headers === undefined\n ) {\n return expandCompactBatchSharedTopicWithSharedKeyAndSharedHeaderValue(\n payloads,\n sharedKey,\n topic,\n partitions,\n offsets,\n sharedHeaderKey,\n sharedHeaderValue,\n )\n }\n\n const messages = new Array<Message>(payloads.length)\n\n for (let index = 0; index < payloads.length; index += 1) {\n const payload = payloads[index]!\n const dictionaryIndex = keyDictionaryIndexes?.[index]\n const key =\n sharedKey ?? keys?.[index] ?? (dictionaryIndex === undefined ? undefined : keyDictionary?.[dictionaryIndex])\n const sharedValue = sharedHeaderValue ?? sharedHeaderValues?.[index]\n const messageHeaders =\n headers?.[index] ??\n (sharedHeaderKey !== undefined && sharedValue !== undefined ? { [sharedHeaderKey]: sharedValue } : undefined)\n const messageTopic = (topic ?? topics?.[index])!\n const partition = partitions[index]!\n const offset = offsets[index]!\n\n messages[index] = createCompactMessage(payload, key, messageHeaders, messageTopic, partition, offset)\n }\n\n return messages\n}\n\nfunction expandCompactBatchSharedTopicWithKeyDictionaryAndSharedHeaderValue(\n payloads: Buffer[],\n keyDictionary: Buffer[],\n keyDictionaryIndexes: number[],\n topic: string,\n partitions: number[],\n offsets: number[],\n sharedHeaderKey: string,\n sharedHeaderValue: Buffer,\n): Message[] {\n const messages = new Array<Message>(payloads.length)\n\n for (let index = 0; index < payloads.length; index += 1) {\n messages[index] = {\n payload: payloads[index]!,\n key: keyDictionary[keyDictionaryIndexes[index]!]!,\n headers: {\n [sharedHeaderKey]: sharedHeaderValue,\n },\n topic,\n partition: partitions[index]!,\n offset: offsets[index]!,\n }\n }\n\n return messages\n}\n\nfunction expandCompactBatchSharedTopicWithSharedKeyAndSharedHeaderValue(\n payloads: Buffer[],\n sharedKey: Buffer,\n topic: string,\n partitions: number[],\n offsets: number[],\n sharedHeaderKey: string,\n sharedHeaderValue: Buffer,\n): Message[] {\n const messages = new Array<Message>(payloads.length)\n\n for (let index = 0; index < payloads.length; index += 1) {\n messages[index] = {\n payload: payloads[index]!,\n key: sharedKey,\n headers: {\n [sharedHeaderKey]: sharedHeaderValue,\n },\n topic,\n partition: partitions[index]!,\n offset: offsets[index]!,\n }\n }\n\n return messages\n}\n\nfunction createCompactMessage(\n payload: Buffer,\n key: Buffer | undefined,\n headers: Record<string, Buffer> | undefined,\n topic: string,\n partition: number,\n offset: number,\n): Message {\n return {\n payload,\n ...(key === undefined ? {} : { key }),\n ...(headers === undefined ? {} : { headers }),\n topic,\n partition,\n offset,\n }\n}\n\nfunction expandCompactBatchStream(compactStream: ReadableStream<CompactMessageBatch>): ReadableStream<Message[]> {\n const reader = compactStream.getReader()\n let closed = false\n\n return new ReadableStream<Message[]>({\n async pull(controller) {\n if (closed) {\n controller.close()\n return\n }\n\n const { value, done } = await reader.read()\n if (done || !value) {\n closed = true\n controller.close()\n return\n }\n\n controller.enqueue(expandCompactBatch(value))\n },\n async cancel(reason) {\n closed = true\n await reader.cancel(reason)\n },\n })\n}\n\nfunction createMetadataBatchStream(\n consumer: KafkaConsumerWithWebStream,\n batchSize: number,\n batchTimeout: number,\n): ReadableStream<Message[]> {\n return expandCompactBatchStream(consumer.recvBatchStreamCompact(batchSize, batchTimeout))\n}\n\nexport interface KafkaClientConfiguration extends Omit<KafkaConfiguration, 'clientId'> {\n /**\n * Optional client id; defaults to librdkafka's default (`rdkafka`).\n *\n * See: https://github.com/confluentinc/librdkafka/blob/master/CONFIGURATION.md\n */\n clientId?: string\n /**\n * Enable diagnostic channel instrumentation. Defaults to true.\n * Set to false to disable all diagnostic channel events.\n */\n diagnostics?: boolean\n}\n\n/**\n * KafkaClient class\n *\n * Core Kafka client that emits events via diagnostic channels.\n * For OpenTelemetry support, install kafka-crab-js-otel and call enableOtelInstrumentation().\n */\nexport class KafkaClient {\n private readonly kafkaClientConfig: KafkaClientConfig\n private readonly kafkaConfiguration: KafkaClientConfiguration & { clientId: string }\n private readonly _diagnosticsEnabled: boolean\n private readonly _diagnosticsConfig: {\n clientId?: string\n serverAddress?: string\n serverPort?: number\n }\n\n /**\n * Creates a KafkaClient instance\n * @throws {Error} If the configuration is invalid\n */\n public constructor(kafkaConfiguration: KafkaClientConfiguration) {\n const resolvedClientId = kafkaConfiguration.clientId ?? 'rdkafka'\n this.kafkaConfiguration = { ...kafkaConfiguration, clientId: resolvedClientId }\n\n // Extract configuration\n const { diagnostics, ...kafkaConfig } = this.kafkaConfiguration\n this.kafkaClientConfig = new KafkaClientConfig(kafkaConfig as KafkaConfiguration)\n\n // Diagnostics defaults to true\n this._diagnosticsEnabled = diagnostics !== false\n\n // Extract broker info for diagnostics\n const firstBroker = this.kafkaConfiguration.brokers.split(',')[0]?.trim()\n const [brokerHostRaw, brokerPortRaw] = firstBroker ? firstBroker.split(':') : [undefined, undefined]\n const brokerHost = brokerHostRaw?.trim()\n const brokerPort = brokerPortRaw ? Number(brokerPortRaw) : undefined\n\n this._diagnosticsConfig = {\n clientId: this.kafkaConfiguration.clientId,\n ...(brokerHost ? { serverAddress: brokerHost } : {}),\n ...(Number.isFinite(brokerPort) ? { serverPort: brokerPort } : {}),\n }\n }\n\n /**\n * Creates a KafkaProducer instance\n * @param {ProducerConfiguration} [producerConfiguration] - Optional producer configuration\n * @returns {KafkaProducer} A KafkaProducer instance\n */\n public createProducer(producerConfiguration?: ProducerConfiguration) {\n const producer = producerConfiguration\n ? this.kafkaClientConfig.createProducer(producerConfiguration)\n : this.kafkaClientConfig.createProducer({})\n\n // Instrument producer for diagnostic channels if enabled\n if (this._diagnosticsEnabled) {\n return this._instrumentProducer(producer)\n }\n\n return producer\n }\n\n /**\n * Creates a KafkaConsumer instance\n * @param {ConsumerConfiguration} consumerConfiguration - Consumer configuration\n * @returns {KafkaConsumer} A KafkaConsumer instance\n * @throws {Error} If the configuration is invalid\n */\n public createConsumer(consumerConfiguration: ConsumerConfiguration) {\n const consumer = this.kafkaClientConfig.createConsumer(consumerConfiguration)\n\n // Instrument consumer for diagnostic channels if enabled\n if (this._diagnosticsEnabled) {\n return this._instrumentConsumer(consumer, consumerConfiguration.groupId)\n }\n\n return consumer\n }\n\n /**\n * Creates a stream consumer instance\n * @param {StreamConsumerConfiguration} streamConfiguration - Stream consumer configuration including batch mode and stream options\n * @returns {KafkaStreamReadable | KafkaBatchStreamReadable} A stream consumer instance\n * @throws {Error} If the configuration is invalid\n */\n public createStreamConsumer(\n streamConfiguration: StreamConsumerConfiguration,\n ): KafkaStreamReadable | KafkaBatchStreamReadable {\n const { batchSize, batchTimeout, streamOptions, ...consumerConfiguration } = streamConfiguration\n const kafkaConsumer = this.kafkaClientConfig.createConsumer(consumerConfiguration)\n const instrumentedConsumer = this._diagnosticsEnabled\n ? this._instrumentConsumer(kafkaConsumer, consumerConfiguration.groupId)\n : kafkaConsumer\n const webStreamConsumer = instrumentedConsumer as KafkaConsumerWithWebStream\n const opts = streamOptions ?? { objectMode: true }\n\n if (batchSize && batchSize > 1) {\n const resolvedBatchTimeout = batchTimeout ?? DEFAULT_WEB_STREAM_BATCH_TIMEOUT\n const batchStream = createMetadataBatchStream(webStreamConsumer, batchSize, resolvedBatchTimeout)\n const instrumentedBatchStream = this._diagnosticsEnabled\n ? instrumentBatchReadableStream(\n batchStream,\n consumerConfiguration.groupId,\n batchSize,\n resolvedBatchTimeout,\n this._diagnosticsConfig,\n )\n : batchStream\n\n return new KafkaBatchStreamReadable({\n kafkaConsumer: instrumentedConsumer,\n batchSize,\n batchTimeout: resolvedBatchTimeout,\n sourceStream: instrumentedBatchStream,\n ...opts,\n })\n }\n\n const serialBatchStream = createMetadataBatchStream(\n webStreamConsumer,\n LEGACY_STREAM_SERIAL_COLLECTOR_SIZE,\n LEGACY_STREAM_SERIAL_COLLECTOR_TIMEOUT,\n )\n const serialStream = flattenBatchStream(serialBatchStream)\n const instrumentedSerialStream = this._diagnosticsEnabled\n ? instrumentConsumerReadableStream(serialStream, consumerConfiguration.groupId, this._diagnosticsConfig)\n : serialStream\n\n return new KafkaStreamReadable({\n kafkaConsumer: instrumentedConsumer,\n sourceStream: instrumentedSerialStream,\n ...opts,\n })\n }\n\n /**\n * Creates a native WebStream consumer.\n * @param {WebStreamConsumerConfiguration} streamConfiguration - Stream consumer configuration\n * @returns {WebStreamConsumer} Native WebStream consumer and raw consumer pair\n */\n public createWebStreamConsumer(streamConfiguration: SerialWebStreamConsumerConfiguration): SerialWebStreamConsumer\n public createWebStreamConsumer<const BatchSizeValue extends number>(\n streamConfiguration: BatchLiteralWebStreamConsumerConfiguration<BatchSizeValue>,\n ): BatchWebStreamConsumer\n public createWebStreamConsumer(streamConfiguration: DynamicBatchWebStreamConsumerConfiguration): WebStreamConsumer\n public createWebStreamConsumer(streamConfiguration: WebStreamConsumerConfiguration): WebStreamConsumer {\n const { batchSize, batchTimeout, serialPrefetchSize, serialPrefetchTimeout, ...consumerConfiguration } =\n streamConfiguration\n\n const kafkaConsumer = this.kafkaClientConfig.createConsumer(consumerConfiguration)\n const instrumentedConsumer = this._diagnosticsEnabled\n ? this._instrumentConsumer(kafkaConsumer, consumerConfiguration.groupId)\n : kafkaConsumer\n const webStreamConsumer = instrumentedConsumer as KafkaConsumerWithWebStream\n\n if (batchSize && batchSize > 1) {\n const resolvedBatchTimeout = batchTimeout ?? DEFAULT_WEB_STREAM_BATCH_TIMEOUT\n const stream = createMetadataBatchStream(webStreamConsumer, batchSize, resolvedBatchTimeout)\n const instrumentedStream = this._diagnosticsEnabled\n ? instrumentBatchReadableStream(\n stream,\n consumerConfiguration.groupId,\n batchSize,\n resolvedBatchTimeout,\n this._diagnosticsConfig,\n )\n : stream\n\n return {\n mode: 'batch',\n consumer: instrumentedConsumer,\n stream: instrumentedStream,\n }\n }\n\n const resolvedPrefetchSize =\n serialPrefetchSize && serialPrefetchSize > 1 ? serialPrefetchSize : DEFAULT_WEB_STREAM_SERIAL_PREFETCH_SIZE\n const resolvedPrefetchTimeout = serialPrefetchTimeout ?? DEFAULT_WEB_STREAM_SERIAL_PREFETCH_TIMEOUT\n const serialStream = flattenBatchStream(\n createMetadataBatchStream(webStreamConsumer, resolvedPrefetchSize, resolvedPrefetchTimeout),\n )\n const instrumentedStream = this._diagnosticsEnabled\n ? instrumentConsumerReadableStream(serialStream, consumerConfiguration.groupId, this._diagnosticsConfig)\n : serialStream\n\n return {\n mode: 'serial',\n consumer: instrumentedConsumer,\n stream: instrumentedStream,\n }\n }\n\n private _instrumentProducer(producer: KafkaProducer) {\n const originalSend = producer.send.bind(producer)\n\n // Use diagnostic channel-based instrumentation for near-zero overhead when no subscribers\n producer.send = instrumentProducerSend(originalSend, this._diagnosticsConfig)\n\n return producer\n }\n\n private _instrumentConsumer(consumer: KafkaConsumer, groupId?: string) {\n const originalRecv = consumer.recv.bind(consumer)\n const originalRecvBatch = consumer.recvBatch.bind(consumer)\n\n // Use diagnostic channel-based instrumentation for near-zero overhead when no subscribers\n consumer.recv = instrumentConsumerReceive(originalRecv, groupId, this._diagnosticsConfig)\n consumer.recvBatch = instrumentBatchReceive(originalRecvBatch, groupId, this._diagnosticsConfig)\n\n return consumer\n }\n}\n"],"mappings":"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"}
|