From e3bab2cca646fa050617787326af140bf6d3c5dd Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 12:51:48 +0100 Subject: [PATCH 01/58] Fixes --- plugin-server/src/capabilities.ts | 9 + .../src/ingestion/ingestion-consumer.ts | 394 ++++++++++++++++++ plugin-server/src/main/pluginsServer.ts | 10 +- plugin-server/src/types.ts | 2 + 4 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 plugin-server/src/ingestion/ingestion-consumer.ts diff --git a/plugin-server/src/capabilities.ts b/plugin-server/src/capabilities.ts index 9cefda83bb90d..eea615421e876 100644 --- a/plugin-server/src/capabilities.ts +++ b/plugin-server/src/capabilities.ts @@ -12,6 +12,7 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin return { mmdb: true, ingestion: true, + ingestionV2: true, // TODO: remove ingestionOverflow: true, ingestionHistorical: true, eventsIngestionPipelines: true, // with null PluginServerMode we run all of them @@ -30,6 +31,14 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin syncInlinePlugins: true, ...sharedCapabilities, } + case PluginServerMode.ingestion_v2: + // NOTE: this mode will be removed in the future and replaced with + // `analytics-ingestion` and `recordings-ingestion` modes. + return { + mmdb: true, + ingestionV2: true, + ...sharedCapabilities, + } case PluginServerMode.ingestion: // NOTE: this mode will be removed in the future and replaced with // `analytics-ingestion` and `recordings-ingestion` modes. diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts new file mode 100644 index 0000000000000..7cd47d8657fe3 --- /dev/null +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -0,0 +1,394 @@ +import * as Sentry from '@sentry/node' +import { Message, MessageHeader } from 'node-rdkafka' +import { Histogram } from 'prom-client' + +import { KAFKA_EVENTS_PLUGIN_INGESTION, KAFKA_EVENTS_PLUGIN_INGESTION_DLQ } from '../config/kafka-topics' +import { BatchConsumer, startBatchConsumer } from '../kafka/batch-consumer' +import { createRdConnectionConfigFromEnvVars } from '../kafka/config' +import { addSentryBreadcrumbsEventListeners } from '../main/ingestion-queues/kafka-metrics' +import { + eventDroppedCounter, + latestOffsetTimestampGauge, + setUsageInNonPersonEventsCounter, +} from '../main/ingestion-queues/metrics' +import { runInstrumentedFunction } from '../main/utils' +import { Hub, PipelineEvent, PluginServerService } from '../types' +import { createKafkaProducerWrapper } from '../utils/db/hub' +import { KafkaProducerWrapper } from '../utils/db/kafka-producer-wrapper' +import { normalizeEvent } from '../utils/event' +import { retryIfRetriable } from '../utils/retries' +import { status } from '../utils/status' +import { EventPipelineRunner } from '../worker/ingestion/event-pipeline/runner' + +// Must require as `tsc` strips unused `import` statements and just requiring this seems to init some globals +require('@sentry/tracing') + +const histogramKafkaBatchSize = new Histogram({ + name: 'ingestion_batch_size', + help: 'The size of the batches we are receiving from Kafka', + buckets: [0, 50, 100, 250, 500, 750, 1000, 1500, 2000, 3000, Infinity], +}) + +const histogramKafkaBatchSizeKb = new Histogram({ + name: 'ingestion_batch_size_kb', + help: 'The size in kb of the batches we are receiving from Kafka', + buckets: [0, 128, 512, 1024, 5120, 10240, 20480, 51200, 102400, 204800, Infinity], +}) + +type GroupedIncomingEvents = { + [key: string]: { message: Message; event: PipelineEvent }[] +} + +const PERSON_EVENTS = new Set(['$set', '$identify', '$create_alias', '$merge_dangerously', '$groupidentify']) +const KNOWN_SET_EVENTS = new Set([ + '$feature_interaction', + '$feature_enrollment_update', + 'survey dismissed', + 'survey sent', +]) + +abstract class IngestionConsumer { + batchConsumer?: BatchConsumer + isStopping = false + protected kafkaProducer?: KafkaProducerWrapper + protected abstract name: string + protected heartbeat = () => {} + protected promises: Set> = new Set() + + protected scheduleWork(promise: Promise): Promise { + this.promises.add(promise) + void promise.finally(() => this.promises.delete(promise)) + return promise + } + + constructor(protected hub: Hub) {} + + public get service(): PluginServerService { + return { + id: this.name, + onShutdown: async () => await this.stop(), + healthcheck: () => this.isHealthy() ?? false, + batchConsumer: this.batchConsumer, + } + } + + protected async runWithHeartbeat(func: () => Promise | T): Promise { + // Helper function to ensure that looping over lots of hog functions doesn't block up the thread, killing the consumer + const res = await func() + this.heartbeat() + await new Promise((resolve) => process.nextTick(resolve)) + + return res + } + + protected async runManyWithHeartbeat(items: T[], func: (item: T) => Promise | R): Promise { + // Helper function to ensure that looping over lots of hog functions doesn't block up the event loop, leading to healthcheck failures + const results = [] + + for (const item of items) { + results.push(await this.runWithHeartbeat(() => func(item))) + } + return results + } + + // protected async produceQueuedMessages() { + // const messages = [...this.messagesToProduce] + // this.messagesToProduce = [] + // await Promise.all( + // messages.map((x) => + // this.kafkaProducer!.produce({ + // topic: x.topic, + // value: Buffer.from(safeClickhouseString(JSON.stringify(x.value))), + // key: x.key, + // waitForAck: true, + // }).catch((reason) => { + // status.error('⚠️', `failed to produce message: ${reason}`) + // }) + // ) + // ) + // } + + protected async startKafkaConsumer(options: { + topic: string + groupId: string + handleBatch: (messages: Message[]) => Promise + }): Promise { + this.batchConsumer = await startBatchConsumer({ + ...options, + connectionConfig: createRdConnectionConfigFromEnvVars(this.hub), + autoCommit: true, + sessionTimeout: this.hub.KAFKA_CONSUMPTION_SESSION_TIMEOUT_MS, + maxPollIntervalMs: this.hub.KAFKA_CONSUMPTION_MAX_POLL_INTERVAL_MS, + consumerMaxBytes: this.hub.KAFKA_CONSUMPTION_MAX_BYTES, + consumerMaxBytesPerPartition: this.hub.KAFKA_CONSUMPTION_MAX_BYTES_PER_PARTITION, + consumerMaxWaitMs: this.hub.KAFKA_CONSUMPTION_MAX_WAIT_MS, + consumerErrorBackoffMs: this.hub.KAFKA_CONSUMPTION_ERROR_BACKOFF_MS, + fetchBatchSize: this.hub.INGESTION_BATCH_SIZE, + batchingTimeoutMs: this.hub.KAFKA_CONSUMPTION_BATCHING_TIMEOUT_MS, + topicCreationTimeoutMs: this.hub.KAFKA_TOPIC_CREATION_TIMEOUT_MS, + topicMetadataRefreshInterval: this.hub.KAFKA_TOPIC_METADATA_REFRESH_INTERVAL_MS, + eachBatch: async (messages, { heartbeat }) => { + status.info('🔁', `${this.name} - handling batch`, { + size: messages.length, + }) + + this.heartbeat = heartbeat + + histogramKafkaBatchSize.observe(messages.length) + histogramKafkaBatchSizeKb.observe(messages.reduce((acc, m) => (m.value?.length ?? 0) + acc, 0) / 1024) + + return await runInstrumentedFunction({ + statsKey: `ingestionConsumer.handleEachBatch`, + sendTimeoutGuardToSentry: false, + func: async () => { + await options.handleBatch(messages) + }, + }) + }, + callEachBatchWhenEmpty: false, + }) + + addSentryBreadcrumbsEventListeners(this.batchConsumer.consumer) + + this.batchConsumer.consumer.on('disconnected', async (err) => { + if (!this.isStopping) { + return + } + // since we can't be guaranteed that the consumer will be stopped before some other code calls disconnect + // we need to listen to disconnect and make sure we're stopped + status.info('🔁', `${this.name} batch consumer disconnected, cleaning up`, { err }) + await this.stop() + }) + } + + public async start(): Promise { + // NOTE: This is only for starting shared services + await Promise.all([ + createKafkaProducerWrapper(this.hub).then((producer) => { + this.kafkaProducer = producer + this.kafkaProducer.producer.connect() + }), + ]) + } + + public async stop(): Promise { + status.info('🔁', `${this.name} - stopping`) + this.isStopping = true + + // Mark as stopping so that we don't actually process any more incoming messages, but still keep the process alive + status.info('🔁', `${this.name} - stopping batch consumer`) + await this.batchConsumer?.stop() + status.info('🔁', `${this.name} - stopping kafka producer`) + await this.kafkaProducer?.disconnect() + + status.info('👍', `${this.name} - stopped!`) + } + + public isHealthy() { + return this.batchConsumer?.isHealthy() + } +} + +/** + * This consumer handles incoming events from the main kafka ingestion topic + */ +export class EventsIngestionConsumer extends IngestionConsumer { + protected name = 'EventsIngestionConsumer' + protected topic = KAFKA_EVENTS_PLUGIN_INGESTION + protected groupId = 'events-ingestion-consumer' // TODO: Make this configurable + + private tokensToDrop: string[] = [] + private tokenDistinctIdsToDrop: string[] = [] + + constructor(hub: Hub) { + super(hub) + + // TODO: Allow overriding the topic and groupId - this way we don't need all the weird duplicated stuff. + + this.tokensToDrop = hub.DROP_EVENTS_BY_TOKEN.split(',') + this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',') + } + + public async processBatch(groupedIncomingEvents: GroupedIncomingEvents): Promise { + await this.runManyWithHeartbeat(Object.entries(groupedIncomingEvents), async ([key, eventsForDistinctId]) => { + // Process every message sequentially, stash promises to await on later + for (const { message, event } of eventsForDistinctId) { + // Track $set usage in events that aren't known to use it, before ingestion adds anything there + if ( + event.properties && + !PERSON_EVENTS.has(event.event) && + !KNOWN_SET_EVENTS.has(event.event) && + ('$set' in event.properties || '$set_once' in event.properties || '$unset' in event.properties) + ) { + setUsageInNonPersonEventsCounter.inc() + } + + try { + const result = await retryIfRetriable(async () => { + const runner = new EventPipelineRunner(this.hub, event, this.hub.eventsProcessor) + return await runner.runEventPipeline(event) + }) + + result.ackPromises?.forEach((promise) => { + void this.scheduleWork( + promise.catch(async (error) => { + await this.handleProcessingError(error, message, event) + }) + ) + }) + } catch (error) { + await this.handleProcessingError(error, message, event) + } + } + }) + + await Promise.all(this.promises) + } + + private async handleProcessingError(error: any, message: Message, event: PipelineEvent) { + status.error('🔥', `Error processing message`, { + stack: error.stack, + error: error, + }) + + // If the error is a non-retriable error, push to the dlq and commit the offset. Else raise the + // error. + // + // NOTE: there is behavior to push to a DLQ at the moment within EventPipelineRunner. This + // doesn't work so well with e.g. messages that when sent to the DLQ is it's self too large. + // Here we explicitly do _not_ add any additional metadata to the message. We might want to add + // some metadata to the message e.g. in the header or reference e.g. the sentry event id. + // + // TODO: property abstract out this `isRetriable` error logic. This is currently relying on the + // fact that node-rdkafka adheres to the `isRetriable` interface. + if (error?.isRetriable === false) { + const sentryEventId = Sentry.captureException(error) + const headers: MessageHeader[] = message.headers ?? [] + headers.push({ ['sentry-event-id']: sentryEventId }) + headers.push({ ['event-id']: event.uuid }) + try { + await this.kafkaProducer!.produce({ + topic: KAFKA_EVENTS_PLUGIN_INGESTION_DLQ, + value: message.value, + key: message.key ?? null, // avoid undefined, just to be safe + headers: headers, + waitForAck: true, + }) + } catch (error) { + // If we can't send to the DLQ and it's not retriable, just continue. We'll commit the + // offset and move on. + if (error?.isRetriable === false) { + status.error('🔥', `Error pushing to DLQ`, { + stack: error.stack, + error: error, + }) + return + } + + // If we can't send to the DLQ and it is retriable, raise the error. + throw error + } + } else { + throw error + } + } + + private logDroppedEvent(token?: string, distinctId?: string) { + status.debug('🔁', `Dropped event`, { + token, + distinctId, + }) + eventDroppedCounter + .labels({ + event_type: 'analytics', + drop_cause: 'blocked_token', + }) + .inc() + } + + private shouldDropEvent(token?: string, distinctId?: string) { + return ( + (token && this.tokensToDrop.includes(token)) || + (distinctId && this.tokenDistinctIdsToDrop.includes(`${token}:${distinctId}`)) + ) + } + + // This consumer always parses from kafka + public _parseKafkaBatch(messages: Message[]): Promise { + return runInstrumentedFunction({ + statsKey: `ingestionConsumer.handleEachBatch.parseKafkaMessages`, + func: () => { + // 1. Parse the messages filtering out the ones that should be dropped + + const batches: GroupedIncomingEvents = {} + + for (const message of messages) { + let distinctId: string | undefined + let token: string | undefined + + message.headers?.forEach((header) => { + if (header.key === 'distinct_id') { + distinctId = header.value.toString() + } + if (header.key === 'token') { + token = header.value.toString() + } + }) + + if (this.shouldDropEvent(token, distinctId)) { + this.logDroppedEvent(token, distinctId) + continue + } + + // TODO: Comment about this weird structure + const { data: dataStr, ...rawEvent } = JSON.parse(message.value!.toString()) + const combinedEvent: PipelineEvent = { ...JSON.parse(dataStr), ...rawEvent } + const event: PipelineEvent = normalizeEvent({ + ...combinedEvent, + }) + + // In case the headers were not set we check the parsed message now + if (this.shouldDropEvent(combinedEvent.token, combinedEvent.distinct_id)) { + this.logDroppedEvent(combinedEvent.token, combinedEvent.distinct_id) + continue + } + + const eventKey = `${event.token}:${event.distinct_id}` + + // TODO: Add back in overflow detection logic + + // We collect the events grouped by token and distinct_id so that we can process batches in parallel whilst keeping the order of events + // for a given distinct_id + if (!batches[eventKey]) { + batches[eventKey] = [] + } + + batches[eventKey].push({ message, event }) + } + + // 2. Overflow the ones that are supposed to be overflowed + + return Promise.resolve(batches) + }, + }) + } + + public async start(): Promise { + await super.start() + await this.startKafkaConsumer({ + topic: this.topic, + groupId: this.groupId, + handleBatch: async (messages) => { + const invocationGlobals = await this._parseKafkaBatch(messages) + await this.processBatch(invocationGlobals) + for (const message of messages) { + if (message.timestamp) { + latestOffsetTimestampGauge + .labels({ partition: message.partition, topic: message.topic, groupId: this.groupId }) + .set(message.timestamp) + } + } + }, + }) + } +} diff --git a/plugin-server/src/main/pluginsServer.ts b/plugin-server/src/main/pluginsServer.ts index c58b42d1a8ef7..b9aa06a2ee50e 100644 --- a/plugin-server/src/main/pluginsServer.ts +++ b/plugin-server/src/main/pluginsServer.ts @@ -53,6 +53,7 @@ import { startScheduledTasksConsumer } from './ingestion-queues/scheduled-tasks- import { SessionRecordingIngester } from './ingestion-queues/session-recording/session-recordings-consumer' import { expressApp, setupCommonRoutes } from './services/http-server' import { getObjectStorage } from './services/object_storage' +import { EventsIngestionConsumer } from '../ingestion/ingestion-consumer' CompressionCodecs[CompressionTypes.Snappy] = SnappyCodec CompressionCodecs[CompressionTypes.LZ4] = new LZ4().codec @@ -266,6 +267,13 @@ export async function startPluginsServer( } } + if (capabilities.ingestionV2) { + const hub = await setupHub() + const consumer = new EventsIngestionConsumer(hub) + await consumer.start() + services.push(consumer.service) + } + if (capabilities.ingestion) { const hub = await setupHub() piscina = piscina ?? (await makePiscina(serverConfig, hub)) @@ -274,7 +282,7 @@ export async function startPluginsServer( hub: hub, }) ) - } + if (capabilities.ingestionHistorical) { const hub = await setupHub() diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 74f109836c752..60fd198d63b96 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -73,6 +73,7 @@ export enum KafkaSaslMechanism { export enum PluginServerMode { ingestion = 'ingestion', + ingestion_v2 = 'ingestion-v2', ingestion_overflow = 'ingestion-overflow', ingestion_historical = 'ingestion-historical', events_ingestion = 'events-ingestion', @@ -348,6 +349,7 @@ export interface PluginServerCapabilities { ingestionOverflow?: boolean ingestionHistorical?: boolean eventsIngestionPipelines?: boolean + ingestionV2?: boolean pluginScheduledTasks?: boolean processPluginJobs?: boolean processAsyncOnEventHandlers?: boolean From 5330f510f8b3900aeab52ca1ad7582fd14f0e597 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 14:00:42 +0100 Subject: [PATCH 02/58] Fixes --- plugin-server/src/ingestion/ingestion-consumer.ts | 2 +- plugin-server/src/worker/ingestion/event-pipeline/runner.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 7cd47d8657fe3..67929b255c580 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -225,7 +225,7 @@ export class EventsIngestionConsumer extends IngestionConsumer { try { const result = await retryIfRetriable(async () => { - const runner = new EventPipelineRunner(this.hub, event, this.hub.eventsProcessor) + const runner = new EventPipelineRunner(this.hub, event) return await runner.runEventPipeline(event) }) diff --git a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts index dc5cf6d8df186..2655697c06422 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts @@ -54,10 +54,10 @@ export class EventPipelineRunner { originalEvent: PipelineEvent eventsProcessor: EventsProcessor - constructor(hub: Hub, event: PipelineEvent, eventProcessor: EventsProcessor) { + constructor(hub: Hub, event: PipelineEvent) { this.hub = hub this.originalEvent = event - this.eventsProcessor = eventProcessor + this.eventsProcessor = new EventsProcessor(hub) } isEventDisallowed(event: PipelineEvent): boolean { From c3e8070b29adc3be5d6a1dae82d6fa5e6f26c71f Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 15:11:14 +0100 Subject: [PATCH 03/58] More changes --- plugin-server/src/config/config.ts | 7 ++ .../src/ingestion/ingestion-consumer.ts | 68 ++++++++++++++++--- .../analytics-events-ingestion-consumer.ts | 7 -- .../batch-processing/each-batch-ingestion.ts | 9 +-- .../src/main/ingestion-queues/metrics.ts | 6 ++ plugin-server/src/types.ts | 11 ++- .../run-ingestion-pipeline.test.ts | 6 +- .../tests/main/process-event.test.ts | 8 +-- plugin-server/tests/main/teardown.test.ts | 2 +- .../tests/worker/dead-letter-queue.test.ts | 4 +- .../event-pipeline-integration.test.ts | 6 +- 11 files changed, 97 insertions(+), 37 deletions(-) diff --git a/plugin-server/src/config/config.ts b/plugin-server/src/config/config.ts index a2e198ec541e5..b4c369456fa7a 100644 --- a/plugin-server/src/config/config.ts +++ b/plugin-server/src/config/config.ts @@ -5,6 +5,7 @@ import { KAFKA_CLICKHOUSE_HEATMAP_EVENTS, KAFKA_EVENTS_JSON, KAFKA_EVENTS_PLUGIN_INGESTION, + KAFKA_EVENTS_PLUGIN_INGESTION_DLQ, KAFKA_EVENTS_PLUGIN_INGESTION_OVERFLOW, KAFKA_EXCEPTION_SYMBOLIFICATION_EVENTS, } from './kafka-topics' @@ -203,6 +204,12 @@ export function getDefaultConfig(): PluginsServerConfig { : '', CYCLOTRON_SHARD_DEPTH_LIMIT: 1000000, + + // New IngestionConsumer config + INGESTION_CONSUMER_GROUP_ID: 'events-ingestion-consumer', + INGESTION_CONSUMER_CONSUME_TOPIC: KAFKA_EVENTS_PLUGIN_INGESTION, + INGESTION_CONSUMER_OVERFLOW_TOPIC: KAFKA_EVENTS_PLUGIN_INGESTION_OVERFLOW, + INGESTION_CONSUMER_DLQ_TOPIC: KAFKA_EVENTS_PLUGIN_INGESTION_DLQ, } } diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 67929b255c580..1a5d4a34dd14f 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -2,12 +2,14 @@ import * as Sentry from '@sentry/node' import { Message, MessageHeader } from 'node-rdkafka' import { Histogram } from 'prom-client' -import { KAFKA_EVENTS_PLUGIN_INGESTION, KAFKA_EVENTS_PLUGIN_INGESTION_DLQ } from '../config/kafka-topics' import { BatchConsumer, startBatchConsumer } from '../kafka/batch-consumer' import { createRdConnectionConfigFromEnvVars } from '../kafka/config' +import { IngestionOverflowMode } from '../main/ingestion-queues/batch-processing/each-batch-ingestion' +import { ingestionOverflowingMessagesTotal } from '../main/ingestion-queues/batch-processing/metrics' import { addSentryBreadcrumbsEventListeners } from '../main/ingestion-queues/kafka-metrics' import { eventDroppedCounter, + ingestionPartitionKeyOverflowed, latestOffsetTimestampGauge, setUsageInNonPersonEventsCounter, } from '../main/ingestion-queues/metrics' @@ -18,6 +20,7 @@ import { KafkaProducerWrapper } from '../utils/db/kafka-producer-wrapper' import { normalizeEvent } from '../utils/event' import { retryIfRetriable } from '../utils/retries' import { status } from '../utils/status' +import { ConfiguredLimiter, LoggingLimiter } from '../utils/token-bucket' import { EventPipelineRunner } from '../worker/ingestion/event-pipeline/runner' // Must require as `tsc` strips unused `import` statements and just requiring this seems to init some globals @@ -194,8 +197,10 @@ abstract class IngestionConsumer { */ export class EventsIngestionConsumer extends IngestionConsumer { protected name = 'EventsIngestionConsumer' - protected topic = KAFKA_EVENTS_PLUGIN_INGESTION - protected groupId = 'events-ingestion-consumer' // TODO: Make this configurable + protected groupId: string + protected topic: string + protected dlqTopic: string + protected overflowTopic?: string private tokensToDrop: string[] = [] private tokenDistinctIdsToDrop: string[] = [] @@ -203,14 +208,17 @@ export class EventsIngestionConsumer extends IngestionConsumer { constructor(hub: Hub) { super(hub) - // TODO: Allow overriding the topic and groupId - this way we don't need all the weird duplicated stuff. - + // The group and topic are configurable allowing for multiple ingestion consumers to be run in parallel + this.groupId = hub.INGESTION_CONSUMER_GROUP_ID + this.topic = hub.INGESTION_CONSUMER_CONSUME_TOPIC + this.overflowTopic = hub.INGESTION_CONSUMER_OVERFLOW_TOPIC + this.dlqTopic = hub.INGESTION_CONSUMER_DLQ_TOPIC this.tokensToDrop = hub.DROP_EVENTS_BY_TOKEN.split(',') this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',') } public async processBatch(groupedIncomingEvents: GroupedIncomingEvents): Promise { - await this.runManyWithHeartbeat(Object.entries(groupedIncomingEvents), async ([key, eventsForDistinctId]) => { + await this.runManyWithHeartbeat(Object.values(groupedIncomingEvents), async (eventsForDistinctId) => { // Process every message sequentially, stash promises to await on later for (const { message, event } of eventsForDistinctId) { // Track $set usage in events that aren't known to use it, before ingestion adds anything there @@ -268,7 +276,7 @@ export class EventsIngestionConsumer extends IngestionConsumer { headers.push({ ['event-id']: event.uuid }) try { await this.kafkaProducer!.produce({ - topic: KAFKA_EVENTS_PLUGIN_INGESTION_DLQ, + topic: this.dlqTopic, value: message.value, key: message.key ?? null, // avoid undefined, just to be safe headers: headers, @@ -313,6 +321,40 @@ export class EventsIngestionConsumer extends IngestionConsumer { ) } + private overflowEnabled() { + return !!this.hub.INGESTION_OVERFLOW_ENABLED + } + + private async emitToOverflow(kafkaMessages: Message[]) { + const overflowTopic = this.hub.INGESTION_CONSUMER_OVERFLOW_TOPIC + if (!overflowTopic) { + throw new Error('No overflow topic configured') + } + + ingestionOverflowingMessagesTotal.inc(kafkaMessages.length) + + const overflowMode = this.hub.INGESTION_OVERFLOW_PRESERVE_PARTITION_LOCALITY + ? IngestionOverflowMode.Reroute + : IngestionOverflowMode.RerouteRandomly + + const useRandomPartitioning = overflowMode === IngestionOverflowMode.RerouteRandomly + + await Promise.all( + kafkaMessages.map((message) => + this.kafkaProducer!.produce({ + topic: this.overflowTopic!, + value: message.value, + // ``message.key`` should not be undefined here, but in the + // (extremely) unlikely event that it is, set it to ``null`` + // instead as that behavior is safer. + key: useRandomPartitioning ? null : message.key ?? null, + headers: message.headers, + waitForAck: true, + }) + ) + ) + } + // This consumer always parses from kafka public _parseKafkaBatch(messages: Message[]): Promise { return runInstrumentedFunction({ @@ -340,7 +382,6 @@ export class EventsIngestionConsumer extends IngestionConsumer { continue } - // TODO: Comment about this weird structure const { data: dataStr, ...rawEvent } = JSON.parse(message.value!.toString()) const combinedEvent: PipelineEvent = { ...JSON.parse(dataStr), ...rawEvent } const event: PipelineEvent = normalizeEvent({ @@ -355,6 +396,17 @@ export class EventsIngestionConsumer extends IngestionConsumer { const eventKey = `${event.token}:${event.distinct_id}` + if (this.overflowEnabled() && !ConfiguredLimiter.consume(eventKey, 1, message.timestamp)) { + // Local overflow detection triggering, reroute to overflow topic too + ingestionPartitionKeyOverflowed.labels(`${event.team_id ?? event.token}`).inc() + if (LoggingLimiter.consume(eventKey, 1)) { + status.warn('🪣', `Local overflow detection triggered on key ${eventKey}`) + } + + void this.scheduleWork(this.emitToOverflow([message])) + continue + } + // TODO: Add back in overflow detection logic // We collect the events grouped by token and distinct_id so that we can process batches in parallel whilst keeping the order of events diff --git a/plugin-server/src/main/ingestion-queues/analytics-events-ingestion-consumer.ts b/plugin-server/src/main/ingestion-queues/analytics-events-ingestion-consumer.ts index 259d231e9d01a..4d953f61deaeb 100644 --- a/plugin-server/src/main/ingestion-queues/analytics-events-ingestion-consumer.ts +++ b/plugin-server/src/main/ingestion-queues/analytics-events-ingestion-consumer.ts @@ -1,5 +1,4 @@ import { Message } from 'node-rdkafka' -import { Counter } from 'prom-client' import { buildStringMatcher } from '../../config/config' import { KAFKA_EVENTS_PLUGIN_INGESTION, prefix as KAFKA_PREFIX } from '../../config/kafka-topics' @@ -8,12 +7,6 @@ import { status } from '../../utils/status' import { eachBatchParallelIngestion, IngestionOverflowMode } from './batch-processing/each-batch-ingestion' import { IngestionConsumer } from './kafka-queue' -export const ingestionPartitionKeyOverflowed = new Counter({ - name: 'ingestion_partition_key_overflowed', - help: 'Indicates that a given key has overflowed capacity and been redirected to a different topic. Value incremented once a minute.', - labelNames: ['partition_key'], -}) - export const startAnalyticsEventsIngestionConsumer = async ({ hub, // TODO: remove needing to pass in the whole hub and be more selective on dependency injection. }: { diff --git a/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts b/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts index 2757853e02ebc..e6ff3c7ce1eff 100644 --- a/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts +++ b/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts @@ -9,9 +9,8 @@ import { status } from '../../../utils/status' import { ConfiguredLimiter, LoggingLimiter } from '../../../utils/token-bucket' import { EventPipelineRunner } from '../../../worker/ingestion/event-pipeline/runner' import { captureIngestionWarning } from '../../../worker/ingestion/utils' -import { ingestionPartitionKeyOverflowed } from '../analytics-events-ingestion-consumer' import { IngestionConsumer } from '../kafka-queue' -import { eventDroppedCounter, latestOffsetTimestampGauge } from '../metrics' +import { eventDroppedCounter, ingestionPartitionKeyOverflowed, latestOffsetTimestampGauge } from '../metrics' import { ingestEventBatchingBatchCountSummary, ingestEventBatchingDistinctIdBatchLengthSummary, @@ -170,11 +169,7 @@ export async function eachBatchParallelIngestion( for (const { message, pluginEvent } of currentBatch) { try { const result = (await retryIfRetriable(async () => { - const runner = new EventPipelineRunner( - queue.pluginsServer, - pluginEvent, - queue.eventsProcessor - ) + const runner = new EventPipelineRunner(queue.pluginsServer, pluginEvent) return await runner.runEventPipeline(pluginEvent) })) as IngestResult diff --git a/plugin-server/src/main/ingestion-queues/metrics.ts b/plugin-server/src/main/ingestion-queues/metrics.ts index abeb3e56237d0..83b8ff61b952b 100644 --- a/plugin-server/src/main/ingestion-queues/metrics.ts +++ b/plugin-server/src/main/ingestion-queues/metrics.ts @@ -49,3 +49,9 @@ export const scheduledTaskCounter = new Counter({ help: 'Scheduled task status change', labelNames: ['status', 'task'], }) + +export const ingestionPartitionKeyOverflowed = new Counter({ + name: 'ingestion_partition_key_overflowed', + help: 'Indicates that a given key has overflowed capacity and been redirected to a different topic. Value incremented once a minute.', + labelNames: ['partition_key'], +}) diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 60fd198d63b96..d4d022d4ec453 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -127,7 +127,16 @@ export type CdpConfig = { CDP_EVENT_PROCESSOR_EXECUTE_FIRST_STEP: boolean } -export interface PluginsServerConfig extends CdpConfig { +export type IngestionConsumerConfig = { + // New config variables used by the new IngestionConsumer + INGESTION_CONSUMER_GROUP_ID: string + INGESTION_CONSUMER_CONSUME_TOPIC: string + INGESTION_CONSUMER_DLQ_TOPIC: string + /** If set then overflow routing is enabled and the topic is used for overflow events */ + INGESTION_CONSUMER_OVERFLOW_TOPIC?: string +} + +export interface PluginsServerConfig extends CdpConfig, IngestionConsumerConfig { TASKS_PER_WORKER: number // number of parallel tasks per worker thread INGESTION_CONCURRENCY: number // number of parallel event ingestion queues per batch INGESTION_BATCH_SIZE: number // kafka consumer batch size diff --git a/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts b/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts index 28d18b2cdd1c3..f4e7325e24c11 100644 --- a/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts +++ b/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts @@ -59,9 +59,9 @@ describe('workerTasks.runEventPipeline()', () => { now: new Date().toISOString(), uuid: new UUIDT().toString(), } - await expect( - new EventPipelineRunner(hub, event, new EventsProcessor(hub)).runEventPipeline(event) - ).rejects.toEqual(new DependencyUnavailableError(errorMessage, 'Postgres', new Error(errorMessage))) + await expect(new EventPipelineRunner(hub, event).runEventPipeline(event)).rejects.toEqual( + new DependencyUnavailableError(errorMessage, 'Postgres', new Error(errorMessage)) + ) pgQueryMock.mockRestore() }) }) diff --git a/plugin-server/tests/main/process-event.test.ts b/plugin-server/tests/main/process-event.test.ts index ff9fbcb9d9823..3f50d39d7960b 100644 --- a/plugin-server/tests/main/process-event.test.ts +++ b/plugin-server/tests/main/process-event.test.ts @@ -103,7 +103,7 @@ async function processEvent( ...data, } as any as PluginEvent - const runner = new EventPipelineRunner(hub, pluginEvent, new EventsProcessor(hub)) + const runner = new EventPipelineRunner(hub, pluginEvent) await runner.runEventPipeline(pluginEvent) await delayUntilEventIngested(() => hub.db.fetchEvents(), ++processEventCounter) @@ -163,7 +163,7 @@ const capture = async (hub: Hub, eventName: string, properties: any = {}) => { team_id: team.id, uuid: new UUIDT().toString(), } - const runner = new EventPipelineRunner(hub, event, new EventsProcessor(hub)) + const runner = new EventPipelineRunner(hub, event) await runner.runEventPipeline(event) await delayUntilEventIngested(() => hub.db.fetchEvents(), ++mockClientEventCounter) } @@ -1654,7 +1654,7 @@ describe('validates eventUuid', () => { properties: { price: 299.99, name: 'AirPods Pro' }, } - const runner = new EventPipelineRunner(hub, pluginEvent, new EventsProcessor(hub)) + const runner = new EventPipelineRunner(hub, pluginEvent) const result = await runner.runEventPipeline(pluginEvent) expect(result.error).toBeDefined() @@ -1673,7 +1673,7 @@ describe('validates eventUuid', () => { properties: { price: 299.99, name: 'AirPods Pro' }, } - const runner = new EventPipelineRunner(hub, pluginEvent, new EventsProcessor(hub)) + const runner = new EventPipelineRunner(hub, pluginEvent) const result = await runner.runEventPipeline(pluginEvent) expect(result.error).toBeDefined() diff --git a/plugin-server/tests/main/teardown.test.ts b/plugin-server/tests/main/teardown.test.ts index 89d1026a1e7e8..fc858d32c5a6d 100644 --- a/plugin-server/tests/main/teardown.test.ts +++ b/plugin-server/tests/main/teardown.test.ts @@ -37,7 +37,7 @@ async function getLogEntriesForPluginConfig(hub: Hub, pluginConfigId: number) { describe('teardown', () => { const processEvent = async (hub: Hub, event: PluginEvent) => { - const result = await new EventPipelineRunner(hub, event, new EventsProcessor(hub)).runEventPipeline(event) + const result = await new EventPipelineRunner(hub, event).runEventPipeline(event) const resultEvent = result.args[0] return resultEvent } diff --git a/plugin-server/tests/worker/dead-letter-queue.test.ts b/plugin-server/tests/worker/dead-letter-queue.test.ts index b9c79471fb42a..52979e7729e8b 100644 --- a/plugin-server/tests/worker/dead-letter-queue.test.ts +++ b/plugin-server/tests/worker/dead-letter-queue.test.ts @@ -60,9 +60,7 @@ describe('events dead letter queue', () => { test('events get sent to dead letter queue on error', async () => { const event = createEvent() - const ingestResponse1 = await new EventPipelineRunner(hub, event, new EventsProcessor(hub)).runEventPipeline( - event - ) + const ingestResponse1 = await new EventPipelineRunner(hub, event).runEventPipeline(event) expect(ingestResponse1).toEqual({ lastStep: 'prepareEventStep', error: 'database unavailable', diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts index 5c1ebcbb49394..1fd7ea56184d9 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts @@ -30,7 +30,7 @@ describe('Event Pipeline integration test', () => { let hookCannon: HookCommander const ingestEvent = async (event: PluginEvent) => { - const runner = new EventPipelineRunner(hub, event, new EventsProcessor(hub)) + const runner = new EventPipelineRunner(hub, event) const result = await runner.runEventPipeline(event) const postIngestionEvent = convertToPostIngestionEvent(result.args[0]) return Promise.all([ @@ -255,13 +255,13 @@ describe('Event Pipeline integration test', () => { uuid: new UUIDT().toString(), } - await new EventPipelineRunner(hub, event, new EventsProcessor(hub)).runEventPipeline(event) + await new EventPipelineRunner(hub, event).runEventPipeline(event) expect(hub.db.fetchPerson).toHaveBeenCalledTimes(1) // we query before creating expect(hub.db.createPerson).toHaveBeenCalledTimes(1) // second time single fetch - await new EventPipelineRunner(hub, event, new EventsProcessor(hub)).runEventPipeline(event) + await new EventPipelineRunner(hub, event).runEventPipeline(event) expect(hub.db.fetchPerson).toHaveBeenCalledTimes(2) }) }) From 38dfb3d6f33161d002538640bd47de9f155a138f Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 15:14:05 +0100 Subject: [PATCH 04/58] More checks --- .../src/ingestion/ingestion-consumer.ts | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 1a5d4a34dd14f..6a2f0d63b68df 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -232,6 +232,18 @@ export class EventsIngestionConsumer extends IngestionConsumer { } try { + const eventKey = `${event.token}:${event.distinct_id}` + // Check the rate limiter and emit to overflow if necessary + if (this.overflowEnabled() && !ConfiguredLimiter.consume(eventKey, 1, message.timestamp)) { + ingestionPartitionKeyOverflowed.labels(`${event.team_id ?? event.token}`).inc() + if (LoggingLimiter.consume(eventKey, 1)) { + status.warn('🪣', `Local overflow detection triggered on key ${eventKey}`) + } + + void this.scheduleWork(this.emitToOverflow([message])) + continue + } + const result = await retryIfRetriable(async () => { const runner = new EventPipelineRunner(this.hub, event) return await runner.runEventPipeline(event) @@ -360,14 +372,13 @@ export class EventsIngestionConsumer extends IngestionConsumer { return runInstrumentedFunction({ statsKey: `ingestionConsumer.handleEachBatch.parseKafkaMessages`, func: () => { - // 1. Parse the messages filtering out the ones that should be dropped - const batches: GroupedIncomingEvents = {} for (const message of messages) { let distinctId: string | undefined let token: string | undefined + // Parse the headers so we can early exit if found and should be dropped message.headers?.forEach((header) => { if (header.key === 'distinct_id') { distinctId = header.value.toString() @@ -382,6 +393,7 @@ export class EventsIngestionConsumer extends IngestionConsumer { continue } + // Parse the message payload into the event object const { data: dataStr, ...rawEvent } = JSON.parse(message.value!.toString()) const combinedEvent: PipelineEvent = { ...JSON.parse(dataStr), ...rawEvent } const event: PipelineEvent = normalizeEvent({ @@ -396,19 +408,6 @@ export class EventsIngestionConsumer extends IngestionConsumer { const eventKey = `${event.token}:${event.distinct_id}` - if (this.overflowEnabled() && !ConfiguredLimiter.consume(eventKey, 1, message.timestamp)) { - // Local overflow detection triggering, reroute to overflow topic too - ingestionPartitionKeyOverflowed.labels(`${event.team_id ?? event.token}`).inc() - if (LoggingLimiter.consume(eventKey, 1)) { - status.warn('🪣', `Local overflow detection triggered on key ${eventKey}`) - } - - void this.scheduleWork(this.emitToOverflow([message])) - continue - } - - // TODO: Add back in overflow detection logic - // We collect the events grouped by token and distinct_id so that we can process batches in parallel whilst keeping the order of events // for a given distinct_id if (!batches[eventKey]) { @@ -418,8 +417,6 @@ export class EventsIngestionConsumer extends IngestionConsumer { batches[eventKey].push({ message, event }) } - // 2. Overflow the ones that are supposed to be overflowed - return Promise.resolve(batches) }, }) From 9f94ca5605261e388d8fcddad5e661a9be304252 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 15:15:30 +0100 Subject: [PATCH 05/58] Fix --- plugin-server/src/main/pluginsServer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-server/src/main/pluginsServer.ts b/plugin-server/src/main/pluginsServer.ts index b9aa06a2ee50e..eeeb834c29028 100644 --- a/plugin-server/src/main/pluginsServer.ts +++ b/plugin-server/src/main/pluginsServer.ts @@ -19,6 +19,7 @@ import { CdpProcessedEventsConsumer, } from '../cdp/cdp-consumers' import { defaultConfig } from '../config/config' +import { EventsIngestionConsumer } from '../ingestion/ingestion-consumer' import { Hub, PluginServerCapabilities, PluginServerService, PluginsServerConfig } from '../types' import { closeHub, createHub, createKafkaClient, createKafkaProducerWrapper } from '../utils/db/hub' import { PostgresRouter } from '../utils/db/postgres' @@ -53,7 +54,6 @@ import { startScheduledTasksConsumer } from './ingestion-queues/scheduled-tasks- import { SessionRecordingIngester } from './ingestion-queues/session-recording/session-recordings-consumer' import { expressApp, setupCommonRoutes } from './services/http-server' import { getObjectStorage } from './services/object_storage' -import { EventsIngestionConsumer } from '../ingestion/ingestion-consumer' CompressionCodecs[CompressionTypes.Snappy] = SnappyCodec CompressionCodecs[CompressionTypes.LZ4] = new LZ4().codec @@ -282,7 +282,7 @@ export async function startPluginsServer( hub: hub, }) ) - + } if (capabilities.ingestionHistorical) { const hub = await setupHub() From b87a8e98fc55aa28119bdd594699708b55911f6a Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 15:16:50 +0100 Subject: [PATCH 06/58] Fixes --- plugin-server/src/ingestion/ingestion-consumer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 6a2f0d63b68df..54d600ec3f8ea 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -334,7 +334,7 @@ export class EventsIngestionConsumer extends IngestionConsumer { } private overflowEnabled() { - return !!this.hub.INGESTION_OVERFLOW_ENABLED + return !!this.hub.INGESTION_CONSUMER_OVERFLOW_TOPIC && this.hub.INGESTION_CONSUMER_OVERFLOW_TOPIC !== this.topic } private async emitToOverflow(kafkaMessages: Message[]) { From 410e36d5d06e99d99a4a0d81b1d243d26abbf672 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 15:38:33 +0100 Subject: [PATCH 07/58] Fixess --- plugin-server/src/capabilities.ts | 3 +- .../src/ingestion/ingestion-consumer.ts | 19 +-- plugin-server/src/main/pluginsServer.ts | 125 ++++++++++++------ plugin-server/src/types.ts | 1 + 4 files changed, 86 insertions(+), 62 deletions(-) diff --git a/plugin-server/src/capabilities.ts b/plugin-server/src/capabilities.ts index eea615421e876..23f18ea3accd2 100644 --- a/plugin-server/src/capabilities.ts +++ b/plugin-server/src/capabilities.ts @@ -11,8 +11,7 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin case null: return { mmdb: true, - ingestion: true, - ingestionV2: true, // TODO: remove + ingestionV2Combined: true, ingestionOverflow: true, ingestionHistorical: true, eventsIngestionPipelines: true, // with null PluginServerMode we run all of them diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 54d600ec3f8ea..bc63a817401dd 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -94,23 +94,6 @@ abstract class IngestionConsumer { return results } - // protected async produceQueuedMessages() { - // const messages = [...this.messagesToProduce] - // this.messagesToProduce = [] - // await Promise.all( - // messages.map((x) => - // this.kafkaProducer!.produce({ - // topic: x.topic, - // value: Buffer.from(safeClickhouseString(JSON.stringify(x.value))), - // key: x.key, - // waitForAck: true, - // }).catch((reason) => { - // status.error('⚠️', `failed to produce message: ${reason}`) - // }) - // ) - // ) - // } - protected async startKafkaConsumer(options: { topic: string groupId: string @@ -215,6 +198,8 @@ export class EventsIngestionConsumer extends IngestionConsumer { this.dlqTopic = hub.INGESTION_CONSUMER_DLQ_TOPIC this.tokensToDrop = hub.DROP_EVENTS_BY_TOKEN.split(',') this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',') + + this.name = `ingestion-consumer-${this.topic}` } public async processBatch(groupedIncomingEvents: GroupedIncomingEvents): Promise { diff --git a/plugin-server/src/main/pluginsServer.ts b/plugin-server/src/main/pluginsServer.ts index eeeb834c29028..5e7c0342b48d7 100644 --- a/plugin-server/src/main/pluginsServer.ts +++ b/plugin-server/src/main/pluginsServer.ts @@ -19,6 +19,11 @@ import { CdpProcessedEventsConsumer, } from '../cdp/cdp-consumers' import { defaultConfig } from '../config/config' +import { + KAFKA_EVENTS_PLUGIN_INGESTION, + KAFKA_EVENTS_PLUGIN_INGESTION_HISTORICAL, + KAFKA_EVENTS_PLUGIN_INGESTION_OVERFLOW, +} from '../config/kafka-topics' import { EventsIngestionConsumer } from '../ingestion/ingestion-consumer' import { Hub, PluginServerCapabilities, PluginServerService, PluginsServerConfig } from '../types' import { closeHub, createHub, createKafkaClient, createKafkaProducerWrapper } from '../utils/db/hub' @@ -267,65 +272,99 @@ export async function startPluginsServer( } } - if (capabilities.ingestionV2) { + if (capabilities.ingestionV2Combined) { + // NOTE: This is for single process deployments like local dev and hobby - it runs all possible consumers + // in a single process. In production these are each separate Deployments of the standard ingestion consumer const hub = await setupHub() - const consumer = new EventsIngestionConsumer(hub) - await consumer.start() - services.push(consumer.service) - } - if (capabilities.ingestion) { - const hub = await setupHub() - piscina = piscina ?? (await makePiscina(serverConfig, hub)) - services.push( - await startAnalyticsEventsIngestionConsumer({ - hub: hub, - }) - ) - } + const consumersOptions = [ + { + topic: KAFKA_EVENTS_PLUGIN_INGESTION, + group_id: `clickhouse-ingestion`, + }, + { + topic: KAFKA_EVENTS_PLUGIN_INGESTION_HISTORICAL, + group_id: `clickhouse-ingestion-historical`, + }, + { topic: KAFKA_EVENTS_PLUGIN_INGESTION_OVERFLOW, group_id: 'clickhouse-ingestion-overflow' }, + { topic: 'client_iwarnings_ingestion', group_id: 'client_iwarnings_ingestion' }, + { topic: 'heatmaps_ingestion', group_id: 'heatmaps_ingestion' }, + { topic: 'exceptions_ingestion', group_id: 'exceptions_ingestion' }, + ] + + for (const consumerOption of consumersOptions) { + const modifiedHub: Hub = { + ...hub, + INGESTION_CONSUMER_CONSUME_TOPIC: consumerOption.topic, + INGESTION_CONSUMER_GROUP_ID: consumerOption.group_id, + } + const consumer = new EventsIngestionConsumer(modifiedHub) + await consumer.start() + services.push(consumer.service) + } + } else { + if (capabilities.ingestionV2) { + const hub = await setupHub() + const consumer = new EventsIngestionConsumer(hub) + await consumer.start() + services.push(consumer.service) + } - if (capabilities.ingestionHistorical) { - const hub = await setupHub() - piscina = piscina ?? (await makePiscina(serverConfig, hub)) - services.push( - await startAnalyticsEventsIngestionHistoricalConsumer({ - hub: hub, - }) - ) - } + // Below are all legacy consumers that will be replaced by the new ingestion consumer that covers all cases - if (capabilities.eventsIngestionPipelines) { - const pipelinesToRun = - serverConfig.PLUGIN_SERVER_EVENTS_INGESTION_PIPELINE === null - ? Object.keys(PIPELINES) - : [serverConfig.PLUGIN_SERVER_EVENTS_INGESTION_PIPELINE] + if (capabilities.ingestion) { + const hub = await setupHub() + piscina = piscina ?? (await makePiscina(serverConfig, hub)) + services.push( + await startAnalyticsEventsIngestionConsumer({ + hub: hub, + }) + ) + } + + if (capabilities.ingestionHistorical) { + const hub = await setupHub() + piscina = piscina ?? (await makePiscina(serverConfig, hub)) + services.push( + await startAnalyticsEventsIngestionHistoricalConsumer({ + hub: hub, + }) + ) + } - for (const pipelineKey of pipelinesToRun) { - if (pipelineKey === null || !PIPELINES[pipelineKey]) { - throw new Error(`Invalid events ingestion pipeline: ${pipelineKey}`) + if (capabilities.eventsIngestionPipelines) { + const pipelinesToRun = + serverConfig.PLUGIN_SERVER_EVENTS_INGESTION_PIPELINE === null + ? Object.keys(PIPELINES) + : [serverConfig.PLUGIN_SERVER_EVENTS_INGESTION_PIPELINE] + + for (const pipelineKey of pipelinesToRun) { + if (pipelineKey === null || !PIPELINES[pipelineKey]) { + throw new Error(`Invalid events ingestion pipeline: ${pipelineKey}`) + } + + const hub = await setupHub() + piscina = piscina ?? (await makePiscina(serverConfig, hub)) + services.push( + await startEventsIngestionPipelineConsumer({ + hub: hub, + pipelineKey: pipelineKey, + }) + ) } + } + if (capabilities.ingestionOverflow) { const hub = await setupHub() piscina = piscina ?? (await makePiscina(serverConfig, hub)) services.push( - await startEventsIngestionPipelineConsumer({ + await startAnalyticsEventsIngestionOverflowConsumer({ hub: hub, - pipelineKey: pipelineKey, }) ) } } - if (capabilities.ingestionOverflow) { - const hub = await setupHub() - piscina = piscina ?? (await makePiscina(serverConfig, hub)) - services.push( - await startAnalyticsEventsIngestionOverflowConsumer({ - hub: hub, - }) - ) - } - if (capabilities.processAsyncOnEventHandlers) { const hub = await setupHub() piscina = piscina ?? (await makePiscina(serverConfig, hub)) diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index d4d022d4ec453..5c529ee9da98d 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -358,6 +358,7 @@ export interface PluginServerCapabilities { ingestionOverflow?: boolean ingestionHistorical?: boolean eventsIngestionPipelines?: boolean + ingestionV2Combined?: boolean ingestionV2?: boolean pluginScheduledTasks?: boolean processPluginJobs?: boolean From c128b812dc4025a41384d4cfdbddb2bb99d048d7 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sat, 18 Jan 2025 16:14:17 +0100 Subject: [PATCH 08/58] Fixes --- .../tests/main/ingestion-queues/run-ingestion-pipeline.test.ts | 1 - plugin-server/tests/main/teardown.test.ts | 1 - plugin-server/tests/worker/dead-letter-queue.test.ts | 1 - .../ingestion/event-pipeline/event-pipeline-integration.test.ts | 1 - 4 files changed, 4 deletions(-) diff --git a/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts b/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts index f4e7325e24c11..02675bf99dafc 100644 --- a/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts +++ b/plugin-server/tests/main/ingestion-queues/run-ingestion-pipeline.test.ts @@ -7,7 +7,6 @@ import { closeHub, createHub } from '../../../src/utils/db/hub' import { PostgresUse } from '../../../src/utils/db/postgres' import { UUIDT } from '../../../src/utils/utils' import { EventPipelineRunner } from '../../../src/worker/ingestion/event-pipeline/runner' -import { EventsProcessor } from '../../../src/worker/ingestion/process-event' import { createOrganization, createTeam, POSTGRES_DELETE_TABLES_QUERY } from '../../helpers/sql' describe('workerTasks.runEventPipeline()', () => { diff --git a/plugin-server/tests/main/teardown.test.ts b/plugin-server/tests/main/teardown.test.ts index fc858d32c5a6d..5a0fa7a6d9b0b 100644 --- a/plugin-server/tests/main/teardown.test.ts +++ b/plugin-server/tests/main/teardown.test.ts @@ -5,7 +5,6 @@ import { waitForExpect } from '../../functional_tests/expectations' import { startPluginsServer } from '../../src/main/pluginsServer' import { Hub, LogLevel, PluginLogEntry, PluginLogEntrySource, PluginLogEntryType } from '../../src/types' import { EventPipelineRunner } from '../../src/worker/ingestion/event-pipeline/runner' -import { EventsProcessor } from '../../src/worker/ingestion/process-event' import { makePiscina } from '../../src/worker/piscina' import { pluginConfig39 } from '../helpers/plugins' import { resetTestDatabase } from '../helpers/sql' diff --git a/plugin-server/tests/worker/dead-letter-queue.test.ts b/plugin-server/tests/worker/dead-letter-queue.test.ts index 52979e7729e8b..82b7e546c66fa 100644 --- a/plugin-server/tests/worker/dead-letter-queue.test.ts +++ b/plugin-server/tests/worker/dead-letter-queue.test.ts @@ -4,7 +4,6 @@ import { Hub, LogLevel } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' import { UUIDT } from '../../src/utils/utils' import { EventPipelineRunner } from '../../src/worker/ingestion/event-pipeline/runner' -import { EventsProcessor } from '../../src/worker/ingestion/process-event' import { generateEventDeadLetterQueueMessage } from '../../src/worker/ingestion/utils' import { delayUntilEventIngested, resetTestDatabaseClickhouse } from '../helpers/clickhouse' import { resetTestDatabase } from '../helpers/sql' diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts index 1fd7ea56184d9..e42713e3dda76 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/event-pipeline-integration.test.ts @@ -15,7 +15,6 @@ import { } from '../../../../src/worker/ingestion/event-pipeline/runAsyncHandlersStep' import { EventPipelineRunner } from '../../../../src/worker/ingestion/event-pipeline/runner' import { HookCommander } from '../../../../src/worker/ingestion/hooks' -import { EventsProcessor } from '../../../../src/worker/ingestion/process-event' import { setupPlugins } from '../../../../src/worker/plugins/setup' import { delayUntilEventIngested, resetTestDatabaseClickhouse } from '../../../helpers/clickhouse' import { commonUserId } from '../../../helpers/plugins' From 17621a9341efd48afe0211ee2738bd8b7c235253 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 10:55:37 +0100 Subject: [PATCH 09/58] Refactor producer --- plugin-server/functional_tests/api.ts | 1 - .../functional_tests/jobs-consumer.test.ts | 6 +- plugin-server/functional_tests/kafka.ts | 17 +- .../scheduled-tasks-runner.test.ts | 8 +- .../session-recordings.test.ts | 3 - plugin-server/src/cdp/cdp-consumers.ts | 33 +- plugin-server/src/kafka/config.ts | 35 +- plugin-server/src/kafka/producer.ts | 337 +++++++++++------- .../src/main/graphile-worker/schedule.ts | 9 +- .../batch-processing/each-batch-ingestion.ts | 3 +- .../main/ingestion-queues/jobs-consumer.ts | 20 +- .../src/main/ingestion-queues/kafka-queue.ts | 3 +- .../scheduled-tasks-consumer.ts | 29 +- .../services/console-logs-ingester.ts | 27 +- .../services/replay-events-ingester.ts | 26 +- .../session-recordings-consumer.ts | 22 +- .../session-recording/utils.ts | 2 +- plugin-server/src/main/pluginsServer.ts | 7 +- plugin-server/src/types.ts | 14 +- plugin-server/src/utils/db/db.ts | 81 +++-- plugin-server/src/utils/db/error.ts | 2 +- plugin-server/src/utils/db/hub.ts | 63 ++-- .../src/utils/db/kafka-producer-wrapper.ts | 161 --------- plugin-server/src/utils/db/utils.ts | 4 +- .../src/worker/ingestion/app-metrics.ts | 13 +- .../event-pipeline/extractHeatmapDataStep.ts | 14 +- .../src/worker/ingestion/person-state.ts | 12 +- .../src/worker/ingestion/process-event.ts | 7 +- plugin-server/src/worker/ingestion/utils.ts | 29 +- .../src/worker/vm/extensions/posthog.ts | 37 +- plugin-server/tests/cdp/cdp-api.test.ts | 15 +- .../tests/cdp/cdp-events-consumer.test.ts | 50 +-- .../cdp/cdp-internal-events-consumer.test.ts | 7 +- .../tests/cdp/helpers/kafka-observer.ts | 4 +- .../tests/helpers/mocks/producer.mock.ts | 47 +++ plugin-server/tests/main/db.test.ts | 23 +- ...nalytics-events-ingestion-consumer.test.ts | 2 - ...events-ingestion-overflow-consumer.test.ts | 30 +- .../main/ingestion-queues/each-batch.test.ts | 2 +- .../services/console-log-ingester.test.ts | 112 +++--- .../services/overflow-manager.test.ts | 3 +- .../services/replay-events-ingester.test.ts | 57 ++- .../session-recording/utils.test.ts | 42 +-- .../tests/main/jobs/schedule.test.ts | 229 ++++++------ .../tests/main/process-event.test.ts | 5 +- .../utils/kafka-producer-wrapper.test.ts | 27 -- plugin-server/tests/worker/console.test.ts | 39 +- .../__snapshots__/app-metrics.test.ts.snap | 21 +- .../worker/ingestion/app-metrics.test.ts | 13 +- .../worker/ingestion/person-state.test.ts | 8 +- .../worker/ingestion/postgres-parity.test.ts | 16 +- plugin-server/tests/worker/vm.test.ts | 77 ++-- 52 files changed, 831 insertions(+), 1023 deletions(-) delete mode 100644 plugin-server/src/utils/db/kafka-producer-wrapper.ts create mode 100644 plugin-server/tests/helpers/mocks/producer.mock.ts delete mode 100644 plugin-server/tests/utils/kafka-producer-wrapper.test.ts diff --git a/plugin-server/functional_tests/api.ts b/plugin-server/functional_tests/api.ts index 4df5eff0701e7..dde721e51d9bd 100644 --- a/plugin-server/functional_tests/api.ts +++ b/plugin-server/functional_tests/api.ts @@ -107,7 +107,6 @@ export const capture = async ({ }) ), key: teamId ? teamId.toString() : '', - waitForAck: true, }) } diff --git a/plugin-server/functional_tests/jobs-consumer.test.ts b/plugin-server/functional_tests/jobs-consumer.test.ts index 353bd3518397e..30e2abd9af282 100644 --- a/plugin-server/functional_tests/jobs-consumer.test.ts +++ b/plugin-server/functional_tests/jobs-consumer.test.ts @@ -43,7 +43,7 @@ describe('dlq handling', () => { test.concurrent(`handles empty messages`, async () => { const key = uuidv4() - await produce({ topic: 'jobs', message: null, key, waitForAck: true }) + await produce({ topic: 'jobs', message: null, key }) await waitForExpect(() => { const messages = dlq.filter((message) => message.key?.toString() === key) @@ -54,7 +54,7 @@ describe('dlq handling', () => { test.concurrent(`handles invalid JSON`, async () => { const key = uuidv4() - await produce({ topic: 'jobs', message: Buffer.from('invalid json'), key, waitForAck: true }) + await produce({ topic: 'jobs', message: Buffer.from('invalid json'), key }) await waitForExpect(() => { const messages = dlq.filter((message) => message.key?.toString() === key) @@ -72,7 +72,7 @@ describe('dlq handling', () => { labels: { topic: 'jobs', partition: '0', groupId: 'jobs-inserter' }, }) - await produce({ topic: 'jobs', message: Buffer.from(''), key: '', waitForAck: true }) + await produce({ topic: 'jobs', message: Buffer.from(''), key: '' }) await waitForExpect(async () => { const metricAfter = await getMetric({ diff --git a/plugin-server/functional_tests/kafka.ts b/plugin-server/functional_tests/kafka.ts index f431488b290ac..b8a9711107dcd 100644 --- a/plugin-server/functional_tests/kafka.ts +++ b/plugin-server/functional_tests/kafka.ts @@ -3,7 +3,7 @@ import SnappyCodec from 'kafkajs-snappy' import { HighLevelProducer } from 'node-rdkafka' import { defaultConfig } from '../src/config/config' -import { produce as defaultProduce } from '../src/kafka/producer' +import { KafkaProducerWrapper } from '../src/kafka/producer' CompressionCodecs[CompressionTypes.Snappy] = SnappyCodec @@ -36,17 +36,8 @@ export async function createKafkaProducer() { return producer } -export async function produce({ - topic, - message, - key, - waitForAck, -}: { - topic: string - message: Buffer | null - key: string - waitForAck: boolean -}) { +export async function produce({ topic, message, key }: { topic: string; message: Buffer | null; key: string }) { producer = producer ?? (await createKafkaProducer()) - await defaultProduce({ producer, topic, value: message, key: Buffer.from(key), waitForAck }) + + await new KafkaProducerWrapper(producer).produce({ topic, value: message, key: Buffer.from(key) }) } diff --git a/plugin-server/functional_tests/scheduled-tasks-runner.test.ts b/plugin-server/functional_tests/scheduled-tasks-runner.test.ts index 48764ae7f90a7..3e3345245a644 100644 --- a/plugin-server/functional_tests/scheduled-tasks-runner.test.ts +++ b/plugin-server/functional_tests/scheduled-tasks-runner.test.ts @@ -43,7 +43,7 @@ describe('dlq handling', () => { test.concurrent(`handles empty messages`, async () => { const key = uuidv4() - await produce({ topic: 'scheduled_tasks', message: null, key, waitForAck: true }) + await produce({ topic: 'scheduled_tasks', message: null, key }) await waitForExpect(() => { const messages = dlq.filter((message) => message.key?.toString() === key) @@ -54,7 +54,7 @@ describe('dlq handling', () => { test.concurrent(`handles invalid JSON`, async () => { const key = uuidv4() - await produce({ topic: 'scheduled_tasks', message: Buffer.from('invalid json'), key, waitForAck: true }) + await produce({ topic: 'scheduled_tasks', message: Buffer.from('invalid json'), key }) await waitForExpect(() => { const messages = dlq.filter((message) => message.key?.toString() === key) @@ -69,7 +69,6 @@ describe('dlq handling', () => { topic: 'scheduled_tasks', message: Buffer.from(JSON.stringify({ taskType: 'invalidTaskType', pluginConfigId: 1 })), key, - waitForAck: true, }) await waitForExpect(() => { @@ -85,7 +84,6 @@ describe('dlq handling', () => { topic: 'scheduled_tasks', message: Buffer.from(JSON.stringify({ taskType: 'runEveryMinute', pluginConfigId: 'asdf' })), key, - waitForAck: true, }) await waitForExpect(() => { @@ -106,7 +104,7 @@ describe('dlq handling', () => { // NOTE: we don't actually care too much about the contents of the // message, just that it triggeres the consumer to try to process it. - await produce({ topic: 'scheduled_tasks', message: Buffer.from(''), key: '', waitForAck: true }) + await produce({ topic: 'scheduled_tasks', message: Buffer.from(''), key: '' }) await waitForExpect(async () => { const metricAfter = await getMetric({ diff --git a/plugin-server/functional_tests/session-recordings.test.ts b/plugin-server/functional_tests/session-recordings.test.ts index 783fbdbeb43cd..ec1377e792734 100644 --- a/plugin-server/functional_tests/session-recordings.test.ts +++ b/plugin-server/functional_tests/session-recordings.test.ts @@ -177,7 +177,6 @@ test.skip('consumer updates timestamp exported to prometheus', async () => { topic: KAFKA_SESSION_RECORDING_SNAPSHOT_ITEM_EVENTS, message: Buffer.from(''), key: '', - waitForAck: true, }) await waitForExpect(async () => { @@ -250,7 +249,6 @@ test.skip(`handles message with no token or with token and no associated team_id topic: KAFKA_SESSION_RECORDING_SNAPSHOT_ITEM_EVENTS, message: Buffer.from(JSON.stringify({ uuid: noTokenUuid, data: JSON.stringify({}) })), key: noTokenKey, - waitForAck: true, }) await produce({ topic: KAFKA_SESSION_RECORDING_SNAPSHOT_ITEM_EVENTS, @@ -258,7 +256,6 @@ test.skip(`handles message with no token or with token and no associated team_id JSON.stringify({ uuid: noAssociatedTeamUuid, token: 'no associated team', data: JSON.stringify({}) }) ), key: noAssociatedTeamKey, - waitForAck: true, }) await capture(makeSessionMessage(teamId, 'should be ingested')) diff --git a/plugin-server/src/cdp/cdp-consumers.ts b/plugin-server/src/cdp/cdp-consumers.ts index 8caeef4c329ab..15b849adc9a7f 100644 --- a/plugin-server/src/cdp/cdp-consumers.ts +++ b/plugin-server/src/cdp/cdp-consumers.ts @@ -14,6 +14,7 @@ import { } from '../config/kafka-topics' import { BatchConsumer, startBatchConsumer } from '../kafka/batch-consumer' import { createRdConnectionConfigFromEnvVars } from '../kafka/config' +import { KafkaProducerWrapper } from '../kafka/producer' import { addSentryBreadcrumbsEventListeners } from '../main/ingestion-queues/kafka-metrics' import { runInstrumentedFunction } from '../main/utils' import { @@ -25,8 +26,6 @@ import { TimestampFormat, ValueMatcher, } from '../types' -import { createKafkaProducerWrapper } from '../utils/db/hub' -import { KafkaProducerWrapper } from '../utils/db/kafka-producer-wrapper' import { safeClickhouseString } from '../utils/db/utils' import { status } from '../utils/status' import { castTimestampOrNow, UUIDT } from '../utils/utils' @@ -168,18 +167,20 @@ abstract class CdpConsumerBase { protected async produceQueuedMessages() { const messages = [...this.messagesToProduce] this.messagesToProduce = [] - await Promise.all( - messages.map((x) => - this.kafkaProducer!.produce({ - topic: x.topic, - value: Buffer.from(safeClickhouseString(JSON.stringify(x.value))), - key: x.key, - waitForAck: true, - }).catch((reason) => { - status.error('⚠️', `failed to produce message: ${reason}`) - }) - ) - ) + + await this.kafkaProducer!.queueMessages( + messages.map((x) => ({ + topic: x.topic, + messages: [ + { + value: safeClickhouseString(JSON.stringify(x.value)), + key: x.key, + }, + ], + })) + ).catch((reason) => { + status.error('⚠️', `failed to produce message: ${reason}`) + }) } protected produceAppMetric(metric: HogFunctionAppMetric) { @@ -329,7 +330,7 @@ abstract class CdpConsumerBase { }): Promise { this.batchConsumer = await startBatchConsumer({ ...options, - connectionConfig: createRdConnectionConfigFromEnvVars(this.hub), + connectionConfig: createRdConnectionConfigFromEnvVars(this.hub, 'consumer'), autoCommit: true, sessionTimeout: this.hub.KAFKA_CONSUMPTION_SESSION_TIMEOUT_MS, maxPollIntervalMs: this.hub.KAFKA_CONSUMPTION_MAX_POLL_INTERVAL_MS, @@ -384,7 +385,7 @@ abstract class CdpConsumerBase { // NOTE: This is only for starting shared services await Promise.all([ this.hogFunctionManager.start(this.hogTypes), - createKafkaProducerWrapper(this.hub).then((producer) => { + KafkaProducerWrapper.create(this.hub).then((producer) => { this.kafkaProducer = producer this.kafkaProducer.producer.connect() }), diff --git a/plugin-server/src/kafka/config.ts b/plugin-server/src/kafka/config.ts index 7ee2736dab67d..02db84a6f0c36 100644 --- a/plugin-server/src/kafka/config.ts +++ b/plugin-server/src/kafka/config.ts @@ -2,7 +2,6 @@ import { GlobalConfig } from 'node-rdkafka' import { hostname } from 'os' import { KafkaConfig } from '../utils/db/hub' -import { KafkaProducerConfig } from './producer' export const RDKAFKA_LOG_LEVEL_MAPPING = { NOTHING: 0, @@ -12,15 +11,31 @@ export const RDKAFKA_LOG_LEVEL_MAPPING = { ERROR: 3, } -export const createRdConnectionConfigFromEnvVars = (kafkaConfig: KafkaConfig): GlobalConfig => { +export const createRdConnectionConfigFromEnvVars = ( + kafkaConfig: KafkaConfig, + target: 'producer' | 'consumer' +): GlobalConfig => { + const kafkaHosts = + target === 'producer' ? kafkaConfig.KAFKA_PRODUCER_HOSTS ?? kafkaConfig.KAFKA_HOSTS : kafkaConfig.KAFKA_HOSTS + + const kafkaSecurityProtocol = + target === 'producer' + ? kafkaConfig.KAFKA_PRODUCER_SECURITY_PROTOCOL ?? kafkaConfig.KAFKA_SECURITY_PROTOCOL + : kafkaConfig.KAFKA_SECURITY_PROTOCOL + + const kafkaClientId = + target === 'producer' + ? kafkaConfig.KAFKA_PRODUCER_CLIENT_ID ?? kafkaConfig.KAFKA_CLIENT_ID + : kafkaConfig.KAFKA_CLIENT_ID + // We get the config from the environment variables. This method should // convert those vars into connection settings that node-rdkafka can use. We // also set the client.id to the hostname of the machine. This is useful for debugging. const config: GlobalConfig = { - 'client.id': kafkaConfig.KAFKA_CLIENT_ID || hostname(), - 'metadata.broker.list': kafkaConfig.KAFKA_HOSTS, - 'security.protocol': kafkaConfig.KAFKA_SECURITY_PROTOCOL - ? (kafkaConfig.KAFKA_SECURITY_PROTOCOL.toLowerCase() as GlobalConfig['security.protocol']) + 'client.id': kafkaClientId || hostname(), + 'metadata.broker.list': kafkaHosts, + 'security.protocol': kafkaSecurityProtocol + ? (kafkaSecurityProtocol.toLowerCase() as GlobalConfig['security.protocol']) : 'plaintext', 'sasl.mechanisms': kafkaConfig.KAFKA_SASL_MECHANISM, 'sasl.username': kafkaConfig.KAFKA_SASL_USER, @@ -44,11 +59,3 @@ export const createRdConnectionConfigFromEnvVars = (kafkaConfig: KafkaConfig): G return config } - -export const createRdProducerConfigFromEnvVars = (producerConfig: KafkaProducerConfig): KafkaProducerConfig => { - return { - KAFKA_PRODUCER_LINGER_MS: producerConfig.KAFKA_PRODUCER_LINGER_MS, - KAFKA_PRODUCER_BATCH_SIZE: producerConfig.KAFKA_PRODUCER_BATCH_SIZE, - KAFKA_PRODUCER_QUEUE_BUFFERING_MAX_MESSAGES: producerConfig.KAFKA_PRODUCER_QUEUE_BUFFERING_MAX_MESSAGES, - } -} diff --git a/plugin-server/src/kafka/producer.ts b/plugin-server/src/kafka/producer.ts index 71c21e8cb9652..7b07742f47299 100644 --- a/plugin-server/src/kafka/producer.ts +++ b/plugin-server/src/kafka/producer.ts @@ -1,162 +1,225 @@ import { ClientMetrics, - HighLevelProducer as RdKafkaProducer, + HighLevelProducer, + LibrdKafkaError, MessageHeader, MessageKey as RdKafkaMessageKey, MessageValue, NumberNullUndefined, - ProducerGlobalConfig, } from 'node-rdkafka' -import { Summary } from 'prom-client' +import { Counter, Summary } from 'prom-client' import { getSpan } from '../sentry' +import { PluginsServerConfig } from '../types' +import { DependencyUnavailableError, MessageSizeTooLarge } from '../utils/db/error' import { status } from '../utils/status' +import { createRdConnectionConfigFromEnvVars } from './config' -export type KafkaProducerConfig = { - KAFKA_PRODUCER_LINGER_MS: number - KAFKA_PRODUCER_BATCH_SIZE: number - KAFKA_PRODUCER_QUEUE_BUFFERING_MAX_MESSAGES: number -} +// TODO: Rewrite this description +/** This class is a wrapper around the rdkafka producer, and does very little. + * It used to be a wrapper around KafkaJS, but we switched to rdkafka because of + * increased performance. + * + * The big difference between this and the original is that we return a promise from + * queueMessage, which will only resolve once we get an ack that the message has + * been persisted to Kafka. So we should get stronger guarantees on processing. + * + * TODO: refactor Kafka producer usage to use rdkafka directly. + */ -// Disallow use of ``undefined`` with ``HighLevelProducer`` since it will result -// in messages that are never produced, and the corresponding callback is never -// called, causing the promise returned to never settle. export type MessageKey = Exclude -export const ingestEventKafkaProduceLatency = new Summary({ - name: 'ingest_event_kafka_produce_latency', - help: 'Wait time for individual Kafka produces', - labelNames: ['topic', 'waitForAck'], - percentiles: [0.5, 0.9, 0.95, 0.99], -}) +export type TopicMessage = { + topic: string + messages: { + value: string | Buffer | null + key?: MessageKey + }[] +} -// Kafka production related functions using node-rdkafka. -export const createKafkaProducer = async (globalConfig: ProducerGlobalConfig, producerConfig: KafkaProducerConfig) => { - const producer = new RdKafkaProducer({ - // milliseconds to wait after the most recently added message before sending a batch. The - // default is 0, which means that messages are sent as soon as possible. This does not mean - // that there will only be one message per batch, as the producer will attempt to fill - // batches up to the batch size while the number of Kafka inflight requests is saturated, by - // default 5 inflight requests. - 'linger.ms': producerConfig.KAFKA_PRODUCER_LINGER_MS, - 'batch.size': producerConfig.KAFKA_PRODUCER_BATCH_SIZE, - 'queue.buffering.max.messages': producerConfig.KAFKA_PRODUCER_QUEUE_BUFFERING_MAX_MESSAGES, - 'compression.codec': 'snappy', - // Ensure that librdkafka handled producer retries do not produce duplicates. Note this - // doesn't mean that if we manually retry a message that it will be idempotent. May reduce - // throughput. Note that at the time of writing the session recording events table in - // ClickHouse uses a `ReplicatedReplacingMergeTree` with a ver param of _timestamp i.e. when - // the event was added to the Kafka ingest topic. The sort key is `team_id, - // toHour(timestamp), session_id, timestamp, uuid` which means duplicate production of the - // same event _should_ be deduplicated when merges occur on the table. This isn't a - // guarantee on removing duplicates though and rather still requires deduplication either - // when querying the table or client side. - 'enable.idempotence': true, - dr_cb: true, - ...globalConfig, - }) - - producer.on('event.log', function (log) { - status.info('📝', 'librdkafka log', { log: log }) - }) - - producer.on('event.error', function (err) { - status.error('📝', 'librdkafka error', { log: err }) - }) - - await new Promise((resolve, reject) => - producer.connect(undefined, (error, data) => { - if (error) { - status.error('⚠️', 'connect_error', { error: error }) - reject(error) - } else { - status.info('📝', 'librdkafka producer connected', { error, brokers: data?.brokers }) - resolve(data) - } +export class KafkaProducerWrapper { + /** Kafka producer used for syncing Postgres and ClickHouse person data. */ + public producer: HighLevelProducer + + static async create(config: PluginsServerConfig) { + const globalConfig = createRdConnectionConfigFromEnvVars(config, 'producer') + const producer = new HighLevelProducer({ + ...globalConfig, + // milliseconds to wait after the most recently added message before sending a batch. The + // default is 0, which means that messages are sent as soon as possible. This does not mean + // that there will only be one message per batch, as the producer will attempt to fill + // batches up to the batch size while the number of Kafka inflight requests is saturated, by + // default 5 inflight requests. + 'linger.ms': config.KAFKA_PRODUCER_LINGER_MS, + 'batch.size': config.KAFKA_PRODUCER_BATCH_SIZE, + 'queue.buffering.max.messages': config.KAFKA_PRODUCER_QUEUE_BUFFERING_MAX_MESSAGES, + 'compression.codec': 'snappy', + // Ensure that librdkafka handled producer retries do not produce duplicates. Note this + // doesn't mean that if we manually retry a message that it will be idempotent. May reduce + // throughput. Note that at the time of writing the session recording events table in + // ClickHouse uses a `ReplicatedReplacingMergeTree` with a ver param of _timestamp i.e. when + // the event was added to the Kafka ingest topic. The sort key is `team_id, + // toHour(timestamp), session_id, timestamp, uuid` which means duplicate production of the + // same event _should_ be deduplicated when merges occur on the table. This isn't a + // guarantee on removing duplicates though and rather still requires deduplication either + // when querying the table or client side. + 'enable.idempotence': true, + dr_cb: true, }) - ) - return producer -} -export const produce = async ({ - producer, - topic, - value, - key, - headers = [], - waitForAck, -}: { - producer: RdKafkaProducer - topic: string - value: MessageValue - key: MessageKey - headers?: MessageHeader[] - waitForAck: boolean -}): Promise => { - status.debug('📤', 'Producing message', { topic: topic }) - const produceSpan = getSpan()?.startChild({ op: 'kafka_produce' }) - return await new Promise((resolve, reject) => { - const produceTimer = ingestEventKafkaProduceLatency - .labels({ topic, waitForAck: waitForAck.toString() }) - .startTimer() - - if (waitForAck) { - producer.produce( - topic, - null, - value, - key, - Date.now(), - headers, - (error: any, offset: NumberNullUndefined) => { - if (error) { - status.error('⚠️', 'produce_error', { error: error, topic: topic }) - reject(error) - } else { - status.debug('📤', 'Produced message', { topic: topic, offset: offset }) - resolve(offset) - } + producer.on('event.log', function (log) { + status.info('📝', 'librdkafka log', { log: log }) + }) - produceTimer() - produceSpan?.finish() - } - ) - } else { - producer.produce(topic, null, value, key, Date.now(), headers, (error: any, _: NumberNullUndefined) => { + producer.on('event.error', function (err) { + status.error('📝', 'librdkafka error', { log: err }) + }) + + await new Promise((resolve, reject) => + producer.connect(undefined, (error, data) => { if (error) { - status.error('⚠️', 'produce_error', { error: error, topic: topic }) + status.error('⚠️', 'connect_error', { error: error }) + reject(error) + } else { + status.info('📝', 'librdkafka producer connected', { error, brokers: data?.brokers }) + resolve(data) } + }) + ) + + return new KafkaProducerWrapper(producer) + } - produceSpan?.finish() + constructor(producer: HighLevelProducer) { + this.producer = producer + } + + async produce({ + value, + key, + topic, + headers, + }: { + value: MessageValue + key: MessageKey + topic: string + headers?: MessageHeader[] + }): Promise { + try { + const produceTimer = ingestEventKafkaProduceLatency.labels({ topic }).startTimer() + const produceSpan = getSpan()?.startChild({ op: 'kafka_produce' }) + kafkaProducerMessagesQueuedCounter.labels({ topic_name: topic }).inc() + status.debug('📤', 'Producing message', { topic: topic }) + + const result = await new Promise((resolve, reject) => { + this.producer.produce( + topic, + null, + value, + key, + Date.now(), + headers ?? [], + (error: any, offset: NumberNullUndefined) => { + return error ? reject(error) : resolve(offset) + } + ) }) - resolve(undefined) + + produceSpan?.finish() + kafkaProducerMessagesWrittenCounter.labels({ topic_name: topic }).inc() + status.debug('📤', 'Produced message', { topic: topic, offset: result }) produceTimer() - } - }) -} -export const disconnectProducer = async (producer: RdKafkaProducer) => { - status.info('🔌', 'Disconnecting producer') - return await new Promise((resolve, reject) => - producer.disconnect((error: any, data: ClientMetrics) => { - status.info('🔌', 'Disconnected producer') - if (error) { - reject(error) - } else { - resolve(data) - } - }) - ) -} -export const flushProducer = async (producer: RdKafkaProducer) => { - status.debug('📤', 'flushing_producer') - return await new Promise((resolve, reject) => - producer.flush(10000, (error) => { - status.debug('📤', 'flushed_producer') - if (error) { - reject(error) - } else { - resolve(null) + } catch (error) { + kafkaProducerMessagesFailedCounter.labels({ topic_name: topic }).inc() + status.error('⚠️', 'kafka_produce_error', { error: error, topic: topic }) + + if ((error as LibrdKafkaError).isRetriable) { + // If we get a retriable error, bubble that up so that the + // caller can retry. + throw new DependencyUnavailableError(error.message, 'Kafka', error) + } else if ((error as LibrdKafkaError).code === 10) { + throw new MessageSizeTooLarge(error.message, error) } - }) - ) + + throw error + } + } + + /** + * Currently this produces messages in parallel. + * If ordering is required then you should use the `produce` method instead in an awaited loop. + */ + async queueMessages(topicMessages: TopicMessage | TopicMessage[]): Promise { + topicMessages = Array.isArray(topicMessages) ? topicMessages : [topicMessages] + + await Promise.all( + topicMessages.map((record) => { + return Promise.all( + record.messages.map((message) => + this.produce({ + topic: record.topic, + key: message.key ? Buffer.from(message.key) : null, + value: message.value ? Buffer.from(message.value) : null, + }) + ) + ) + }) + ) + } + + public async flush() { + status.debug('📤', 'flushing_producer') + + return await new Promise((resolve, reject) => + this.producer.flush(10000, (error) => { + status.debug('📤', 'flushed_producer') + if (error) { + reject(error) + } else { + resolve(null) + } + }) + ) + } + + public async disconnect(): Promise { + await this.flush() + + status.info('🔌', 'Disconnecting producer') + await new Promise((resolve, reject) => + this.producer.disconnect((error: any, data: ClientMetrics) => { + status.info('🔌', 'Disconnected producer') + if (error) { + reject(error) + } else { + resolve(data) + } + }) + ) + } } + +export const kafkaProducerMessagesQueuedCounter = new Counter({ + name: 'kafka_producer_messages_queued_total', + help: 'Count of messages queued to the Kafka producer, by destination topic.', + labelNames: ['topic_name'], +}) + +export const kafkaProducerMessagesWrittenCounter = new Counter({ + name: 'kafka_producer_messages_written_total', + help: 'Count of messages written to Kafka, by destination topic.', + labelNames: ['topic_name'], +}) + +export const kafkaProducerMessagesFailedCounter = new Counter({ + name: 'kafka_producer_messages_failed_total', + help: 'Count of write failures by the Kafka producer, by destination topic.', + labelNames: ['topic_name'], +}) + +export const ingestEventKafkaProduceLatency = new Summary({ + name: 'ingest_event_kafka_produce_latency', + help: 'Wait time for individual Kafka produces', + labelNames: ['topic'], + percentiles: [0.5, 0.9, 0.95, 0.99], +}) diff --git a/plugin-server/src/main/graphile-worker/schedule.ts b/plugin-server/src/main/graphile-worker/schedule.ts index 16435d02c0466..fa1ba04684366 100644 --- a/plugin-server/src/main/graphile-worker/schedule.ts +++ b/plugin-server/src/main/graphile-worker/schedule.ts @@ -55,12 +55,9 @@ export async function runScheduledTasks( if (server.USE_KAFKA_FOR_SCHEDULED_TASKS) { for (const pluginConfigId of server.pluginSchedule?.[taskType] || []) { status.info('⏲️', 'queueing_schedule_task', { taskType, pluginConfigId }) - await server.kafkaProducer.queueMessage({ - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [{ key: pluginConfigId.toString(), value: JSON.stringify({ taskType, pluginConfigId }) }], - }, - waitForAck: true, + await server.kafkaProducer.queueMessages({ + topic: KAFKA_SCHEDULED_TASKS, + messages: [{ key: pluginConfigId.toString(), value: JSON.stringify({ taskType, pluginConfigId }) }], }) graphileScheduledTaskCounter.labels({ status: 'queued', task: taskType }).inc() } diff --git a/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts b/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts index 2757853e02ebc..15e33b9accbc8 100644 --- a/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts +++ b/plugin-server/src/main/ingestion-queues/batch-processing/each-batch-ingestion.ts @@ -80,7 +80,6 @@ async function handleProcessingError( value: message.value, key: message.key ?? null, // avoid undefined, just to be safe headers: headers, - waitForAck: true, }) } catch (error) { // If we can't send to the DLQ and it's not retriable, just continue. We'll commit the @@ -271,6 +270,7 @@ export function computeKey(pluginEvent: PipelineEvent): string { async function emitToOverflow(queue: IngestionConsumer, kafkaMessages: Message[], overflowMode: IngestionOverflowMode) { ingestionOverflowingMessagesTotal.inc(kafkaMessages.length) const useRandomPartitioning = overflowMode === IngestionOverflowMode.RerouteRandomly + await Promise.all( kafkaMessages.map((message) => queue.pluginsServer.kafkaProducer.produce({ @@ -281,7 +281,6 @@ async function emitToOverflow(queue: IngestionConsumer, kafkaMessages: Message[] // instead as that behavior is safer. key: useRandomPartitioning ? null : message.key ?? null, headers: message.headers, - waitForAck: true, }) ) ) diff --git a/plugin-server/src/main/ingestion-queues/jobs-consumer.ts b/plugin-server/src/main/ingestion-queues/jobs-consumer.ts index 1ed19c2fc6fce..f21b324604901 100644 --- a/plugin-server/src/main/ingestion-queues/jobs-consumer.ts +++ b/plugin-server/src/main/ingestion-queues/jobs-consumer.ts @@ -1,8 +1,8 @@ import { EachBatchHandler, Kafka } from 'kafkajs' import { Counter } from 'prom-client' -import { KafkaProducerWrapper } from 'utils/db/kafka-producer-wrapper' import { KAFKA_JOBS, KAFKA_JOBS_DLQ } from '../../config/kafka-topics' +import { KafkaProducerWrapper } from '../../kafka/producer' import { EnqueuedPluginJob, JobName, PluginsServerConfig } from '../../types' import { status } from '../../utils/status' import { GraphileWorker } from '../graphile-worker/graphile-worker' @@ -54,12 +54,9 @@ export const startJobsConsumer = async ({ value: message.value, }) // TODO: handle resolving offsets asynchronously - await producer.queueMessage({ - kafkaMessage: { - topic: KAFKA_JOBS_DLQ, - messages: [{ value: message.value, key: message.key }], - }, - waitForAck: true, + await producer.queueMessages({ + topic: KAFKA_JOBS_DLQ, + messages: [{ value: message.value, key: message.key }], }) resolveOffset(message.offset) continue @@ -74,12 +71,9 @@ export const startJobsConsumer = async ({ error, }) // TODO: handle resolving offsets asynchronously - await producer.queueMessage({ - kafkaMessage: { - topic: KAFKA_JOBS_DLQ, - messages: [{ value: message.value, key: message.key }], - }, - waitForAck: true, + await producer.queueMessages({ + topic: KAFKA_JOBS_DLQ, + messages: [{ value: message.value, key: message.key }], }) resolveOffset(message.offset) continue diff --git a/plugin-server/src/main/ingestion-queues/kafka-queue.ts b/plugin-server/src/main/ingestion-queues/kafka-queue.ts index 1e7a58a0e076b..e3a8c3df2cbc6 100644 --- a/plugin-server/src/main/ingestion-queues/kafka-queue.ts +++ b/plugin-server/src/main/ingestion-queues/kafka-queue.ts @@ -6,7 +6,6 @@ import { Counter } from 'prom-client' import { BatchConsumer, startBatchConsumer } from '../../kafka/batch-consumer' import { createRdConnectionConfigFromEnvVars } from '../../kafka/config' import { Hub } from '../../types' -import { KafkaConfig } from '../../utils/db/hub' import { timeoutGuard } from '../../utils/db/utils' import { status } from '../../utils/status' import { killGracefully } from '../../utils/utils' @@ -185,7 +184,7 @@ export class IngestionConsumer { this.consumer = await startBatchConsumer({ batchingTimeoutMs: this.pluginsServer.KAFKA_CONSUMPTION_BATCHING_TIMEOUT_MS, consumerErrorBackoffMs: this.pluginsServer.KAFKA_CONSUMPTION_ERROR_BACKOFF_MS, - connectionConfig: createRdConnectionConfigFromEnvVars(this.pluginsServer as KafkaConfig), + connectionConfig: createRdConnectionConfigFromEnvVars(this.pluginsServer, 'consumer'), topic: this.topic, groupId: this.consumerGroupId, autoCommit: true, diff --git a/plugin-server/src/main/ingestion-queues/scheduled-tasks-consumer.ts b/plugin-server/src/main/ingestion-queues/scheduled-tasks-consumer.ts index 8a225f02766ff..8ce5fdbefecae 100644 --- a/plugin-server/src/main/ingestion-queues/scheduled-tasks-consumer.ts +++ b/plugin-server/src/main/ingestion-queues/scheduled-tasks-consumer.ts @@ -1,7 +1,7 @@ import { Batch, EachBatchHandler, Kafka } from 'kafkajs' -import { KafkaProducerWrapper } from 'utils/db/kafka-producer-wrapper' import { KAFKA_SCHEDULED_TASKS, KAFKA_SCHEDULED_TASKS_DLQ } from '../../config/kafka-topics' +import { KafkaProducerWrapper } from '../../kafka/producer' import { PluginServerService, PluginsServerConfig } from '../../types' import { DependencyUnavailableError } from '../../utils/db/error' import { status } from '../../utils/status' @@ -164,12 +164,9 @@ const getTasksFromBatch = async (batch: Batch, producer: KafkaProducerWrapper) = status.warn('⚠️', `Invalid message for partition ${batch.partition} offset ${message.offset}.`, { value: message.value, }) - await producer.queueMessage({ - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS_DLQ, - messages: [{ value: message.value, key: message.key }], - }, - waitForAck: true, + await producer.queueMessages({ + topic: KAFKA_SCHEDULED_TASKS_DLQ, + messages: [{ value: message.value, key: message.key }], }) continue } @@ -185,24 +182,18 @@ const getTasksFromBatch = async (batch: Batch, producer: KafkaProducerWrapper) = status.warn('⚠️', `Invalid message for partition ${batch.partition} offset ${message.offset}.`, { error: error.stack ?? error, }) - await producer.queueMessage({ - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS_DLQ, - messages: [{ value: message.value, key: message.key }], - }, - waitForAck: true, + await producer.queueMessages({ + topic: KAFKA_SCHEDULED_TASKS_DLQ, + messages: [{ value: message.value, key: message.key }], }) continue } if (!taskTypes.includes(task.taskType) || isNaN(task.pluginConfigId)) { status.warn('⚠️', `Invalid schema for partition ${batch.partition} offset ${message.offset}.`, task) - await producer.queueMessage({ - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS_DLQ, - messages: [{ value: message.value, key: message.key }], - }, - waitForAck: true, + await producer.queueMessages({ + topic: KAFKA_SCHEDULED_TASKS_DLQ, + messages: [{ value: message.value, key: message.key }], }) continue } diff --git a/plugin-server/src/main/ingestion-queues/session-recording/services/console-logs-ingester.ts b/plugin-server/src/main/ingestion-queues/session-recording/services/console-logs-ingester.ts index 50662d472bc57..ea0f548cccb8c 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/services/console-logs-ingester.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/services/console-logs-ingester.ts @@ -1,11 +1,10 @@ import { captureException } from '@sentry/node' -import { HighLevelProducer as RdKafkaProducer, NumberNullUndefined } from 'node-rdkafka' import { Counter } from 'prom-client' import { KAFKA_LOG_ENTRIES } from '../../../../config/kafka-topics' import { findOffsetsToCommit } from '../../../../kafka/consumer' import { retryOnDependencyUnavailableError } from '../../../../kafka/error-handling' -import { flushProducer, produce } from '../../../../kafka/producer' +import { KafkaProducerWrapper } from '../../../../kafka/producer' import { status } from '../../../../utils/status' import { eventDroppedCounter } from '../../metrics' import { ConsoleLogEntry, gatherConsoleLogEvents, RRWebEventType } from '../process-event' @@ -41,12 +40,12 @@ function deduplicateConsoleLogEvents(consoleLogEntries: ConsoleLogEntry[]): Cons // am going to leave this duplication and then collapse it when/if we add a performance events ingester export class ConsoleLogsIngester { constructor( - private readonly producer: RdKafkaProducer, + private readonly producer: KafkaProducerWrapper, private readonly persistentHighWaterMarker?: OffsetHighWaterMarker ) {} public async consumeBatch(messages: IncomingRecordingMessage[]) { - const pendingProduceRequests: Promise[] = [] + const pendingProduceRequests: Promise[] = [] for (const message of messages) { const results = await retryOnDependencyUnavailableError(() => this.consume(message)) @@ -60,7 +59,7 @@ export class ConsoleLogsIngester { // On each loop, we flush the producer to ensure that all messages // are sent to Kafka. try { - await flushProducer(this.producer!) + await this.producer.flush() } catch (error) { // Rather than handling errors from flush, we instead handle // errors per produce request, which gives us a little more @@ -105,7 +104,7 @@ export class ConsoleLogsIngester { } } - public async consume(event: IncomingRecordingMessage): Promise[] | void> { + public async consume(event: IncomingRecordingMessage): Promise[] | void> { const drop = (reason: string) => { eventDroppedCounter .labels({ @@ -155,15 +154,15 @@ export class ConsoleLogsIngester { ) consoleLogEventsCounter.inc(consoleLogEvents.length) - return consoleLogEvents.map((cle: ConsoleLogEntry) => - produce({ - producer, + return [ + this.producer.queueMessages({ topic: KAFKA_LOG_ENTRIES, - value: Buffer.from(JSON.stringify(cle)), - key: event.session_id, - waitForAck: true, - }) - ) + messages: consoleLogEvents.map((cle: ConsoleLogEntry) => ({ + value: JSON.stringify(cle), + key: event.session_id, + })), + }), + ] } catch (error) { status.error('⚠️', '[console-log-events-ingester] processing_error', { error: error, diff --git a/plugin-server/src/main/ingestion-queues/session-recording/services/replay-events-ingester.ts b/plugin-server/src/main/ingestion-queues/session-recording/services/replay-events-ingester.ts index c54be841678d6..17ba00d657ff9 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/services/replay-events-ingester.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/services/replay-events-ingester.ts @@ -1,14 +1,12 @@ import { captureException } from '@sentry/node' import { randomUUID } from 'crypto' import { DateTime } from 'luxon' -import { HighLevelProducer as RdKafkaProducer, NumberNullUndefined } from 'node-rdkafka' import { Counter } from 'prom-client' import { KAFKA_CLICKHOUSE_SESSION_REPLAY_EVENTS } from '../../../../config/kafka-topics' import { findOffsetsToCommit } from '../../../../kafka/consumer' import { retryOnDependencyUnavailableError } from '../../../../kafka/error-handling' -import { flushProducer, produce } from '../../../../kafka/producer' -import { KafkaProducerWrapper } from '../../../../utils/db/kafka-producer-wrapper' +import { KafkaProducerWrapper } from '../../../../kafka/producer' import { status } from '../../../../utils/status' import { captureIngestionWarning } from '../../../../worker/ingestion/utils' import { eventDroppedCounter } from '../../metrics' @@ -32,12 +30,12 @@ const dataIngestedCounter = new Counter({ export class ReplayEventsIngester { constructor( - private readonly producer: RdKafkaProducer, + private readonly producer: KafkaProducerWrapper, private readonly persistentHighWaterMarker?: OffsetHighWaterMarker ) {} public async consumeBatch(messages: IncomingRecordingMessage[]) { - const pendingProduceRequests: Promise[] = [] + const pendingProduceRequests: Promise[] = [] for (const message of messages) { const results = await retryOnDependencyUnavailableError(() => this.consume(message)) @@ -51,7 +49,7 @@ export class ReplayEventsIngester { // On each loop, we flush the producer to ensure that all messages // are sent to Kafka. try { - await flushProducer(this.producer!) + await this.producer.flush() } catch (error) { // Rather than handling errors from flush, we instead handle // errors per produce request, which gives us a little more @@ -97,7 +95,7 @@ export class ReplayEventsIngester { } } - public async consume(event: IncomingRecordingMessage): Promise[] | void> { + public async consume(event: IncomingRecordingMessage): Promise[] | void> { const drop = (reason: string) => { eventDroppedCounter .labels({ @@ -149,7 +147,7 @@ export class ReplayEventsIngester { } await captureIngestionWarning( - new KafkaProducerWrapper(this.producer), + this.producer, event.team_id, !asDate.isValid ? 'replay_timestamp_invalid' : 'replay_timestamp_too_far', { @@ -184,12 +182,14 @@ export class ReplayEventsIngester { dataIngestedCounter.inc({ snapshot_source: replayRecord.snapshot_source ?? undefined }, replayRecord.size) return [ - produce({ - producer: this.producer, + this.producer.queueMessages({ topic: KAFKA_CLICKHOUSE_SESSION_REPLAY_EVENTS, - value: Buffer.from(JSON.stringify(replayRecord)), - key: event.session_id, - waitForAck: true, + messages: [ + { + value: JSON.stringify(replayRecord), + key: event.session_id, + }, + ], }), ] } catch (error) { diff --git a/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts b/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts index 6e3cd0a84b755..2344a28f89d19 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts @@ -11,11 +11,10 @@ import { KAFKA_SESSION_RECORDING_SNAPSHOT_ITEM_OVERFLOW, } from '../../../config/kafka-topics' import { BatchConsumer, startBatchConsumer } from '../../../kafka/batch-consumer' -import { createRdConnectionConfigFromEnvVars, createRdProducerConfigFromEnvVars } from '../../../kafka/config' -import { createKafkaProducer } from '../../../kafka/producer' +import { createRdConnectionConfigFromEnvVars } from '../../../kafka/config' +import { KafkaProducerWrapper } from '../../../kafka/producer' import { PluginServerService, PluginsServerConfig, RedisPool, TeamId, ValueMatcher } from '../../../types' import { BackgroundRefresher } from '../../../utils/background-refresher' -import { KafkaProducerWrapper } from '../../../utils/db/kafka-producer-wrapper' import { PostgresRouter } from '../../../utils/db/postgres' import { createRedisPool } from '../../../utils/db/redis' import { status } from '../../../utils/status' @@ -472,24 +471,19 @@ export class SessionRecordingIngester { await this.teamsRefresher.refresh() // NOTE: We use the standard config as we connect to the analytics kafka for producing - const globalConnectionConfig = createRdConnectionConfigFromEnvVars(this.config) - const globalProducerConfig = createRdProducerConfigFromEnvVars(this.config) - - this.sharedClusterProducerWrapper = new KafkaProducerWrapper( - await createKafkaProducer(globalConnectionConfig, globalProducerConfig) - ) + this.sharedClusterProducerWrapper = await KafkaProducerWrapper.create(this.config) this.sharedClusterProducerWrapper.producer.connect() if (this.config.SESSION_RECORDING_CONSOLE_LOGS_INGESTION_ENABLED) { this.consoleLogsIngester = new ConsoleLogsIngester( - this.sharedClusterProducerWrapper.producer, + this.sharedClusterProducerWrapper, this.persistentHighWaterMarker ) } if (this.config.SESSION_RECORDING_REPLAY_EVENTS_INGESTION_ENABLED) { this.replayEventsIngester = new ReplayEventsIngester( - this.sharedClusterProducerWrapper.producer, + this.sharedClusterProducerWrapper, this.persistentHighWaterMarker ) } @@ -497,7 +491,11 @@ export class SessionRecordingIngester { // Create a node-rdkafka consumer that fetches batches of messages, runs // eachBatchWithContext, then commits offsets for the batch. // the batch consumer reads from the session replay kafka cluster - const replayClusterConnectionConfig = createRdConnectionConfigFromEnvVars(this.sessionRecordingKafkaConfig()) + const replayClusterConnectionConfig = createRdConnectionConfigFromEnvVars( + // TODO: Replace this with the new ENV vars for producer specific config when ready. + this.sessionRecordingKafkaConfig(), + 'consumer' + ) this.batchConsumer = await startBatchConsumer({ connectionConfig: replayClusterConnectionConfig, diff --git a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts index 16b336d8f952c..8cca764e2e3ef 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts @@ -4,8 +4,8 @@ import { KafkaConsumer, Message, MessageHeader, PartitionMetadata } from 'node-r import path from 'path' import { Counter } from 'prom-client' +import { KafkaProducerWrapper } from '../../../kafka/producer' import { PipelineEvent, RawEventMessage, RRWebEvent } from '../../../types' -import { KafkaProducerWrapper } from '../../../utils/db/kafka-producer-wrapper' import { status } from '../../../utils/status' import { captureIngestionWarning } from '../../../worker/ingestion/utils' import { eventDroppedCounter } from '../metrics' diff --git a/plugin-server/src/main/pluginsServer.ts b/plugin-server/src/main/pluginsServer.ts index c58b42d1a8ef7..192be4527470c 100644 --- a/plugin-server/src/main/pluginsServer.ts +++ b/plugin-server/src/main/pluginsServer.ts @@ -19,8 +19,9 @@ import { CdpProcessedEventsConsumer, } from '../cdp/cdp-consumers' import { defaultConfig } from '../config/config' +import { KafkaProducerWrapper } from '../kafka/producer' import { Hub, PluginServerCapabilities, PluginServerService, PluginsServerConfig } from '../types' -import { closeHub, createHub, createKafkaClient, createKafkaProducerWrapper } from '../utils/db/hub' +import { closeHub, createHub, createKafkaClient } from '../utils/db/hub' import { PostgresRouter } from '../utils/db/postgres' import { createRedisClient } from '../utils/db/redis' import { cancelAllScheduledJobs } from '../utils/node-schedule' @@ -336,12 +337,12 @@ export async function startPluginsServer( const kafka = hub?.kafka ?? createKafkaClient(serverConfig) const teamManager = hub?.teamManager ?? new TeamManager(postgres, serverConfig) const organizationManager = hub?.organizationManager ?? new OrganizationManager(postgres, teamManager) - const KafkaProducerWrapper = hub?.kafkaProducer ?? (await createKafkaProducerWrapper(serverConfig)) + const kafkaProducerWrapper = hub?.kafkaProducer ?? (await KafkaProducerWrapper.create(serverConfig)) const rustyHook = hub?.rustyHook ?? new RustyHook(serverConfig) const appMetrics = hub?.appMetrics ?? new AppMetrics( - KafkaProducerWrapper, + kafkaProducerWrapper, serverConfig.APP_METRICS_FLUSH_FREQUENCY_MS, serverConfig.APP_METRICS_FLUSH_MAX_QUEUE_SIZE ) diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 74f109836c752..fb40c048bb464 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -19,10 +19,10 @@ import { DateTime } from 'luxon' import { VM } from 'vm2' import { EncryptedFields } from './cdp/encryption-utils' +import { KafkaProducerWrapper } from './kafka/producer' import { ObjectStorage } from './main/services/object_storage' import { Celery } from './utils/db/celery' import { DB } from './utils/db/db' -import { KafkaProducerWrapper } from './utils/db/kafka-producer-wrapper' import { PostgresRouter } from './utils/db/postgres' import { UUID } from './utils/utils' import { ActionManager } from './worker/ingestion/action-manager' @@ -164,15 +164,23 @@ export interface PluginsServerConfig extends CdpConfig { // Common redis params REDIS_POOL_MIN_SIZE: number // minimum number of Redis connections to use per thread REDIS_POOL_MAX_SIZE: number // maximum number of Redis connections to use per thread + // Kafka params - identical for client and producer KAFKA_HOSTS: string // comma-delimited Kafka hosts + KAFKA_PRODUCER_HOSTS?: string // If specified - different hosts to produce to (useful for migrating between kafka clusters) + KAFKA_SECURITY_PROTOCOL: KafkaSecurityProtocol | undefined + KAFKA_PRODUCER_SECURITY_PROTOCOL?: KafkaSecurityProtocol // If specified - different security protocol to produce to (useful for migrating between kafka clusters) + KAFKA_CLIENT_ID: string | undefined + KAFKA_PRODUCER_CLIENT_ID?: string // If specified - different client ID to produce to (useful for migrating between kafka clusters) + + // Other methods that are generally only used by self-hosted users KAFKA_CLIENT_CERT_B64: string | undefined KAFKA_CLIENT_CERT_KEY_B64: string | undefined KAFKA_TRUSTED_CERT_B64: string | undefined - KAFKA_SECURITY_PROTOCOL: KafkaSecurityProtocol | undefined KAFKA_SASL_MECHANISM: KafkaSaslMechanism | undefined KAFKA_SASL_USER: string | undefined KAFKA_SASL_PASSWORD: string | undefined - KAFKA_CLIENT_ID: string | undefined + + // Consumer specific settings KAFKA_CLIENT_RACK: string | undefined KAFKA_CONSUMPTION_MAX_BYTES: number KAFKA_CONSUMPTION_MAX_BYTES_PER_PARTITION: number diff --git a/plugin-server/src/utils/db/db.ts b/plugin-server/src/utils/db/db.ts index c89c08520fffe..eeee1c49b1072 100644 --- a/plugin-server/src/utils/db/db.ts +++ b/plugin-server/src/utils/db/db.ts @@ -3,11 +3,11 @@ import { CacheOptions, Properties } from '@posthog/plugin-scaffold' import { captureException } from '@sentry/node' import { Pool as GenericPool } from 'generic-pool' import Redis from 'ioredis' -import { ProducerRecord } from 'kafkajs' import { DateTime } from 'luxon' import { QueryResult } from 'pg' import { KAFKA_GROUPS, KAFKA_PERSON_DISTINCT_ID, KAFKA_PLUGIN_LOG_ENTRIES } from '../../config/kafka-topics' +import { KafkaProducerWrapper, TopicMessage } from '../../kafka/producer' import { Action, ClickHouseEvent, @@ -63,7 +63,6 @@ import { UUIDT, } from '../utils' import { OrganizationPluginsAccessLevel } from './../../types' -import { KafkaProducerWrapper } from './kafka-producer-wrapper' import { personUpdateVersionMismatchCounter, pluginLogEntryCounter } from './metrics' import { PostgresRouter, PostgresUse, TransactionClient } from './postgres' import { @@ -697,7 +696,7 @@ export class DB { }) } - await this.kafkaProducer.queueMessages({ kafkaMessages, waitForAck: true }) + await this.kafkaProducer.queueMessages(kafkaMessages) return person } @@ -706,7 +705,7 @@ export class DB { person: InternalPerson, update: Partial, tx?: TransactionClient - ): Promise<[InternalPerson, ProducerRecord[]]> { + ): Promise<[InternalPerson, TopicMessage[]]> { let versionString = 'COALESCE(version, 0)::numeric + 1' if (update.version) { versionString = update.version.toString() @@ -758,7 +757,7 @@ export class DB { return [updatedPerson, [kafkaMessage]] } - public async deletePerson(person: InternalPerson, tx?: TransactionClient): Promise { + public async deletePerson(person: InternalPerson, tx?: TransactionClient): Promise { const { rows } = await this.postgres.query<{ version: string }>( tx ?? PostgresUse.COMMON_WRITE, 'DELETE FROM posthog_person WHERE team_id = $1 AND id = $2 RETURNING version', @@ -766,7 +765,7 @@ export class DB { 'deletePerson' ) - let kafkaMessages: ProducerRecord[] = [] + let kafkaMessages: TopicMessage[] = [] if (rows.length > 0) { const [row] = rows @@ -881,7 +880,7 @@ export class DB { ): Promise { const kafkaMessages = await this.addDistinctIdPooled(person, distinctId, version, tx) if (kafkaMessages.length) { - await this.kafkaProducer.queueMessages({ kafkaMessages, waitForAck: true }) + await this.kafkaProducer.queueMessages(kafkaMessages) } } @@ -890,7 +889,7 @@ export class DB { distinctId: string, version: number, tx?: TransactionClient - ): Promise { + ): Promise { const insertResult = await this.postgres.query( tx ?? PostgresUse.COMMON_WRITE, // NOTE: Keep this in sync with the posthog_persondistinctid INSERT in `createPerson` @@ -923,7 +922,7 @@ export class DB { source: InternalPerson, target: InternalPerson, tx?: TransactionClient - ): Promise { + ): Promise { let movedDistinctIdResult: QueryResult | null = null try { movedDistinctIdResult = await this.postgres.query( @@ -1099,12 +1098,12 @@ export class DB { return queryResult.data as PluginLogEntry[] } - public async queuePluginLogEntry(entry: LogEntryPayload): Promise { + public queuePluginLogEntry(entry: LogEntryPayload): Promise { const { pluginConfig, source, message, type, timestamp, instanceId } = entry const configuredLogLevel = pluginConfig.plugin?.log_level || this.pluginsDefaultLogLevel if (!shouldStoreLog(configuredLogLevel, type)) { - return + return Promise.resolve() } const parsedEntry = { @@ -1122,24 +1121,33 @@ export class DB { if (parsedEntry.message.length > 50_000) { const { message, ...rest } = parsedEntry status.warn('⚠️', 'Plugin log entry too long, ignoring.', rest) - return + return Promise.resolve() } pluginLogEntryCounter.labels({ plugin_id: String(pluginConfig.plugin_id), source }).inc() try { - await this.kafkaProducer.queueSingleJsonMessage({ - topic: KAFKA_PLUGIN_LOG_ENTRIES, - key: parsedEntry.id, - object: parsedEntry, - // For logs, we relax our durability requirements a little and - // do not wait for acks that Kafka has persisted the message to - // disk. - waitForAck: false, - }) + // For logs, we relax our durability requirements a little and + // do not wait for acks that Kafka has persisted the message to + // disk. + void this.kafkaProducer + .queueMessages({ + topic: KAFKA_PLUGIN_LOG_ENTRIES, + messages: [{ key: parsedEntry.id, value: JSON.stringify(parsedEntry) }], + }) + .catch((error) => { + status.warn('⚠️', 'Failed to produce plugin log entry', { + error, + entry: parsedEntry, + }) + }) + + // TRICKY: We don't want to block the caller, so we return a promise that resolves immediately. + return Promise.resolve() } catch (e) { captureException(e, { tags: { team_id: entry.pluginConfig.team_id } }) console.error('Failed to produce message', e, parsedEntry) + return Promise.resolve() } } @@ -1412,23 +1420,20 @@ export class DB { createdAt: DateTime, version: number ): Promise { - await this.kafkaProducer.queueMessage({ - kafkaMessage: { - topic: KAFKA_GROUPS, - messages: [ - { - value: JSON.stringify({ - group_type_index: groupTypeIndex, - group_key: groupKey, - team_id: teamId, - group_properties: JSON.stringify(properties), - created_at: castTimestampOrNow(createdAt, TimestampFormat.ClickHouseSecondPrecision), - version, - }), - }, - ], - }, - waitForAck: true, + await this.kafkaProducer.queueMessages({ + topic: KAFKA_GROUPS, + messages: [ + { + value: JSON.stringify({ + group_type_index: groupTypeIndex, + group_key: groupKey, + team_id: teamId, + group_properties: JSON.stringify(properties), + created_at: castTimestampOrNow(createdAt, TimestampFormat.ClickHouseSecondPrecision), + version, + }), + }, + ], }) } diff --git a/plugin-server/src/utils/db/error.ts b/plugin-server/src/utils/db/error.ts index 96924a35a9c17..8bd2d4f8f5f5d 100644 --- a/plugin-server/src/utils/db/error.ts +++ b/plugin-server/src/utils/db/error.ts @@ -35,7 +35,7 @@ export async function processError( captureException(new Error('Tried to process error for nonexistent plugin config!'), { tags: { team_id: event?.team_id }, }) - return + return Promise.resolve() } if (error instanceof DependencyUnavailableError) { diff --git a/plugin-server/src/utils/db/hub.ts b/plugin-server/src/utils/db/hub.ts index c8753b4256bc0..c646d5cb62046 100644 --- a/plugin-server/src/utils/db/hub.ts +++ b/plugin-server/src/utils/db/hub.ts @@ -12,13 +12,11 @@ import { EncryptedFields } from '../../cdp/encryption-utils' import { buildIntegerMatcher, defaultConfig } from '../../config/config' import { KAFKAJS_LOG_LEVEL_MAPPING } from '../../config/constants' import { KAFKA_JOBS } from '../../config/kafka-topics' -import { createRdConnectionConfigFromEnvVars, createRdProducerConfigFromEnvVars } from '../../kafka/config' -import { createKafkaProducer } from '../../kafka/producer' +import { KafkaProducerWrapper } from '../../kafka/producer' import { getObjectStorage } from '../../main/services/object_storage' import { EnqueuedPluginJob, Hub, - KafkaSaslMechanism, KafkaSecurityProtocol, PluginServerCapabilities, PluginsServerConfig, @@ -37,7 +35,6 @@ import { PluginsApiKeyManager } from './../../worker/vm/extensions/helpers/api-k import { RootAccessManager } from './../../worker/vm/extensions/helpers/root-acess-manager' import { Celery } from './celery' import { DB } from './db' -import { KafkaProducerWrapper } from './kafka-producer-wrapper' import { PostgresRouter } from './postgres' import { createRedisPool } from './redis' @@ -54,13 +51,6 @@ pgTypes.setTypeParser(1184 /* types.TypeId.TIMESTAMPTZ */, (timeStr) => timeStr ? DateTime.fromSQL(timeStr, { zone: 'utc' }).toISO() : null ) -export async function createKafkaProducerWrapper(serverConfig: PluginsServerConfig): Promise { - const kafkaConnectionConfig = createRdConnectionConfigFromEnvVars(serverConfig) - const producerConfig = createRdProducerConfigFromEnvVars(serverConfig) - const producer = await createKafkaProducer(kafkaConnectionConfig, producerConfig) - return new KafkaProducerWrapper(producer) -} - export function createEventsToDropByToken(eventsToDropByTokenStr?: string): Map { const eventsToDropByToken: Map = new Map() if (eventsToDropByTokenStr) { @@ -113,7 +103,7 @@ export async function createHub( status.info('🤔', `Connecting to Kafka...`) const kafka = createKafkaClient(serverConfig) - const kafkaProducer = await createKafkaProducerWrapper(serverConfig) + const kafkaProducer = await KafkaProducerWrapper.create(serverConfig) status.info('👍', `Kafka ready`) const postgres = new PostgresRouter(serverConfig) @@ -158,17 +148,14 @@ export async function createHub( // an acknowledgement as for instance there are some jobs that are // chained, and if we do not manage to produce then the chain will be // broken. - await kafkaProducer.queueMessage({ - kafkaMessage: { - topic: KAFKA_JOBS, - messages: [ - { - value: Buffer.from(JSON.stringify(job)), - key: Buffer.from(job.pluginConfigTeam.toString()), - }, - ], - }, - waitForAck: true, + await kafkaProducer.queueMessages({ + topic: KAFKA_JOBS, + messages: [ + { + value: Buffer.from(JSON.stringify(job)), + key: Buffer.from(job.pluginConfigTeam.toString()), + }, + ], }) } @@ -229,19 +216,23 @@ export const closeHub = async (hub: Hub): Promise => { } } -export type KafkaConfig = { - KAFKA_HOSTS: string - KAFKAJS_LOG_LEVEL: keyof typeof KAFKAJS_LOG_LEVEL_MAPPING - KAFKA_SECURITY_PROTOCOL: 'PLAINTEXT' | 'SSL' | 'SASL_PLAINTEXT' | 'SASL_SSL' | undefined - KAFKA_CLIENT_CERT_B64?: string - KAFKA_CLIENT_CERT_KEY_B64?: string - KAFKA_TRUSTED_CERT_B64?: string - KAFKA_SASL_MECHANISM?: KafkaSaslMechanism - KAFKA_SASL_USER?: string - KAFKA_SASL_PASSWORD?: string - KAFKA_CLIENT_RACK?: string - KAFKA_CLIENT_ID?: string -} +export type KafkaConfig = Pick< + PluginsServerConfig, + | 'KAFKA_HOSTS' + | 'KAFKA_PRODUCER_HOSTS' + | 'KAFKA_SECURITY_PROTOCOL' + | 'KAFKA_PRODUCER_SECURITY_PROTOCOL' + | 'KAFKA_CLIENT_ID' + | 'KAFKA_PRODUCER_CLIENT_ID' + | 'KAFKA_CLIENT_RACK' + | 'KAFKAJS_LOG_LEVEL' + | 'KAFKA_CLIENT_CERT_B64' + | 'KAFKA_CLIENT_CERT_KEY_B64' + | 'KAFKA_TRUSTED_CERT_B64' + | 'KAFKA_SASL_MECHANISM' + | 'KAFKA_SASL_USER' + | 'KAFKA_SASL_PASSWORD' +> export function createKafkaClient({ KAFKA_HOSTS, diff --git a/plugin-server/src/utils/db/kafka-producer-wrapper.ts b/plugin-server/src/utils/db/kafka-producer-wrapper.ts deleted file mode 100644 index 0813c783096a4..0000000000000 --- a/plugin-server/src/utils/db/kafka-producer-wrapper.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { Message, ProducerRecord } from 'kafkajs' -import { HighLevelProducer, LibrdKafkaError, MessageHeader, MessageValue } from 'node-rdkafka' -import { Counter } from 'prom-client' - -import { disconnectProducer, flushProducer, MessageKey, produce } from '../../kafka/producer' -import { status } from '../../utils/status' -import { DependencyUnavailableError, MessageSizeTooLarge } from './error' - -/** This class is a wrapper around the rdkafka producer, and does very little. - * It used to be a wrapper around KafkaJS, but we switched to rdkafka because of - * increased performance. - * - * The big difference between this and the original is that we return a promise from - * queueMessage, which will only resolve once we get an ack that the message has - * been persisted to Kafka. So we should get stronger guarantees on processing. - * - * TODO: refactor Kafka producer usage to use rdkafka directly. - */ -export class KafkaProducerWrapper { - /** Kafka producer used for syncing Postgres and ClickHouse person data. */ - public producer: HighLevelProducer - - constructor(producer: HighLevelProducer) { - this.producer = producer - } - - async produce({ - value, - key, - topic, - headers, - waitForAck, - }: { - value: MessageValue - key: MessageKey - topic: string - headers?: MessageHeader[] - waitForAck: boolean - }): Promise { - try { - kafkaProducerMessagesQueuedCounter.labels({ topic_name: topic }).inc() - return await produce({ - producer: this.producer, - topic: topic, - key: key, - value: value, - headers: headers, - waitForAck: waitForAck, - }).then((_) => { - kafkaProducerMessagesWrittenCounter.labels({ topic_name: topic }).inc() - return // Swallow the returned offsets, and return a void for easier typing - }) - } catch (error) { - kafkaProducerMessagesFailedCounter.labels({ topic_name: topic }).inc() - status.error('⚠️', 'kafka_produce_error', { error: error, topic: topic }) - - if ((error as LibrdKafkaError).isRetriable) { - // If we get a retriable error, bubble that up so that the - // caller can retry. - throw new DependencyUnavailableError(error.message, 'Kafka', error) - } else if ((error as LibrdKafkaError).code === 10) { - throw new MessageSizeTooLarge(error.message, error) - } - - throw error - } - } - - async queueMessage({ kafkaMessage, waitForAck }: { kafkaMessage: ProducerRecord; waitForAck: boolean }) { - return await Promise.all( - kafkaMessage.messages.map((message) => - this.produce({ - topic: kafkaMessage.topic, - key: message.key ? Buffer.from(message.key) : null, - value: message.value ? Buffer.from(message.value) : null, - headers: convertKafkaJSHeadersToRdKafkaHeaders(message.headers), - waitForAck: waitForAck, - }) - ) - ) - } - - async queueMessages({ - kafkaMessages, - waitForAck, - }: { - kafkaMessages: ProducerRecord[] - waitForAck: boolean - }): Promise { - await Promise.all(kafkaMessages.map((kafkaMessage) => this.queueMessage({ kafkaMessage, waitForAck }))) - } - - async queueSingleJsonMessage({ - topic, - key, - object, - waitForAck, - }: { - topic: string - key: Message['key'] - object: Record - waitForAck: boolean - }): Promise { - await this.queueMessage({ - kafkaMessage: { - topic, - messages: [{ key, value: JSON.stringify(object) }], - }, - waitForAck, - }) - } - - public async flush() { - return await flushProducer(this.producer) - } - - public async disconnect(): Promise { - await this.flush() - await disconnectProducer(this.producer) - } -} - -export const convertKafkaJSHeadersToRdKafkaHeaders = (headers: Message['headers'] = undefined) => - // We need to convert from KafkaJS headers to rdkafka - // headers format. The former has type - // { [key: string]: string | Buffer | (string | - // Buffer)[] | undefined } - // while the latter has type - // { [key: string]: Buffer }[]. The formers values that - // are arrays need to be converted into an array of - // objects with a single key-value pair, and the - // undefined values need to be filtered out. - headers - ? Object.entries(headers) - .flatMap(([key, value]) => - value === undefined - ? [] - : Array.isArray(value) - ? value.map((v) => ({ key, value: Buffer.from(v) })) - : [{ key, value: Buffer.from(value) }] - ) - .map(({ key, value }) => ({ [key]: value })) - : undefined - -export const kafkaProducerMessagesQueuedCounter = new Counter({ - name: 'kafka_producer_messages_queued_total', - help: 'Count of messages queued to the Kafka producer, by destination topic.', - labelNames: ['topic_name'], -}) - -export const kafkaProducerMessagesWrittenCounter = new Counter({ - name: 'kafka_producer_messages_written_total', - help: 'Count of messages written to Kafka, by destination topic.', - labelNames: ['topic_name'], -}) - -export const kafkaProducerMessagesFailedCounter = new Counter({ - name: 'kafka_producer_messages_failed_total', - help: 'Count of write failures by the Kafka producer, by destination topic.', - labelNames: ['topic_name'], -}) diff --git a/plugin-server/src/utils/db/utils.ts b/plugin-server/src/utils/db/utils.ts index 6a81cba6f1e97..f0204f0ef4c77 100644 --- a/plugin-server/src/utils/db/utils.ts +++ b/plugin-server/src/utils/db/utils.ts @@ -1,6 +1,6 @@ import { Properties } from '@posthog/plugin-scaffold' import * as Sentry from '@sentry/node' -import { ProducerRecord } from 'kafkajs' +import { TopicMessage } from 'kafka/producer' import { Counter } from 'prom-client' import { defaultConfig } from '../../config/config' @@ -181,7 +181,7 @@ export function hasDifferenceWithProposedNewNormalisationMode(properties: Proper return !areMapsEqual(setOnce, filteredSetOnce) } -export function generateKafkaPersonUpdateMessage(person: InternalPerson, isDeleted = false): ProducerRecord { +export function generateKafkaPersonUpdateMessage(person: InternalPerson, isDeleted = false): TopicMessage { return { topic: KAFKA_PERSON, messages: [ diff --git a/plugin-server/src/worker/ingestion/app-metrics.ts b/plugin-server/src/worker/ingestion/app-metrics.ts index 5e0a83c92ae31..4273118db9a41 100644 --- a/plugin-server/src/worker/ingestion/app-metrics.ts +++ b/plugin-server/src/worker/ingestion/app-metrics.ts @@ -2,9 +2,9 @@ import * as Sentry from '@sentry/node' import { Message } from 'kafkajs' import { DateTime } from 'luxon' import { configure } from 'safe-stable-stringify' -import { KafkaProducerWrapper } from 'utils/db/kafka-producer-wrapper' import { KAFKA_APP_METRICS } from '../../config/kafka-topics' +import { KafkaProducerWrapper } from '../../kafka/producer' import { TeamId, TimestampFormat } from '../../types' import { cleanErrorStackTrace } from '../../utils/db/error' import { status } from '../../utils/status' @@ -164,7 +164,7 @@ export class AppMetrics { this.queueSize = 0 this.queuedData = {} - const kafkaMessages: Message[] = Object.values(queue).map((value) => ({ + const messages: Message[] = Object.values(queue).map((value) => ({ value: JSON.stringify({ timestamp: castTimestampOrNow(DateTime.fromMillis(value.lastTimestamp), TimestampFormat.ClickHouse), team_id: value.metric.teamId, @@ -182,12 +182,9 @@ export class AppMetrics { } as RawAppMetric), })) - await this.kafkaProducer.queueMessage({ - kafkaMessage: { - topic: KAFKA_APP_METRICS, - messages: kafkaMessages, - }, - waitForAck: true, + await this.kafkaProducer.queueMessages({ + topic: KAFKA_APP_METRICS, + messages: messages, }) status.debug('🚽', `Finished flushing app metrics, took ${Date.now() - startTime}ms`) } diff --git a/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts index 93c759a1770a4..413ff28436cb6 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts @@ -34,15 +34,15 @@ export async function extractHeatmapDataStep( if (team?.heatmaps_opt_in !== false) { const heatmapEvents = extractScrollDepthHeatmapData(event) ?? [] - // eslint-disable-next-line @typescript-eslint/no-floating-promises - acks = heatmapEvents.map((rawEvent) => { - return runner.hub.kafkaProducer.produce({ + acks.push( + runner.hub.kafkaProducer.queueMessages({ topic: runner.hub.CLICKHOUSE_HEATMAPS_KAFKA_TOPIC, - key: eventUuid, - value: Buffer.from(JSON.stringify(rawEvent)), - waitForAck: true, + messages: heatmapEvents.map((rawEvent) => ({ + key: eventUuid, + value: JSON.stringify(rawEvent), + })), }) - }) + ) } } catch (e) { acks.push( diff --git a/plugin-server/src/worker/ingestion/person-state.ts b/plugin-server/src/worker/ingestion/person-state.ts index 2a4aa85592547..aee156fe3b808 100644 --- a/plugin-server/src/worker/ingestion/person-state.ts +++ b/plugin-server/src/worker/ingestion/person-state.ts @@ -1,11 +1,11 @@ import { PluginEvent, Properties } from '@posthog/plugin-scaffold' import * as Sentry from '@sentry/node' -import { ProducerRecord } from 'kafkajs' import LRU from 'lru-cache' import { DateTime } from 'luxon' import { Counter } from 'prom-client' import { ONE_HOUR } from '../../config/constants' +import { TopicMessage } from '../../kafka/producer' import { InternalPerson, Person, PropertyUpdateOperation } from '../../types' import { DB } from '../../utils/db/db' import { PostgresUse, TransactionClient } from '../../utils/db/postgres' @@ -301,7 +301,7 @@ export class PersonState { if (Object.keys(update).length > 0) { const [updatedPerson, kafkaMessages] = await this.db.updatePersonDeprecated(person, update) - const kafkaAck = this.db.kafkaProducer.queueMessages({ kafkaMessages, waitForAck: true }) + const kafkaAck = this.db.kafkaProducer.queueMessages(kafkaMessages) return [updatedPerson, kafkaAck] } @@ -682,14 +682,14 @@ export class PersonState { const properties: Properties = { ...otherPerson.properties, ...mergeInto.properties } this.applyEventPropertyUpdates(properties) - const [mergedPerson, kafkaMessages] = await this.handleMergeTransaction( + const [mergedPerson, kafkaAcks] = await this.handleMergeTransaction( mergeInto, otherPerson, olderCreatedAt, // Keep the oldest created_at (i.e. the first time we've seen either person) properties ) - return [mergedPerson, kafkaMessages] + return [mergedPerson, kafkaAcks] } private isMergeAllowed(mergeFrom: InternalPerson): boolean { @@ -712,7 +712,7 @@ export class PersonState { }) .inc() - const [mergedPerson, kafkaMessages]: [InternalPerson, ProducerRecord[]] = await this.db.postgres.transaction( + const [mergedPerson, kafkaMessages]: [InternalPerson, TopicMessage[]] = await this.db.postgres.transaction( PostgresUse.COMMON_WRITE, 'mergePeople', async (tx) => { @@ -768,7 +768,7 @@ export class PersonState { }) .inc() - const kafkaAck = this.db.kafkaProducer.queueMessages({ kafkaMessages, waitForAck: true }) + const kafkaAck = this.db.kafkaProducer.queueMessages(kafkaMessages) return [mergedPerson, kafkaAck] } diff --git a/plugin-server/src/worker/ingestion/process-event.ts b/plugin-server/src/worker/ingestion/process-event.ts index 2162d243d3b77..94fe012faa955 100644 --- a/plugin-server/src/worker/ingestion/process-event.ts +++ b/plugin-server/src/worker/ingestion/process-event.ts @@ -4,6 +4,7 @@ import * as Sentry from '@sentry/node' import { DateTime } from 'luxon' import { Counter, Summary } from 'prom-client' +import { KafkaProducerWrapper } from '../../kafka/producer' import { Element, GroupTypeIndex, @@ -21,7 +22,6 @@ import { import { DB, GroupId } from '../../utils/db/db' import { elementsToString, extractElements } from '../../utils/db/elements-chain' import { MessageSizeTooLarge } from '../../utils/db/error' -import { KafkaProducerWrapper } from '../../utils/db/kafka-producer-wrapper' import { safeClickhouseString, sanitizeEventName, timeoutGuard } from '../../utils/db/utils' import { status } from '../../utils/status' import { castTimestampOrNow } from '../../utils/utils' @@ -264,12 +264,11 @@ export class EventsProcessor { } emitEvent(rawEvent: RawKafkaEvent): Promise { - const ack = this.kafkaProducer + return this.kafkaProducer .produce({ topic: this.pluginsServer.CLICKHOUSE_JSON_EVENTS_KAFKA_TOPIC, key: rawEvent.uuid, value: Buffer.from(JSON.stringify(rawEvent)), - waitForAck: true, }) .catch(async (error) => { // Some messages end up significantly larger than the original @@ -283,8 +282,6 @@ export class EventsProcessor { throw error } }) - - return ack } private async upsertGroup( diff --git a/plugin-server/src/worker/ingestion/utils.ts b/plugin-server/src/worker/ingestion/utils.ts index c6c313d74d459..0375ab05e343e 100644 --- a/plugin-server/src/worker/ingestion/utils.ts +++ b/plugin-server/src/worker/ingestion/utils.ts @@ -1,10 +1,10 @@ import { PluginEvent, ProcessedPluginEvent } from '@posthog/plugin-scaffold' -import { ProducerRecord } from 'kafkajs' import { DateTime } from 'luxon' +import { KafkaProducerWrapper, TopicMessage } from '../../kafka/producer' import { PipelineEvent, TeamId, TimestampFormat } from '../../types' -import { KafkaProducerWrapper } from '../../utils/db/kafka-producer-wrapper' import { safeClickhouseString } from '../../utils/db/utils' +import { status } from '../../utils/status' import { IngestionWarningLimiter } from '../../utils/token-bucket' import { castTimestampOrNow, castTimestampToClickhouseFormat, UUIDT } from '../../utils/utils' import { KAFKA_EVENTS_DEAD_LETTER_QUEUE, KAFKA_INGESTION_WARNINGS } from './../../config/kafka-topics' @@ -20,7 +20,7 @@ export function generateEventDeadLetterQueueMessage( error: unknown, teamId: number, errorLocation = 'plugin_server_ingest_event' -): ProducerRecord { +): TopicMessage { let errorMessage = 'Event ingestion failed. ' if (error instanceof Error) { errorMessage += `Error: ${error.message}` @@ -48,7 +48,7 @@ export function generateEventDeadLetterQueueMessage( team_id: event.team_id || teamId, } - const message = { + return { topic: KAFKA_EVENTS_DEAD_LETTER_QUEUE, messages: [ { @@ -56,7 +56,6 @@ export function generateEventDeadLetterQueueMessage( }, ], } - return message } // These get displayed under Data Management > Ingestion Warnings @@ -79,8 +78,9 @@ export async function captureIngestionWarning( ) { const limiter_key = `${teamId}:${type}:${debounce?.key || ''}` if (!!debounce?.alwaysSend || IngestionWarningLimiter.consume(limiter_key, 1)) { - await kafkaProducer.queueMessage({ - kafkaMessage: { + // TODO: Either here or in follow up change this to an await as we do care. + void kafkaProducer + .queueMessages({ topic: KAFKA_INGESTION_WARNINGS, messages: [ { @@ -93,10 +93,15 @@ export async function captureIngestionWarning( }), }, ], - }, - waitForAck: false, - }) - } else { - return Promise.resolve() + }) + .catch((error) => { + status.warn('⚠️', 'Failed to produce ingestion warning', { + error, + team_id: teamId, + type, + details, + }) + }) } + return Promise.resolve() } diff --git a/plugin-server/src/worker/vm/extensions/posthog.ts b/plugin-server/src/worker/vm/extensions/posthog.ts index 34e9cb2befd1c..7cf98dd81a939 100644 --- a/plugin-server/src/worker/vm/extensions/posthog.ts +++ b/plugin-server/src/worker/vm/extensions/posthog.ts @@ -28,26 +28,23 @@ async function queueEvent(hub: Hub, pluginConfig: PluginConfig, data: InternalDa partitionKeyHash.update(`${data.team_id}:${data.distinct_id}`) const partitionKey = partitionKeyHash.digest('hex') - await hub.kafkaProducer.queueMessage({ - kafkaMessage: { - topic: hub.KAFKA_CONSUMPTION_TOPIC!, - messages: [ - { - key: partitionKey, - value: JSON.stringify({ - distinct_id: data.distinct_id, - ip: '', - site_url: '', - data: JSON.stringify(data), - team_id: pluginConfig.team_id, - now: data.timestamp, - sent_at: data.timestamp, - uuid: data.uuid, - } as RawEventMessage), - }, - ], - }, - waitForAck: true, + await hub.kafkaProducer.queueMessages({ + topic: hub.KAFKA_CONSUMPTION_TOPIC!, + messages: [ + { + key: partitionKey, + value: JSON.stringify({ + distinct_id: data.distinct_id, + ip: '', + site_url: '', + data: JSON.stringify(data), + team_id: pluginConfig.team_id, + now: data.timestamp, + sent_at: data.timestamp, + uuid: data.uuid, + } as RawEventMessage), + }, + ], }) } diff --git a/plugin-server/tests/cdp/cdp-api.test.ts b/plugin-server/tests/cdp/cdp-api.test.ts index 73d54f27a6e44..ef7f3eade2520 100644 --- a/plugin-server/tests/cdp/cdp-api.test.ts +++ b/plugin-server/tests/cdp/cdp-api.test.ts @@ -1,3 +1,5 @@ +import '../helpers/mocks/producer.mock' + import express from 'express' import supertest from 'supertest' @@ -47,19 +49,6 @@ jest.mock('../../src/utils/fetch', () => { } }) -jest.mock('../../src/utils/db/kafka-producer-wrapper', () => { - const mockKafkaProducer = { - producer: { - connect: jest.fn(), - }, - disconnect: jest.fn(), - produce: jest.fn(), - } - return { - KafkaProducerWrapper: jest.fn(() => mockKafkaProducer), - } -}) - const mockFetch: jest.Mock = require('../../src/utils/fetch').trackedFetch jest.setTimeout(1000) diff --git a/plugin-server/tests/cdp/cdp-events-consumer.test.ts b/plugin-server/tests/cdp/cdp-events-consumer.test.ts index db400a56672b3..5294256a2862b 100644 --- a/plugin-server/tests/cdp/cdp-events-consumer.test.ts +++ b/plugin-server/tests/cdp/cdp-events-consumer.test.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line simple-import-sort/imports +import { getParsedQueuedMessages, mockProducer } from '../helpers/mocks/producer.mock' + import { CdpInternalEventsConsumer, CdpProcessedEventsConsumer } from '../../src/cdp/cdp-consumers' import { HogWatcherState } from '../../src/cdp/hog-watcher' import { HogFunctionInvocationGlobals, HogFunctionType } from '../../src/cdp/types' @@ -44,34 +47,32 @@ jest.mock('../../src/utils/fetch', () => { } }) -jest.mock('../../src/utils/db/kafka-producer-wrapper', () => { - const mockKafkaProducer = { - producer: { - connect: jest.fn(), - }, - disconnect: jest.fn(), - produce: jest.fn(() => Promise.resolve()), - } - return { - KafkaProducerWrapper: jest.fn(() => mockKafkaProducer), - } -}) - const mockFetch: jest.Mock = require('../../src/utils/fetch').trackedFetch -const mockProducer = require('../../src/utils/db/kafka-producer-wrapper').KafkaProducerWrapper() - jest.setTimeout(1000) -const decodeKafkaMessage = (message: any): any => { - return { - ...message, - value: JSON.parse(message.value.toString()), - } +type DecodedKafkaMessage = { + topic: string + key?: any + value: Record } -const decodeAllKafkaMessages = (): any[] => { - return mockProducer.produce.mock.calls.map((x) => decodeKafkaMessage(x[0])) +const decodeAllKafkaMessages = (): DecodedKafkaMessage[] => { + const queuedMessages = getParsedQueuedMessages() + + const result: DecodedKafkaMessage[] = [] + + for (const topicMessage of queuedMessages) { + for (const message of topicMessage.messages) { + result.push({ + topic: topicMessage.topic, + key: message.key, + value: message.value ?? {}, + }) + } + } + + return result } /** @@ -98,6 +99,8 @@ describe.each([ beforeEach(async () => { await resetTestDatabase() hub = await createHub() + hub.kafkaProducer = mockProducer + team = await getFirstTeam(hub) processor = new Consumer(hub) @@ -262,7 +265,6 @@ describe.each([ state: expect.any(String), }, key: expect.stringContaining(fnFetchNoFilters.id.toString()), - waitForAck: true, }, ]) }) @@ -314,7 +316,7 @@ describe.each([ const invocations = await processor.processBatch([globals]) expect(invocations).toHaveLength(0) - expect(mockProducer.produce).toHaveBeenCalledTimes(2) + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) expect(decodeAllKafkaMessages()).toMatchObject([ { diff --git a/plugin-server/tests/cdp/cdp-internal-events-consumer.test.ts b/plugin-server/tests/cdp/cdp-internal-events-consumer.test.ts index 995b2eeae2667..81b94cbcb6daf 100644 --- a/plugin-server/tests/cdp/cdp-internal-events-consumer.test.ts +++ b/plugin-server/tests/cdp/cdp-internal-events-consumer.test.ts @@ -1,3 +1,5 @@ +import '../helpers/mocks/producer.mock' + import { CdpInternalEventsConsumer } from '../../src/cdp/cdp-consumers' import { HogFunctionType } from '../../src/cdp/types' import { Hub, Team } from '../../src/types' @@ -24,12 +26,11 @@ describe('CDP Internal Events Consumer', () => { team = await getFirstTeam(hub) processor = new CdpInternalEventsConsumer(hub) - // Speed hack as we don't need all of kafka to be started for this test - await processor.hogFunctionManager.start(processor['hogTypes']) + await processor.start() }) afterEach(async () => { - jest.setTimeout(1000) + await processor.stop() await closeHub(hub) }) diff --git a/plugin-server/tests/cdp/helpers/kafka-observer.ts b/plugin-server/tests/cdp/helpers/kafka-observer.ts index 462c06fc1e137..8bcaf8f8b7cfc 100644 --- a/plugin-server/tests/cdp/helpers/kafka-observer.ts +++ b/plugin-server/tests/cdp/helpers/kafka-observer.ts @@ -18,11 +18,11 @@ export type TestKafkaObserver = { export const createKafkaObserver = async (hub: Hub, topics: string[]): Promise => { const consumer = await createKafkaConsumer({ - ...createRdConnectionConfigFromEnvVars(hub), + ...createRdConnectionConfigFromEnvVars(hub, 'consumer'), 'group.id': `test-group-${new UUIDT().toString()}`, }) - const adminClient = createAdminClient(createRdConnectionConfigFromEnvVars(hub)) + const adminClient = createAdminClient(createRdConnectionConfigFromEnvVars(hub, 'consumer')) await Promise.all(topics.map((topic) => ensureTopicExists(adminClient, topic, 1000))) adminClient.disconnect() diff --git a/plugin-server/tests/helpers/mocks/producer.mock.ts b/plugin-server/tests/helpers/mocks/producer.mock.ts new file mode 100644 index 0000000000000..5bd3b0fe94d84 --- /dev/null +++ b/plugin-server/tests/helpers/mocks/producer.mock.ts @@ -0,0 +1,47 @@ +import { KafkaProducerWrapper, TopicMessage } from '../../../src/kafka/producer' + +export type ParsedTopicMessage = { + topic: string + messages: { + key: string | null + value: Record | null + }[] +} + +jest.mock('../../../src/kafka/producer', () => { + const mockKafkaProducer = { + create: jest.fn(() => mockKafkaProducer), + producer: { + connect: jest.fn(), + }, + disconnect: jest.fn(), + produce: jest.fn(), + queueMessages: jest.fn(() => Promise.resolve()), + } + + const MockKafkaProducer = { + create: jest.fn(() => Promise.resolve(mockKafkaProducer)), + } + return { + KafkaProducerWrapper: MockKafkaProducer, + _producer: mockKafkaProducer, + } +}) + +export const mockProducer = require('../../../src/kafka/producer')._producer as KafkaProducerWrapper + +export const getQueuedMessages = (): TopicMessage[] => { + return jest.mocked(mockProducer).queueMessages.mock.calls.reduce((acc, call) => { + return acc.concat(Array.isArray(call[0]) ? call[0] : [call[0]]) + }, [] as TopicMessage[]) +} + +export const getParsedQueuedMessages = (): ParsedTopicMessage[] => { + return getQueuedMessages().map((topicMessage) => ({ + topic: topicMessage.topic, + messages: topicMessage.messages.map((message) => ({ + key: typeof message.key === 'string' ? message.key : null, + value: message.value ? JSON.parse(message.value.toString()) : null, + })), + })) +} diff --git a/plugin-server/tests/main/db.test.ts b/plugin-server/tests/main/db.test.ts index 5c465aadfbae0..0d7d4c5e118e9 100644 --- a/plugin-server/tests/main/db.test.ts +++ b/plugin-server/tests/main/db.test.ts @@ -351,7 +351,7 @@ describe('DB', () => { describe('updatePerson', () => { it('Clickhouse and Postgres are in sync if multiple updates concurrently', async () => { - jest.spyOn(db.kafkaProducer!, 'queueMessage') + jest.spyOn(db.kafkaProducer!, 'queueMessages') const team = await getFirstTeam(hub) const uuid = new UUIDT().toString() const distinctId = 'distinct_id1' @@ -364,10 +364,7 @@ describe('DB', () => { const updateTs = DateTime.fromISO('2000-04-04T11:42:06.502Z').toUTC() const update = { created_at: updateTs } const [updatedPerson, kafkaMessages] = await db.updatePersonDeprecated(personProvided, update) - await hub.db.kafkaProducer.queueMessages({ - kafkaMessages, - waitForAck: true, - }) + await hub.db.kafkaProducer.queueMessages(kafkaMessages) // verify we have the correct update in Postgres db const personDbAfter = await fetchPersonByPersonId(personDbBefore.team_id, personDbBefore.id) @@ -380,10 +377,9 @@ describe('DB', () => { expect(updatedPerson.properties).toEqual({ c: 'aaa' }) // verify correct Kafka message was sent - expect(db.kafkaProducer!.queueMessage).toHaveBeenLastCalledWith({ - kafkaMessage: generateKafkaPersonUpdateMessage(updatedPerson), - waitForAck: true, - }) + expect(db.kafkaProducer!.queueMessages).toHaveBeenLastCalledWith([ + generateKafkaPersonUpdateMessage(updatedPerson), + ]) }) }) @@ -428,15 +424,12 @@ describe('DB', () => { const [_p, updatePersonKafkaMessages] = await db.updatePersonDeprecated(person, { properties: { foo: 'bar' }, }) - await hub.db.kafkaProducer.queueMessages({ - kafkaMessages: updatePersonKafkaMessages, - waitForAck: true, - }) + await hub.db.kafkaProducer.queueMessages(updatePersonKafkaMessages) await db.kafkaProducer.flush() await delayUntilEventIngested(fetchPersonsRows, 2) const kafkaMessages = await db.deletePerson(person) - await db.kafkaProducer.queueMessages({ kafkaMessages, waitForAck: true }) + await db.kafkaProducer.queueMessages(kafkaMessages) await db.kafkaProducer.flush() const persons = await delayUntilEventIngested(fetchPersonsRows, 3) @@ -533,7 +526,7 @@ describe('DB', () => { 'group_key', { prop: 'val' }, TIMESTAMP, - { prop: TIMESTAMP.toISO() }, + { prop: TIMESTAMP.toISO()! }, { prop: PropertyUpdateOperation.Set }, 1 ) diff --git a/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-consumer.test.ts b/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-consumer.test.ts index ef43415544733..e13ed3d040e4e 100644 --- a/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-consumer.test.ts +++ b/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-consumer.test.ts @@ -101,7 +101,6 @@ describe('eachBatchParallelIngestion with overflow reroute', () => { topic: KAFKA_EVENTS_PLUGIN_INGESTION_OVERFLOW, value: message.value, key: null, - waitForAck: true, }) // Event is not processed here @@ -126,7 +125,6 @@ describe('eachBatchParallelIngestion with overflow reroute', () => { topic: KAFKA_EVENTS_PLUGIN_INGESTION_OVERFLOW, value: message.value, key: overflowMode === IngestionOverflowMode.Reroute ? message.key : null, - waitForAck: true, }) } ) diff --git a/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-overflow-consumer.test.ts b/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-overflow-consumer.test.ts index e0f46c4a39d31..7ffcffc2ea44a 100644 --- a/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-overflow-consumer.test.ts +++ b/plugin-server/tests/main/ingestion-queues/analytics-events-ingestion-overflow-consumer.test.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line simple-import-sort/imports +import { getParsedQueuedMessages, mockProducer } from '../../helpers/mocks/producer.mock' + import { Settings } from 'luxon' import { buildStringMatcher } from '../../../src/config/config' @@ -49,7 +52,6 @@ const captureEndpointEvent2 = { describe('eachBatchParallelIngestion with overflow consume', () => { let queue: any - let mockQueueMessage: jest.Mock function createBatchWithMultipleEventsWithKeys(events: any[], timestamp?: any): any { return events.map((event) => ({ @@ -64,21 +66,16 @@ describe('eachBatchParallelIngestion with overflow consume', () => { // luxon datetime lets you specify a fixed "now" Settings.now = () => new Date(2018, 4, 25).valueOf() - mockQueueMessage = jest.fn() queue = { bufferSleep: jest.fn(), pluginsServer: { INGESTION_CONCURRENCY: 4, - kafkaProducer: { - queueMessage: mockQueueMessage, - }, + kafkaProducer: mockProducer, teamManager: { getTeamForEvent: jest.fn(), }, db: { - kafkaProducer: { - queueMessage: mockQueueMessage, - }, + kafkaProducer: mockProducer, }, }, } @@ -96,12 +93,14 @@ describe('eachBatchParallelIngestion with overflow consume', () => { expect(queue.pluginsServer.teamManager.getTeamForEvent).toHaveBeenCalledTimes(1) expect(consume).toHaveBeenCalledWith('1:ingestion_capacity_overflow:id', 1) - expect(mockQueueMessage).toHaveBeenCalledWith({ - kafkaMessage: { + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + expect(getParsedQueuedMessages()).toEqual([ + { topic: 'clickhouse_ingestion_warnings_test', messages: [ { - value: JSON.stringify({ + key: null, + value: { team_id: 1, type: 'ingestion_capacity_overflow', source: 'plugin-server', @@ -109,12 +108,11 @@ describe('eachBatchParallelIngestion with overflow consume', () => { overflowDistinctId: 'id', }), timestamp: castTimestampOrNow(null, TimestampFormat.ClickHouse), - }), + }, }, ], }, - waitForAck: false, - }) + ]) // Event is processed expect(runEventPipeline).toHaveBeenCalled() @@ -132,7 +130,7 @@ describe('eachBatchParallelIngestion with overflow consume', () => { await eachBatchParallelIngestion(tokenBlockList, batch, queue, mode) expect(consume).toHaveBeenCalledWith('1:ingestion_capacity_overflow:id', 1) - expect(queue.pluginsServer.kafkaProducer.queueMessage).not.toHaveBeenCalled() + expect(mockProducer.queueMessages).not.toHaveBeenCalled() // Event is processed expect(runEventPipeline).toHaveBeenCalled() @@ -153,7 +151,7 @@ describe('eachBatchParallelIngestion with overflow consume', () => { const tokenBlockList = buildStringMatcher('mytoken,more_token', false) await eachBatchParallelIngestion(tokenBlockList, batch, queue, mode) - expect(queue.pluginsServer.kafkaProducer.queueMessage).not.toHaveBeenCalled() + expect(mockProducer.queueMessages).not.toHaveBeenCalled() // captureEndpointEvent2 is processed, captureEndpointEvent1 are dropped expect(runEventPipeline).toHaveBeenCalledTimes(1) diff --git a/plugin-server/tests/main/ingestion-queues/each-batch.test.ts b/plugin-server/tests/main/ingestion-queues/each-batch.test.ts index 0ec4979207e30..6382aae230c40 100644 --- a/plugin-server/tests/main/ingestion-queues/each-batch.test.ts +++ b/plugin-server/tests/main/ingestion-queues/each-batch.test.ts @@ -137,7 +137,7 @@ describe('eachBatchX', () => { TASKS_PER_WORKER: 10, INGESTION_CONCURRENCY: 4, kafkaProducer: { - queueMessage: jest.fn(), + queueMessages: jest.fn(() => Promise.resolve()), }, pluginConfigsPerTeam: new Map(), }, diff --git a/plugin-server/tests/main/ingestion-queues/session-recording/services/console-log-ingester.test.ts b/plugin-server/tests/main/ingestion-queues/session-recording/services/console-log-ingester.test.ts index 6778a4933cad7..37abe0207c82e 100644 --- a/plugin-server/tests/main/ingestion-queues/session-recording/services/console-log-ingester.test.ts +++ b/plugin-server/tests/main/ingestion-queues/session-recording/services/console-log-ingester.test.ts @@ -1,13 +1,11 @@ -import { HighLevelProducer } from 'node-rdkafka' - -import { produce } from '../../../../../src/kafka/producer' import { ConsoleLogsIngester } from '../../../../../src/main/ingestion-queues/session-recording/services/console-logs-ingester' import { OffsetHighWaterMarker } from '../../../../../src/main/ingestion-queues/session-recording/services/offset-high-water-marker' import { IncomingRecordingMessage } from '../../../../../src/main/ingestion-queues/session-recording/types' import { status } from '../../../../../src/utils/status' jest.mock('../../../../../src/utils/status') -jest.mock('../../../../../src/kafka/producer') + +import { getParsedQueuedMessages, mockProducer } from '../../../../helpers/mocks/producer.mock' const makeIncomingMessage = ( data: Record[], @@ -34,18 +32,10 @@ const makeIncomingMessage = ( describe('console log ingester', () => { let consoleLogIngester: ConsoleLogsIngester - const mockProducer: jest.Mock = jest.fn() beforeEach(() => { - mockProducer.mockClear() - mockProducer['connect'] = jest.fn() - mockProducer['isConnected'] = () => true - const mockedHighWaterMarker = { isBelowHighWaterMark: jest.fn() } as unknown as OffsetHighWaterMarker - consoleLogIngester = new ConsoleLogsIngester( - mockProducer as unknown as HighLevelProducer, - mockedHighWaterMarker - ) + consoleLogIngester = new ConsoleLogsIngester(mockProducer, mockedHighWaterMarker) }) describe('when enabled on team', () => { test('it truncates large console logs', async () => { @@ -61,14 +51,14 @@ describe('console log ingester', () => { ) ) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce).mock.calls).toEqual([ - [ - { - key: '', - producer: mockProducer, - topic: 'log_entries_test', - value: Buffer.from( - JSON.stringify({ + + expect(getParsedQueuedMessages()).toEqual([ + { + topic: 'log_entries_test', + messages: [ + { + key: '', + value: { team_id: 0, message: 'a'.repeat(2999), level: 'info', @@ -76,11 +66,10 @@ describe('console log ingester', () => { log_source_id: '', instance_id: null, timestamp: '1970-01-01 00:00:00.000', - }) - ), - waitForAck: true, - }, - ], + }, + }, + ], + }, ]) }) @@ -105,15 +94,14 @@ describe('console log ingester', () => { ) ) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce)).toHaveBeenCalledTimes(2) - expect(jest.mocked(produce).mock.calls).toEqual([ - [ - { - key: '', - producer: mockProducer, - topic: 'log_entries_test', - value: Buffer.from( - JSON.stringify({ + expect(jest.mocked(mockProducer.queueMessages)).toHaveBeenCalledTimes(1) + expect(getParsedQueuedMessages()).toEqual([ + { + topic: 'log_entries_test', + messages: [ + { + key: '', + value: { team_id: 0, message: 'aaaaa', level: 'info', @@ -121,18 +109,11 @@ describe('console log ingester', () => { log_source_id: '', instance_id: null, timestamp: '1970-01-01 00:00:00.000', - }) - ), - waitForAck: true, - }, - ], - [ - { - key: '', - producer: mockProducer, - topic: 'log_entries_test', - value: Buffer.from( - JSON.stringify({ + }, + }, + { + key: '', + value: { team_id: 0, message: 'ccccc', level: 'info', @@ -140,11 +121,10 @@ describe('console log ingester', () => { log_source_id: '', instance_id: null, timestamp: '1970-01-01 00:00:00.000', - }) - ), - waitForAck: true, - }, - ], + }, + }, + ], + }, ]) }) @@ -165,14 +145,13 @@ describe('console log ingester', () => { ) ) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce).mock.calls).toEqual([ - [ - { - key: '', - producer: mockProducer, - topic: 'log_entries_test', - value: Buffer.from( - JSON.stringify({ + expect(getParsedQueuedMessages()).toEqual([ + { + topic: 'log_entries_test', + messages: [ + { + key: '', + value: { team_id: 0, message: 'aaaaa', level: 'info', @@ -180,11 +159,10 @@ describe('console log ingester', () => { log_source_id: '', instance_id: null, timestamp: '1970-01-01 00:00:00.000', - }) - ), - waitForAck: true, - }, - ], + }, + }, + ], + }, ]) }) }) @@ -192,12 +170,12 @@ describe('console log ingester', () => { describe('when disabled on team', () => { test('it drops console logs', async () => { await consoleLogIngester.consume(makeIncomingMessage([{ plugin: 'rrweb/console@1' }], false)) - expect(jest.mocked(produce)).not.toHaveBeenCalled() + expect(jest.mocked(mockProducer.queueMessages)).not.toHaveBeenCalled() }) test('it does not drop events with no console logs', async () => { await consoleLogIngester.consume(makeIncomingMessage([{ plugin: 'some-other-plugin' }], false)) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce)).not.toHaveBeenCalled() + expect(jest.mocked(mockProducer.queueMessages)).not.toHaveBeenCalled() }) }) }) diff --git a/plugin-server/tests/main/ingestion-queues/session-recording/services/overflow-manager.test.ts b/plugin-server/tests/main/ingestion-queues/session-recording/services/overflow-manager.test.ts index 63b507a2dff03..a9d5f2ebccaa0 100644 --- a/plugin-server/tests/main/ingestion-queues/session-recording/services/overflow-manager.test.ts +++ b/plugin-server/tests/main/ingestion-queues/session-recording/services/overflow-manager.test.ts @@ -5,7 +5,8 @@ import { Hub } from '../../../../../src/types' import { closeHub, createHub } from '../../../../../src/utils/db/hub' jest.mock('../../../../../src/utils/status') -jest.mock('../../../../../src/kafka/producer') + +import '../../../../helpers/mocks/producer.mock' const CAPTURE_OVERFLOW_REDIS_KEY = '@posthog/capture-overflow/replay' diff --git a/plugin-server/tests/main/ingestion-queues/session-recording/services/replay-events-ingester.test.ts b/plugin-server/tests/main/ingestion-queues/session-recording/services/replay-events-ingester.test.ts index e9e94583bc4c6..91cbd19061cd0 100644 --- a/plugin-server/tests/main/ingestion-queues/session-recording/services/replay-events-ingester.test.ts +++ b/plugin-server/tests/main/ingestion-queues/session-recording/services/replay-events-ingester.test.ts @@ -1,7 +1,5 @@ import { DateTime } from 'luxon' -import { HighLevelProducer } from 'node-rdkafka' -import { produce } from '../../../../../src/kafka/producer' import { OffsetHighWaterMarker } from '../../../../../src/main/ingestion-queues/session-recording/services/offset-high-water-marker' import { ReplayEventsIngester } from '../../../../../src/main/ingestion-queues/session-recording/services/replay-events-ingester' import { IncomingRecordingMessage } from '../../../../../src/main/ingestion-queues/session-recording/types' @@ -10,7 +8,8 @@ import { status } from '../../../../../src/utils/status' import { castTimestampOrNow } from '../../../../../src/utils/utils' jest.mock('../../../../../src/utils/status') -jest.mock('../../../../../src/kafka/producer') + +import { getParsedQueuedMessages, mockProducer } from '../../../../helpers/mocks/producer.mock' const makeIncomingMessage = ( source: string | null, @@ -41,15 +40,10 @@ const makeIncomingMessage = ( describe('replay events ingester', () => { let ingester: ReplayEventsIngester - const mockProducer: jest.Mock = jest.fn() beforeEach(() => { - mockProducer.mockClear() - mockProducer['connect'] = jest.fn() - mockProducer['isConnected'] = () => true - const mockedHighWaterMarker = { isBelowHighWaterMark: jest.fn() } as unknown as OffsetHighWaterMarker - ingester = new ReplayEventsIngester(mockProducer as unknown as HighLevelProducer, mockedHighWaterMarker) + ingester = new ReplayEventsIngester(mockProducer, mockedHighWaterMarker) }) test('does not ingest messages from a month in the future', async () => { @@ -60,13 +54,11 @@ describe('replay events ingester', () => { await ingester.consume(makeIncomingMessage("mickey's fun house", twoMonthsFromNow.toMillis())) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce).mock.calls).toHaveLength(1) - expect(jest.mocked(produce).mock.calls[0]).toHaveLength(1) - const call = jest.mocked(produce).mock.calls[0][0] - - expect(call.topic).toEqual('clickhouse_ingestion_warnings_test') - // call.value is a Buffer convert it to a string - const value = call.value ? JSON.parse(call.value.toString()) : null + expect(jest.mocked(mockProducer.queueMessages)).toHaveBeenCalledTimes(1) + const topicMessages = getParsedQueuedMessages() + expect(topicMessages).toHaveLength(1) + expect(topicMessages[0].topic).toEqual('clickhouse_ingestion_warnings_test') + const value = topicMessages[0].messages[0].value! const expectedTimestamp = castTimestampOrNow(twoMonthsFromNow, TimestampFormat.ClickHouse) expect(value.source).toEqual('plugin-server') @@ -87,12 +79,13 @@ describe('replay events ingester', () => { await ingester.consume(makeIncomingMessage("mickey's fun house", ts)) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce).mock.calls).toHaveLength(1) - expect(jest.mocked(produce).mock.calls[0]).toHaveLength(1) - const call = jest.mocked(produce).mock.calls[0][0] - expect(call.topic).toEqual('clickhouse_session_replay_events_test') + expect(jest.mocked(mockProducer.queueMessages).mock.calls).toHaveLength(1) + expect(jest.mocked(mockProducer.queueMessages).mock.calls[0]).toHaveLength(1) + const topicMessages = getParsedQueuedMessages() + expect(topicMessages).toHaveLength(1) + expect(topicMessages[0].topic).toEqual('clickhouse_session_replay_events_test') // call.value is a Buffer convert it to a string - const value = call.value ? JSON.parse(call.value.toString()) : null + const value = topicMessages[0].messages[0].value! expect(value).toEqual({ active_milliseconds: 0, click_count: 0, @@ -121,12 +114,11 @@ describe('replay events ingester', () => { await ingester.consume(makeIncomingMessage(null, ts)) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce).mock.calls).toHaveLength(1) - expect(jest.mocked(produce).mock.calls[0]).toHaveLength(1) - const call = jest.mocked(produce).mock.calls[0][0] - expect(call.topic).toEqual('clickhouse_session_replay_events_test') - // call.value is a Buffer convert it to a string - const value = call.value ? JSON.parse(call.value.toString()) : null + expect(jest.mocked(mockProducer.queueMessages).mock.calls).toHaveLength(1) + const topicMessages = getParsedQueuedMessages() + expect(topicMessages).toHaveLength(1) + expect(topicMessages[0].topic).toEqual('clickhouse_session_replay_events_test') + const value = topicMessages[0].messages[0].value! expect(value).toEqual({ active_milliseconds: 0, click_count: 0, @@ -164,12 +156,11 @@ describe('replay events ingester', () => { ) expect(jest.mocked(status.debug).mock.calls).toEqual([]) - expect(jest.mocked(produce).mock.calls).toHaveLength(1) - expect(jest.mocked(produce).mock.calls[0]).toHaveLength(1) - const call = jest.mocked(produce).mock.calls[0][0] - expect(call.topic).toEqual('clickhouse_session_replay_events_test') - // call.value is a Buffer convert it to a string - const value = call.value ? JSON.parse(call.value.toString()) : null + expect(jest.mocked(mockProducer.queueMessages)).toHaveBeenCalledTimes(1) + const topicMessages = getParsedQueuedMessages() + expect(topicMessages).toHaveLength(1) + expect(topicMessages[0].topic).toEqual('clickhouse_session_replay_events_test') + const value = topicMessages[0].messages[0].value! expect(value).toEqual({ active_milliseconds: 0, click_count: 0, diff --git a/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts b/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts index 6678c28d92a3e..f40002b695d4b 100644 --- a/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts +++ b/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts @@ -1,6 +1,7 @@ import { Settings } from 'luxon' import { Message, MessageHeader } from 'node-rdkafka' +import { KafkaProducerWrapper } from '../../../../src/kafka/producer' import { allSettledWithConcurrency, getLagMultiplier, @@ -9,7 +10,6 @@ import { parseKafkaBatch, parseKafkaMessage, } from '../../../../src/main/ingestion-queues/session-recording/utils' -import { KafkaProducerWrapper } from '../../../../src/utils/db/kafka-producer-wrapper' import { UUIDT } from '../../../../src/utils/utils' describe('session-recording utils', () => { @@ -69,7 +69,7 @@ describe('session-recording utils', () => { let fakeProducer: KafkaProducerWrapper beforeEach(() => { Settings.now = () => new Date('2023-08-30T19:15:54.887316+00:00').getTime() - fakeProducer = { queueMessage: jest.fn() } as unknown as KafkaProducerWrapper + fakeProducer = { queueMessages: jest.fn(() => Promise.resolve()) } as unknown as KafkaProducerWrapper }) it('can parse a message correctly', async () => { @@ -212,16 +212,13 @@ describe('session-recording utils', () => { [ [ { - kafkaMessage: { - messages: [ - expectedIngestionWarningMessage({ - libVersion: '1.74.0', - parsedVersion: { major: 1, minor: 74 }, - }), - ], - topic: 'clickhouse_ingestion_warnings_test', - }, - waitForAck: false, + messages: [ + expectedIngestionWarningMessage({ + libVersion: '1.74.0', + parsedVersion: { major: 1, minor: 74 }, + }), + ], + topic: 'clickhouse_ingestion_warnings_test', }, ], ], @@ -232,16 +229,13 @@ describe('session-recording utils', () => { [ [ { - kafkaMessage: { - messages: [ - expectedIngestionWarningMessage({ - libVersion: '1.32.0', - parsedVersion: { major: 1, minor: 32 }, - }), - ], - topic: 'clickhouse_ingestion_warnings_test', - }, - waitForAck: false, + messages: [ + expectedIngestionWarningMessage({ + libVersion: '1.32.0', + parsedVersion: { major: 1, minor: 32 }, + }), + ], + topic: 'clickhouse_ingestion_warnings_test', }, ], ], @@ -254,7 +248,7 @@ describe('session-recording utils', () => { () => Promise.resolve({ teamId: 1, consoleLogIngestionEnabled: false }), fakeProducer ) - expect(jest.mocked(fakeProducer.queueMessage).mock.calls).toEqual(expectedCalls) + expect(jest.mocked(fakeProducer.queueMessages).mock.calls).toEqual(expectedCalls) }) describe('team token must be in header *not* body', () => { @@ -349,7 +343,7 @@ describe('session-recording utils', () => { let fakeProducer: KafkaProducerWrapper beforeEach(() => { Settings.now = () => new Date('2023-08-30T19:15:54.887316+00:00').getTime() - fakeProducer = { queueMessage: jest.fn() } as unknown as KafkaProducerWrapper + fakeProducer = { queueMessages: jest.fn(() => Promise.resolve()) } as unknown as KafkaProducerWrapper }) it('can parse and reduce a batch of messages', async () => { diff --git a/plugin-server/tests/main/jobs/schedule.test.ts b/plugin-server/tests/main/jobs/schedule.test.ts index b6b52c892f23d..da2fb2bbede8e 100644 --- a/plugin-server/tests/main/jobs/schedule.test.ts +++ b/plugin-server/tests/main/jobs/schedule.test.ts @@ -1,7 +1,7 @@ import { KAFKA_SCHEDULED_TASKS } from '../../../src/config/kafka-topics' +import { KafkaProducerWrapper } from '../../../src/kafka/producer' import { runScheduledTasks } from '../../../src/main/graphile-worker/schedule' import { Hub } from '../../../src/types' -import { KafkaProducerWrapper } from '../../../src/utils/db/kafka-producer-wrapper' import { UUID } from '../../../src/utils/utils' const mockHub: Hub = { @@ -27,7 +27,7 @@ describe('Graphile Worker schedule', () => { runEveryDay: [7, 8, 9], }, kafkaProducer: { - queueMessage: jest.fn(), + queueMessages: jest.fn(() => Promise.resolve()), } as unknown as KafkaProducerWrapper, USE_KAFKA_FOR_SCHEDULED_TASKS: true, } @@ -36,148 +36,121 @@ describe('Graphile Worker schedule', () => { job: { run_at: new Date() }, } as any) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(1, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '1', - value: JSON.stringify({ - taskType: 'runEveryMinute', - pluginConfigId: 1, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(1, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '1', + value: JSON.stringify({ + taskType: 'runEveryMinute', + pluginConfigId: 1, + }), + }, + ], }) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(2, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '2', - value: JSON.stringify({ - taskType: 'runEveryMinute', - pluginConfigId: 2, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(2, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '2', + value: JSON.stringify({ + taskType: 'runEveryMinute', + pluginConfigId: 2, + }), + }, + ], }) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(3, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '3', - value: JSON.stringify({ - taskType: 'runEveryMinute', - pluginConfigId: 3, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(3, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '3', + value: JSON.stringify({ + taskType: 'runEveryMinute', + pluginConfigId: 3, + }), + }, + ], }) await runScheduledTasks(mockHubWithPluginSchedule, mockPiscina as any, 'runEveryHour', { job: { run_at: new Date() }, } as any) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(4, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '4', - value: JSON.stringify({ - taskType: 'runEveryHour', - pluginConfigId: 4, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(4, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '4', + value: JSON.stringify({ + taskType: 'runEveryHour', + pluginConfigId: 4, + }), + }, + ], }) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(5, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '5', - value: JSON.stringify({ - taskType: 'runEveryHour', - pluginConfigId: 5, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(5, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '5', + value: JSON.stringify({ + taskType: 'runEveryHour', + pluginConfigId: 5, + }), + }, + ], }) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(6, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '6', - value: JSON.stringify({ - taskType: 'runEveryHour', - pluginConfigId: 6, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(6, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '6', + value: JSON.stringify({ + taskType: 'runEveryHour', + pluginConfigId: 6, + }), + }, + ], }) await runScheduledTasks(mockHubWithPluginSchedule, mockPiscina as any, 'runEveryDay', { job: { run_at: new Date() }, } as any) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(7, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '7', - value: JSON.stringify({ - taskType: 'runEveryDay', - pluginConfigId: 7, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(7, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '7', + value: JSON.stringify({ + taskType: 'runEveryDay', + pluginConfigId: 7, + }), + }, + ], }) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(8, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '8', - value: JSON.stringify({ - taskType: 'runEveryDay', - pluginConfigId: 8, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(8, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '8', + value: JSON.stringify({ + taskType: 'runEveryDay', + pluginConfigId: 8, + }), + }, + ], }) - expect(mockHubWithPluginSchedule.kafkaProducer.queueMessage).toHaveBeenNthCalledWith(9, { - kafkaMessage: { - topic: KAFKA_SCHEDULED_TASKS, - messages: [ - { - key: '9', - value: JSON.stringify({ - taskType: 'runEveryDay', - pluginConfigId: 9, - }), - }, - ], - }, - waitForAck: true, + expect(mockHubWithPluginSchedule.kafkaProducer.queueMessages).toHaveBeenNthCalledWith(9, { + topic: KAFKA_SCHEDULED_TASKS, + messages: [ + { + key: '9', + value: JSON.stringify({ + taskType: 'runEveryDay', + pluginConfigId: 9, + }), + }, + ], }) }) }) diff --git a/plugin-server/tests/main/process-event.test.ts b/plugin-server/tests/main/process-event.test.ts index ff9fbcb9d9823..e33da08a760d7 100644 --- a/plugin-server/tests/main/process-event.test.ts +++ b/plugin-server/tests/main/process-event.test.ts @@ -199,10 +199,7 @@ test('merge people', async () => { created_at: DateTime.fromISO('2019-07-01T00:00:00Z'), }) - await hub.db.kafkaProducer.queueMessages({ - kafkaMessages: [...kafkaMessages0, ...kafkaMessages1], - waitForAck: true, - }) + await hub.db.kafkaProducer.queueMessages([...kafkaMessages0, ...kafkaMessages1]) await processEvent( 'person_1', diff --git a/plugin-server/tests/utils/kafka-producer-wrapper.test.ts b/plugin-server/tests/utils/kafka-producer-wrapper.test.ts deleted file mode 100644 index 148ccd4ca811b..0000000000000 --- a/plugin-server/tests/utils/kafka-producer-wrapper.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { convertKafkaJSHeadersToRdKafkaHeaders } from '../../src/utils/db/kafka-producer-wrapper' - -test('can convert from KafkaJS headers to rdkafka headers', () => { - expect(convertKafkaJSHeadersToRdKafkaHeaders()).toEqual(undefined) - expect(convertKafkaJSHeadersToRdKafkaHeaders({})).toEqual([]) - expect(convertKafkaJSHeadersToRdKafkaHeaders({ foo: 'bar' })).toEqual([{ foo: Buffer.from('bar') }]) - expect(convertKafkaJSHeadersToRdKafkaHeaders({ foo: ['bar', 'baz'] })).toEqual([ - { foo: Buffer.from('bar') }, - { foo: Buffer.from('baz') }, - ]) - expect(convertKafkaJSHeadersToRdKafkaHeaders({ foo: ['bar', 'baz'], qux: 'quux' })).toEqual([ - { foo: Buffer.from('bar') }, - { foo: Buffer.from('baz') }, - { qux: Buffer.from('quux') }, - ]) - expect(convertKafkaJSHeadersToRdKafkaHeaders({ foo: undefined })).toEqual([]) - - // We should be able to use strings and Buffers interchangeably - expect(convertKafkaJSHeadersToRdKafkaHeaders({ foo: Buffer.from('bar') })).toEqual([{ foo: Buffer.from('bar') }]) - expect(convertKafkaJSHeadersToRdKafkaHeaders({ foo: 'bar' })).toEqual([{ foo: Buffer.from('bar') }]) - - // We should be able to use strings and Buffers interchangeably in arrays - expect(convertKafkaJSHeadersToRdKafkaHeaders({ foo: [Buffer.from('bar'), 'baz'] })).toEqual([ - { foo: Buffer.from('bar') }, - { foo: Buffer.from('baz') }, - ]) -}) diff --git a/plugin-server/tests/worker/console.test.ts b/plugin-server/tests/worker/console.test.ts index 0237eaf682b2a..7ebd551427c49 100644 --- a/plugin-server/tests/worker/console.test.ts +++ b/plugin-server/tests/worker/console.test.ts @@ -1,5 +1,7 @@ -import { ConsoleExtension } from '@posthog/plugin-scaffold' +// eslint-disable-next-line simple-import-sort/imports +import { getParsedQueuedMessages, mockProducer } from '../helpers/mocks/producer.mock' +import { ConsoleExtension } from '@posthog/plugin-scaffold' import { KAFKA_PLUGIN_LOG_ENTRIES } from '../../src/config/kafka-topics' import { Hub, PluginLogEntrySource, PluginLogEntryType } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' @@ -8,7 +10,6 @@ import { pluginConfig39 } from '../../tests/helpers/plugins' jest.setTimeout(60000) // 60 sec timeout jest.mock('../../src/utils/status') -jest.mock('../../src/utils/db/kafka-producer-wrapper') describe('console extension', () => { let hub: Hub @@ -35,27 +36,29 @@ describe('console extension', () => { testCases.forEach(([description, args, expectedFinalMessage]) => { it(`leaves a well-formed ${description} entry in the database`, async () => { - const queueSingleJsonMessageSpy = jest.spyOn(hub.kafkaProducer, 'queueSingleJsonMessage') const console = createConsole(hub, pluginConfig39) await (console[typeMethod](...args) as unknown as Promise) - expect(queueSingleJsonMessageSpy).toHaveBeenCalledTimes(1) - expect(queueSingleJsonMessageSpy).toHaveBeenCalledWith({ + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + expect(getParsedQueuedMessages()[0]).toEqual({ topic: KAFKA_PLUGIN_LOG_ENTRIES, - key: expect.any(String), - object: { - source: PluginLogEntrySource.Console, - type, - id: expect.any(String), - team_id: pluginConfig39.team_id, - plugin_id: pluginConfig39.plugin_id, - plugin_config_id: pluginConfig39.id, - timestamp: expect.any(String), - message: expectedFinalMessage, - instance_id: hub.instanceId.toString(), - }, - waitForAck: false, + messages: [ + { + key: expect.any(String), + value: { + source: PluginLogEntrySource.Console, + type, + id: expect.any(String), + team_id: pluginConfig39.team_id, + plugin_id: pluginConfig39.plugin_id, + plugin_config_id: pluginConfig39.id, + timestamp: expect.any(String), + message: expectedFinalMessage, + instance_id: hub.instanceId.toString(), + }, + }, + ], }) }) }) diff --git a/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap b/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap index 198c666d8cebb..10cf219b7e43b 100644 --- a/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap +++ b/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap @@ -1,18 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AppMetrics() flush() flushes queued messages 1`] = ` -[ - [ - { - "kafkaMessage": { - "messages": [ - { - "value": "{"timestamp":"1970-01-01 00:16:40.000","team_id":2,"plugin_config_id":2,"job_id":"000-000","category":"processEvent","successes":1,"successes_on_retry":0,"failures":0}", - }, - ], - "topic": "clickhouse_app_metrics_test", - }, - "waitForAck": true, +Array [ + Array [ + Object { + "messages": Array [ + Object { + "value": "{\\"timestamp\\":\\"1970-01-01 00:16:40.000\\",\\"team_id\\":2,\\"plugin_config_id\\":2,\\"job_id\\":\\"000-000\\",\\"category\\":\\"processEvent\\",\\"successes\\":1,\\"successes_on_retry\\":0,\\"failures\\":0}", + }, + ], + "topic": "clickhouse_app_metrics_test", }, ], ] diff --git a/plugin-server/tests/worker/ingestion/app-metrics.test.ts b/plugin-server/tests/worker/ingestion/app-metrics.test.ts index bf2642d24b1aa..469449e2a60e2 100644 --- a/plugin-server/tests/worker/ingestion/app-metrics.test.ts +++ b/plugin-server/tests/worker/ingestion/app-metrics.test.ts @@ -1,6 +1,6 @@ +import { KafkaProducerWrapper } from '../../../src/kafka/producer' import { Hub } from '../../../src/types' import { closeHub, createHub } from '../../../src/utils/db/hub' -import { KafkaProducerWrapper } from '../../../src/utils/db/kafka-producer-wrapper' import { UUIDT } from '../../../src/utils/utils' import { AppMetricIdentifier, AppMetrics } from '../../../src/worker/ingestion/app-metrics' import { delayUntilEventIngested, resetTestDatabaseClickhouse } from '../../helpers/clickhouse' @@ -25,9 +25,8 @@ describe('AppMetrics()', () => { beforeEach(() => { kafkaProducer = { producer: jest.fn(), - waitForAck: jest.fn(), produce: jest.fn(), - queueMessage: jest.fn(), + queueMessages: jest.fn(() => Promise.resolve()), flush: jest.fn(), disconnect: jest.fn(), } as unknown as KafkaProducerWrapper @@ -258,7 +257,7 @@ describe('AppMetrics()', () => { describe('flush()', () => { it('flushes queued messages', async () => { - const spy = jest.spyOn(kafkaProducer, 'queueMessage') + const spy = jest.spyOn(kafkaProducer, 'queueMessages') await appMetrics.queueMetric({ ...metric, jobId: '000-000', successes: 1 }, timestamp) await appMetrics.flush() @@ -269,7 +268,7 @@ describe('AppMetrics()', () => { it('does nothing if nothing queued', async () => { await appMetrics.flush() - expect(kafkaProducer.queueMessage).not.toHaveBeenCalled() + expect(kafkaProducer.queueMessages).not.toHaveBeenCalled() }) }) @@ -282,7 +281,7 @@ describe('AppMetrics()', () => { APP_METRICS_FLUSH_MAX_QUEUE_SIZE: 5, }) // doesn't flush again on the next call, i.e. flust metrics were reset - jest.spyOn(hub.kafkaProducer, 'queueMessage').mockReturnValue(Promise.resolve()) + jest.spyOn(hub.kafkaProducer, 'queueMessages').mockReturnValue(Promise.resolve()) }) afterEach(async () => { await closeHub(hub) @@ -293,7 +292,7 @@ describe('AppMetrics()', () => { beforeEach(async () => { await resetTestDatabaseClickhouse() - jest.mocked(hub.kafkaProducer.queueMessage).mockRestore() + jest.mocked(hub.kafkaProducer.queueMessages).mockRestore() }) it('can read its own writes', async () => { diff --git a/plugin-server/tests/worker/ingestion/person-state.test.ts b/plugin-server/tests/worker/ingestion/person-state.test.ts index fcf548ec0b199..565353633f60c 100644 --- a/plugin-server/tests/worker/ingestion/person-state.test.ts +++ b/plugin-server/tests/worker/ingestion/person-state.test.ts @@ -12,7 +12,7 @@ import { uuidFromDistinctId } from '../../../src/worker/ingestion/person-uuid' import { delayUntilEventIngested } from '../../helpers/clickhouse' import { createOrganization, createTeam, fetchPostgresPersons, insertRow } from '../../helpers/sql' -jest.setTimeout(5000) // 5 sec timeout +jest.setTimeout(30000) // 5 sec timeout const timestamp = DateTime.fromISO('2020-01-01T12:00:05.200Z').toUTC() const timestamp2 = DateTime.fromISO('2020-02-02T12:00:05.200Z').toUTC() @@ -180,6 +180,7 @@ describe('PersonState.update()', () => { }) it('overrides are created only when distinct_id is in posthog_personlessdistinctid', async () => { + const start = performance.now() // oldUserDistinctId exists, and 'old2' will merge into it, but not create an override await hub.db.createPerson(timestamp, {}, {}, {}, teamId, null, false, oldUserUuid, [ { distinctId: oldUserDistinctId }, @@ -221,9 +222,13 @@ describe('PersonState.update()', () => { await kafkaAcks await kafkaAcks2 + console.log('Post acks', performance.now() - start) + // new2 has an override, because it was in posthog_personlessdistinctid await delayUntilEventIngested(() => fetchOverridesForDistinctId('new2')) + console.log('Postgres', performance.now() - start) const chOverrides = await fetchOverridesForDistinctId('new2') + console.log('Clickhouse', performance.now() - start) expect(chOverrides.length).toEqual(1) expect(chOverrides).toEqual( expect.arrayContaining([ @@ -237,6 +242,7 @@ describe('PersonState.update()', () => { // old2 has no override, because it wasn't in posthog_personlessdistinctid const chOverridesOld = await fetchOverridesForDistinctId('old2') + console.log('post fetch 2', performance.now() - start) expect(chOverridesOld.length).toEqual(0) }) diff --git a/plugin-server/tests/worker/ingestion/postgres-parity.test.ts b/plugin-server/tests/worker/ingestion/postgres-parity.test.ts index 00de97124395b..42e181fc2ef98 100644 --- a/plugin-server/tests/worker/ingestion/postgres-parity.test.ts +++ b/plugin-server/tests/worker/ingestion/postgres-parity.test.ts @@ -45,7 +45,7 @@ describe('postgres parity', () => { await resetTestDatabaseClickhouse(extraServerConfig) console.log('[TEST] Starting plugins server') const startResponse = await startPluginsServer(extraServerConfig, makePiscina, { ingestion: true }) - hub = startResponse.hub + hub = startResponse.hub! stopServer = startResponse.stop teamId++ console.log('[TEST] Setting up seed data') @@ -180,10 +180,7 @@ describe('postgres parity', () => { is_identified: true, }) - await hub.db.kafkaProducer.queueMessages({ - kafkaMessages, - waitForAck: true, - }) + await hub.db.kafkaProducer.queueMessages(kafkaMessages) await delayUntilEventIngested(async () => (await hub.db.fetchPersons(Database.ClickHouse)).filter((p) => p.is_identified) @@ -211,10 +208,7 @@ describe('postgres parity', () => { is_identified: false, }) - await hub.db.kafkaProducer.queueMessages({ - kafkaMessages: kafkaMessages2, - waitForAck: true, - }) + await hub.db.kafkaProducer.queueMessages(kafkaMessages2) expect(updatedPerson.version).toEqual(2) @@ -354,7 +348,7 @@ describe('postgres parity', () => { // move distinct ids from person to to anotherPerson const kafkaMessages = await hub.db.moveDistinctIds(person, anotherPerson) - await hub.db!.kafkaProducer!.queueMessages({ kafkaMessages, waitForAck: true }) + await hub.db!.kafkaProducer!.queueMessages(kafkaMessages) await delayUntilEventIngested(() => hub.db.fetchDistinctIdValues(anotherPerson, Database.ClickHouse), 2) // it got added @@ -410,7 +404,7 @@ describe('postgres parity', () => { // delete person await hub.db.postgres.transaction(PostgresUse.COMMON_WRITE, '', async (client) => { const deletePersonMessage = await hub.db.deletePerson(person, client) - await hub.db!.kafkaProducer!.queueMessage({ kafkaMessage: deletePersonMessage[0], waitForAck: true }) + await hub.db!.kafkaProducer!.queueMessages(deletePersonMessage[0]) }) await delayUntilEventIngested(async () => diff --git a/plugin-server/tests/worker/vm.test.ts b/plugin-server/tests/worker/vm.test.ts index 6f4f35460da19..778cedb0a2af7 100644 --- a/plugin-server/tests/worker/vm.test.ts +++ b/plugin-server/tests/worker/vm.test.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line simple-import-sort/imports +import { getParsedQueuedMessages, mockProducer } from '../helpers/mocks/producer.mock' + import { PluginEvent, ProcessedPluginEvent } from '@posthog/plugin-scaffold' import fetch from 'node-fetch' @@ -12,7 +15,6 @@ import { plugin60 } from '../helpers/plugins' import { resetTestDatabase } from '../helpers/sql' jest.mock('../../src/utils/status') -jest.mock('../../src/utils/db/kafka-producer-wrapper') jest.mock('../../src/main/graphile-worker/graphile-worker') jest.setTimeout(100000) @@ -683,26 +685,28 @@ describe('vm tests', () => { ...defaultEvent, event: 'logged event', } - const queueSingleJsonMessageSpy = jest.spyOn(hub.kafkaProducer, 'queueSingleJsonMessage') await vm.methods.processEvent!(event) - expect(queueSingleJsonMessageSpy).toHaveBeenCalledTimes(1) - expect(queueSingleJsonMessageSpy).toHaveBeenCalledWith({ + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + expect(getParsedQueuedMessages()[0]).toEqual({ topic: KAFKA_PLUGIN_LOG_ENTRIES, - key: expect.any(String), - object: { - id: expect.any(String), - instance_id: hub.instanceId.toString(), - message: 'logged event', - plugin_config_id: pluginConfig39.id, - plugin_id: pluginConfig39.plugin_id, - source: PluginLogEntrySource.Console, - team_id: pluginConfig39.team_id, - timestamp: expect.any(String), - type: PluginLogEntryType.Log, - }, - waitForAck: false, + messages: [ + { + key: expect.any(String), + value: { + id: expect.any(String), + instance_id: hub.instanceId.toString(), + message: 'logged event', + plugin_config_id: pluginConfig39.id, + plugin_id: pluginConfig39.plugin_id, + source: PluginLogEntrySource.Console, + team_id: pluginConfig39.team_id, + timestamp: expect.any(String), + type: PluginLogEntryType.Log, + }, + }, + ], }) }) @@ -961,16 +965,14 @@ describe('vm tests', () => { ` await resetTestDatabase(indexJs) const vm = await createReadyPluginConfigVm(hub, pluginConfig39, indexJs) - - const queueMessageSpy = jest.spyOn(hub.kafkaProducer, 'queueMessage') - const response = await vm.tasks.schedule.runEveryMinute.exec() expect(response).toBe('haha') - expect(queueMessageSpy).toHaveBeenCalledTimes(1) - expect(queueMessageSpy.mock.calls[0][0].kafkaMessage.topic).toEqual(KAFKA_EVENTS_PLUGIN_INGESTION) - const parsedMessage = JSON.parse(queueMessageSpy.mock.calls[0][0].kafkaMessage.messages[0].value!.toString()) - expect(JSON.parse(parsedMessage.data)).toMatchObject({ + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + const queuedMessages = getParsedQueuedMessages() + expect(queuedMessages[0].topic).toEqual(KAFKA_EVENTS_PLUGIN_INGESTION) + const parsedMessage = JSON.parse(queuedMessages[0].messages[0].value!.data) + expect(parsedMessage).toMatchObject({ distinct_id: 'plugin-id-60', event: 'my-new-event', properties: expect.objectContaining({ @@ -991,15 +993,14 @@ describe('vm tests', () => { await resetTestDatabase(indexJs) const vm = await createReadyPluginConfigVm(hub, pluginConfig39, indexJs) - const queueMessageSpy = jest.spyOn(hub.kafkaProducer, 'queueMessage') - const response = await vm.tasks.schedule.runEveryMinute.exec() expect(response).toBe('haha') - expect(queueMessageSpy).toHaveBeenCalledTimes(1) - expect(queueMessageSpy.mock.calls[0][0].kafkaMessage.topic).toEqual(KAFKA_EVENTS_PLUGIN_INGESTION) - const parsedMessage = JSON.parse(queueMessageSpy.mock.calls[0][0].kafkaMessage.messages[0].value!.toString()) - expect(JSON.parse(parsedMessage.data)).toMatchObject({ + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + const queuedMessages = getParsedQueuedMessages() + expect(queuedMessages[0].topic).toEqual(KAFKA_EVENTS_PLUGIN_INGESTION) + const parsedMessage = JSON.parse(queuedMessages[0].messages[0].value!.data) + expect(parsedMessage).toMatchObject({ timestamp: '2020-02-23T02:15:00Z', // taken out of the properties distinct_id: 'plugin-id-60', event: 'my-new-event', @@ -1016,17 +1017,17 @@ describe('vm tests', () => { ` await resetTestDatabase(indexJs) const vm = await createReadyPluginConfigVm(hub, pluginConfig39, indexJs) - - const queueMessageSpy = jest.spyOn(hub.kafkaProducer, 'queueMessage') - const response = await vm.tasks.schedule.runEveryMinute.exec() expect(response).toBe('haha') - expect(response).toBe('haha') - expect(queueMessageSpy).toHaveBeenCalledTimes(1) - expect(queueMessageSpy.mock.calls[0][0].kafkaMessage.topic).toEqual(KAFKA_EVENTS_PLUGIN_INGESTION) - const parsedMessage = JSON.parse(queueMessageSpy.mock.calls[0][0].kafkaMessage.messages[0].value!.toString()) - expect(JSON.parse(parsedMessage.data)).toMatchObject({ + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + const queuedMessages = getParsedQueuedMessages() + + expect(queuedMessages[0].topic).toEqual(KAFKA_EVENTS_PLUGIN_INGESTION) + + const parsedData = JSON.parse(queuedMessages[0].messages[0].value!.data) + + expect(parsedData).toMatchObject({ distinct_id: 'custom id', event: 'my-new-event', properties: expect.objectContaining({ From 46837c1a3e370a2d20f54886adb9dd96b757bc84 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 10:56:29 +0100 Subject: [PATCH 10/58] Fixes --- .../produceExceptionSymbolificationEventStep.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugin-server/src/worker/ingestion/event-pipeline/produceExceptionSymbolificationEventStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/produceExceptionSymbolificationEventStep.ts index 7d2b6682c5808..df6c135542e55 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/produceExceptionSymbolificationEventStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/produceExceptionSymbolificationEventStep.ts @@ -7,11 +7,14 @@ export function produceExceptionSymbolificationEventStep( event: RawKafkaEvent ): Promise<[Promise]> { const ack = runner.hub.kafkaProducer - .produce({ + .queueMessages({ topic: runner.hub.EXCEPTIONS_SYMBOLIFICATION_KAFKA_TOPIC, - key: String(event.team_id), - value: Buffer.from(JSON.stringify(event)), - waitForAck: true, + messages: [ + { + key: String(event.team_id), + value: Buffer.from(JSON.stringify(event)), + }, + ], }) .catch((error) => { status.warn('⚠️', 'Failed to produce exception event for symbolification', { From a4327cb7b15814daa47c020f5c2d360cf343c79b Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:01:13 +0100 Subject: [PATCH 11/58] Fix --- plugin-server/src/worker/ingestion/event-pipeline/runner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts index dc5cf6d8df186..6d70e62398f5a 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts @@ -352,7 +352,7 @@ export class EventPipelineRunner { teamId, `plugin_server_ingest_event:${currentStepName}` ) - await this.hub.db.kafkaProducer!.queueMessage({ kafkaMessage: message, waitForAck: true }) + await this.hub.db.kafkaProducer.queueMessages(message) } catch (dlqError) { status.info('🔔', `Errored trying to add event to dead letter queue. Error: ${dlqError}`) Sentry.captureException(dlqError, { From 73f623c1d7a59feb0d15ec3b06a4d0b7f0cb3674 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:04:20 +0100 Subject: [PATCH 12/58] Fixes --- .../ingestion/__snapshots__/app-metrics.test.ts.snap | 12 ++++++------ .../tests/worker/ingestion/person-state.test.ts | 5 ----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap b/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap index 10cf219b7e43b..0081d6ad973c8 100644 --- a/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap +++ b/plugin-server/tests/worker/ingestion/__snapshots__/app-metrics.test.ts.snap @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`AppMetrics() flush() flushes queued messages 1`] = ` -Array [ - Array [ - Object { - "messages": Array [ - Object { - "value": "{\\"timestamp\\":\\"1970-01-01 00:16:40.000\\",\\"team_id\\":2,\\"plugin_config_id\\":2,\\"job_id\\":\\"000-000\\",\\"category\\":\\"processEvent\\",\\"successes\\":1,\\"successes_on_retry\\":0,\\"failures\\":0}", +[ + [ + { + "messages": [ + { + "value": "{"timestamp":"1970-01-01 00:16:40.000","team_id":2,"plugin_config_id":2,"job_id":"000-000","category":"processEvent","successes":1,"successes_on_retry":0,"failures":0}", }, ], "topic": "clickhouse_app_metrics_test", diff --git a/plugin-server/tests/worker/ingestion/person-state.test.ts b/plugin-server/tests/worker/ingestion/person-state.test.ts index 565353633f60c..e8e132b33814d 100644 --- a/plugin-server/tests/worker/ingestion/person-state.test.ts +++ b/plugin-server/tests/worker/ingestion/person-state.test.ts @@ -222,13 +222,9 @@ describe('PersonState.update()', () => { await kafkaAcks await kafkaAcks2 - console.log('Post acks', performance.now() - start) - // new2 has an override, because it was in posthog_personlessdistinctid await delayUntilEventIngested(() => fetchOverridesForDistinctId('new2')) - console.log('Postgres', performance.now() - start) const chOverrides = await fetchOverridesForDistinctId('new2') - console.log('Clickhouse', performance.now() - start) expect(chOverrides.length).toEqual(1) expect(chOverrides).toEqual( expect.arrayContaining([ @@ -242,7 +238,6 @@ describe('PersonState.update()', () => { // old2 has no override, because it wasn't in posthog_personlessdistinctid const chOverridesOld = await fetchOverridesForDistinctId('old2') - console.log('post fetch 2', performance.now() - start) expect(chOverridesOld.length).toEqual(0) }) From 3cef6f71a280236daff617d1069564157d5e07f3 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:20:09 +0100 Subject: [PATCH 13/58] fix --- .../ingestion/event-pipeline/runner.test.ts | 81 +++++++++---------- 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts index 6e54ec8f3c5aa..3b0fac9927931 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts @@ -1,6 +1,7 @@ import { PluginEvent } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' +import { KafkaProducerWrapper } from '../../../../src/kafka/producer' import { ISOTimestamp, Person, PipelineEvent, PreIngestionEvent, RawKafkaEvent } from '../../../../src/types' import { createEventsToDropByToken } from '../../../../src/utils/db/hub' import { createEventStep } from '../../../../src/worker/ingestion/event-pipeline/createEventStep' @@ -108,14 +109,20 @@ describe('EventPipelineRunner', () => { let runner: TestEventPipelineRunner let hub: any + const mockProducer: jest.Mocked = { + queueMessages: jest.fn(() => Promise.resolve()) as any, + } as any + beforeEach(() => { + jest.mocked(mockProducer.queueMessages).mockResolvedValue(Promise.resolve()) + hub = { - kafkaProducer: { queueMessage: jest.fn() }, + kafkaProducer: mockProducer, teamManager: { fetchTeam: jest.fn(() => {}), }, db: { - kafkaProducer: { queueMessage: jest.fn() }, + kafkaProducer: mockProducer, fetchPerson: jest.fn(), }, eventsToDropByToken: createEventsToDropByToken('drop_token:drop_id,drop_token_all:*'), @@ -254,10 +261,10 @@ describe('EventPipelineRunner', () => { await runner.runEventPipeline(pipelineEvent) - expect(hub.db.kafkaProducer.queueMessage).toHaveBeenCalledTimes(1) - expect( - JSON.parse(hub.db.kafkaProducer.queueMessage.mock.calls[0][0].kafkaMessage.messages[0].value) - ).toMatchObject({ + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + + expect(mockProducer.queueMessages.mock.calls[0][0].topic).toEqual('events_dead_letter_queue_test') + expect(JSON.parse(mockProducer.queueMessages.mock.calls[0][0].messages[0].value)).toMatchObject({ team_id: 2, distinct_id: 'my_id', error: 'Event ingestion failed. Error: testError', @@ -272,7 +279,7 @@ describe('EventPipelineRunner', () => { await runner.runEventPipeline(pipelineEvent) - expect(hub.db.kafkaProducer.queueMessage).not.toHaveBeenCalled() + expect(mockProducer.queueMessages).not.toHaveBeenCalled() expect(pipelineStepDLQCounterSpy).not.toHaveBeenCalled() }) }) @@ -286,20 +293,12 @@ describe('EventPipelineRunner', () => { team_id: 9, } - const hub: any = { - db: { - kafkaProducer: { queueMessage: jest.fn() }, - }, - } - const runner = new TestEventPipelineRunner(hub, event, new EventsProcessor(hub)) jest.mocked(populateTeamDataStep).mockResolvedValue(event) await runner.runEventPipeline(event) expect(runner.steps).toEqual(['populateTeamDataStep']) - expect(hub.db.kafkaProducer.queueMessage).toHaveBeenCalledTimes(1) - expect( - JSON.parse(hub.db.kafkaProducer.queueMessage.mock.calls[0][0].kafkaMessage.messages[0].value) - ).toMatchObject({ + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + expect(JSON.parse(mockProducer.queueMessages.mock.calls[0][0].messages[0].value)).toMatchObject({ team_id: 9, type: 'client_ingestion_warning', details: JSON.stringify({ @@ -402,36 +401,28 @@ describe('EventPipelineRunner', () => { }) }) }) -}) -describe('EventPipelineRunner $process_person_profile=false', () => { - it('drops events that are not allowed when $process_person_profile=false', async () => { - for (const eventName of ['$identify', '$create_alias', '$merge_dangerously', '$groupidentify']) { - const event = { - ...pipelineEvent, - properties: { $process_person_profile: false }, - event: eventName, - team_id: 9, - } + describe('EventPipelineRunner $process_person_profile=false', () => { + it.each(['$identify', '$create_alias', '$merge_dangerously', '$groupidentify'])( + 'drops event %s that are not allowed when $process_person_profile=false', + async (eventName) => { + const event = { + ...pipelineEvent, + properties: { $process_person_profile: false }, + event: eventName, + team_id: 9, + } + jest.mocked(populateTeamDataStep).mockResolvedValue(event) - const hub: any = { - db: { - kafkaProducer: { queueMessage: jest.fn() }, - }, + await runner.runEventPipeline(event) + expect(runner.steps).toEqual(['populateTeamDataStep']) + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + expect(JSON.parse(mockProducer.queueMessages.mock.calls[0][0].messages[0].value)).toMatchObject({ + team_id: 9, + type: 'invalid_event_when_process_person_profile_is_false', + details: JSON.stringify({ eventUuid: 'uuid1', event: eventName, distinctId: 'my_id' }), + }) } - const runner = new TestEventPipelineRunner(hub, event, new EventsProcessor(hub)) - jest.mocked(populateTeamDataStep).mockResolvedValue(event) - - await runner.runEventPipeline(event) - expect(runner.steps).toEqual(['populateTeamDataStep']) - expect(hub.db.kafkaProducer.queueMessage).toHaveBeenCalledTimes(1) - expect( - JSON.parse(hub.db.kafkaProducer.queueMessage.mock.calls[0][0].kafkaMessage.messages[0].value) - ).toMatchObject({ - team_id: 9, - type: 'invalid_event_when_process_person_profile_is_false', - details: JSON.stringify({ eventUuid: 'uuid1', event: eventName, distinctId: 'my_id' }), - }) - } + ) }) }) From 6f0d9b6998fc8c8111bcc70b25ee21465ad0ecd9 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:27:26 +0100 Subject: [PATCH 14/58] Fixes --- .../event-pipeline/extractHeatmapDataStep.ts | 22 ++++++++++--------- .../ingestion/event-pipeline/runner.test.ts | 5 +++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts index 413ff28436cb6..3228233e62560 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/extractHeatmapDataStep.ts @@ -26,7 +26,7 @@ export async function extractHeatmapDataStep( ): Promise<[PreIngestionEvent, Promise[]]> { const { eventUuid, teamId } = event - let acks: Promise[] = [] + const acks: Promise[] = [] try { const team = await runner.hub.teamManager.fetchTeam(teamId) @@ -34,15 +34,17 @@ export async function extractHeatmapDataStep( if (team?.heatmaps_opt_in !== false) { const heatmapEvents = extractScrollDepthHeatmapData(event) ?? [] - acks.push( - runner.hub.kafkaProducer.queueMessages({ - topic: runner.hub.CLICKHOUSE_HEATMAPS_KAFKA_TOPIC, - messages: heatmapEvents.map((rawEvent) => ({ - key: eventUuid, - value: JSON.stringify(rawEvent), - })), - }) - ) + if (heatmapEvents.length > 0) { + acks.push( + runner.hub.kafkaProducer.queueMessages({ + topic: runner.hub.CLICKHOUSE_HEATMAPS_KAFKA_TOPIC, + messages: heatmapEvents.map((rawEvent) => ({ + key: eventUuid, + value: JSON.stringify(rawEvent), + })), + }) + ) + } } } catch (e) { acks.push( diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts index 3b0fac9927931..51dcd867767b0 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts @@ -110,11 +110,11 @@ describe('EventPipelineRunner', () => { let hub: any const mockProducer: jest.Mocked = { - queueMessages: jest.fn(() => Promise.resolve()) as any, + queueMessages: jest.fn() as any, } as any beforeEach(() => { - jest.mocked(mockProducer.queueMessages).mockResolvedValue(Promise.resolve()) + jest.mocked(mockProducer.queueMessages).mockImplementation(() => Promise.resolve()) hub = { kafkaProducer: mockProducer, @@ -277,6 +277,7 @@ describe('EventPipelineRunner', () => { const pipelineStepDLQCounterSpy = jest.spyOn(metrics.pipelineStepDLQCounter, 'labels') jest.mocked(processOnEventStep).mockRejectedValue(error) + expect(mockProducer.queueMessages).not.toHaveBeenCalled() await runner.runEventPipeline(pipelineEvent) expect(mockProducer.queueMessages).not.toHaveBeenCalled() From 02753d8d9c8b5162beb24420a07608f075d3524c Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:34:46 +0100 Subject: [PATCH 15/58] Fixes --- .../extractHeatmapDataStep.test.ts.snap | 5263 +---------------- .../extractHeatmapDataStep.test.ts | 35 +- 2 files changed, 84 insertions(+), 5214 deletions(-) diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/extractHeatmapDataStep.test.ts.snap b/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/extractHeatmapDataStep.test.ts.snap index 724035afff4e2..639739ab9907d 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/extractHeatmapDataStep.test.ts.snap +++ b/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/extractHeatmapDataStep.test.ts.snap @@ -4,5204 +4,73 @@ exports[`extractHeatmapDataStep() parses and ingests correct $heatmap_data 2`] = [ [ { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "messages": [ + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"mousemove","x":64,"y":23,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"rageclick","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"mousemove","x":40,"y":29,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"mousemove","x":66,"y":42,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":27,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":27,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"rageclick","x":40,"y":27,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":40,"y":27,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":45,"y":17,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + { + "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", + "value": "{"type":"click","x":7,"y":9,"pointer_target_fixed":false,"viewport_height":83,"viewport_width":67,"current_url":"http://localhost:3000/","session_id":"018eebf3-79cd-70da-895f-b6cf352bd688","scale_factor":16,"timestamp":"2024-04-17 12:06:46.861","team_id":1,"distinct_id":"018eebf3-79b1-7082-a7c6-eeb56a36002f"}", + }, + ], "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 109, - 111, - 117, - 115, - 101, - 109, - 111, - 118, - 101, - 34, - 44, - 34, - 120, - 34, - 58, - 54, - 52, - 44, - 34, - 121, - 34, - 58, - 50, - 51, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 114, - 97, - 103, - 101, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 109, - 111, - 117, - 115, - 101, - 109, - 111, - 118, - 101, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 109, - 111, - 117, - 115, - 101, - 109, - 111, - 118, - 101, - 34, - 44, - 34, - 120, - 34, - 58, - 54, - 54, - 44, - 34, - 121, - 34, - 58, - 52, - 50, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 55, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 55, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 114, - 97, - 103, - 101, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 55, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 48, - 44, - 34, - 121, - 34, - 58, - 50, - 55, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 52, - 53, - 44, - 34, - 121, - 34, - 58, - 49, - 55, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, - }, - ], - [ - { - "key": "018eebf3-cb48-750b-bfad-36409ea6f2b2", - "topic": undefined, - "value": { - "data": [ - 123, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 99, - 108, - 105, - 99, - 107, - 34, - 44, - 34, - 120, - 34, - 58, - 55, - 44, - 34, - 121, - 34, - 58, - 57, - 44, - 34, - 112, - 111, - 105, - 110, - 116, - 101, - 114, - 95, - 116, - 97, - 114, - 103, - 101, - 116, - 95, - 102, - 105, - 120, - 101, - 100, - 34, - 58, - 102, - 97, - 108, - 115, - 101, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 104, - 101, - 105, - 103, - 104, - 116, - 34, - 58, - 56, - 51, - 44, - 34, - 118, - 105, - 101, - 119, - 112, - 111, - 114, - 116, - 95, - 119, - 105, - 100, - 116, - 104, - 34, - 58, - 54, - 55, - 44, - 34, - 99, - 117, - 114, - 114, - 101, - 110, - 116, - 95, - 117, - 114, - 108, - 34, - 58, - 34, - 104, - 116, - 116, - 112, - 58, - 47, - 47, - 108, - 111, - 99, - 97, - 108, - 104, - 111, - 115, - 116, - 58, - 51, - 48, - 48, - 48, - 47, - 34, - 44, - 34, - 115, - 101, - 115, - 115, - 105, - 111, - 110, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 99, - 100, - 45, - 55, - 48, - 100, - 97, - 45, - 56, - 57, - 53, - 102, - 45, - 98, - 54, - 99, - 102, - 51, - 53, - 50, - 98, - 100, - 54, - 56, - 56, - 34, - 44, - 34, - 115, - 99, - 97, - 108, - 101, - 95, - 102, - 97, - 99, - 116, - 111, - 114, - 34, - 58, - 49, - 54, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 50, - 48, - 50, - 52, - 45, - 48, - 52, - 45, - 49, - 55, - 32, - 49, - 50, - 58, - 48, - 54, - 58, - 52, - 54, - 46, - 56, - 54, - 49, - 34, - 44, - 34, - 116, - 101, - 97, - 109, - 95, - 105, - 100, - 34, - 58, - 49, - 44, - 34, - 100, - 105, - 115, - 116, - 105, - 110, - 99, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 49, - 56, - 101, - 101, - 98, - 102, - 51, - 45, - 55, - 57, - 98, - 49, - 45, - 55, - 48, - 56, - 50, - 45, - 97, - 55, - 99, - 54, - 45, - 101, - 101, - 98, - 53, - 54, - 97, - 51, - 54, - 48, - 48, - 50, - 102, - 34, - 125, - ], - "type": "Buffer", - }, - "waitForAck": true, }, ], ] diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/extractHeatmapDataStep.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/extractHeatmapDataStep.test.ts index 11035a94472c4..f6a8bc844774f 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/extractHeatmapDataStep.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/extractHeatmapDataStep.test.ts @@ -1,6 +1,8 @@ +import { KafkaProducerWrapper, TopicMessage } from '../../../../src/kafka/producer' import { ISOTimestamp, PreIngestionEvent } from '../../../../src/types' import { cloneObject } from '../../../../src/utils/utils' import { extractHeatmapDataStep } from '../../../../src/worker/ingestion/event-pipeline/extractHeatmapDataStep' +import { EventPipelineRunner } from '../../../../src/worker/ingestion/event-pipeline/runner' jest.mock('../../../../src/worker/plugins/run') @@ -124,17 +126,17 @@ const preIngestionEvent: PreIngestionEvent = { } describe('extractHeatmapDataStep()', () => { - let runner: any + let runner: EventPipelineRunner let event: PreIngestionEvent + const mockProducer: jest.Mocked = { + queueMessages: jest.fn(() => Promise.resolve()) as any, + } as any beforeEach(() => { event = cloneObject(preIngestionEvent) runner = { hub: { - kafkaProducer: { - produce: jest.fn((e) => Promise.resolve(e)), - queueMessage: jest.fn((e) => Promise.resolve(e)), - }, + kafkaProducer: mockProducer, teamManager: { fetchTeam: jest.fn(() => Promise.resolve({ heatmaps_opt_in: true })), }, @@ -146,12 +148,11 @@ describe('extractHeatmapDataStep()', () => { const response = await extractHeatmapDataStep(runner, event) expect(response[0]).toEqual(event) expect(response[0].properties.$heatmap_data).toBeUndefined() - expect(response[1]).toHaveLength(16) - expect(runner.hub.kafkaProducer.produce).toBeCalledTimes(16) - - const firstProduceCall = runner.hub.kafkaProducer.produce.mock.calls[0][0] - - const parsed = JSON.parse(firstProduceCall.value.toString()) + expect(response[1]).toHaveLength(1) + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + const messages = (mockProducer.queueMessages.mock.calls[0][0] as TopicMessage).messages + expect(messages).toHaveLength(16) + const parsed = JSON.parse(messages[0].value.toString()) expect(parsed).toMatchInlineSnapshot(` { @@ -171,7 +172,7 @@ describe('extractHeatmapDataStep()', () => { `) // The rest we can just compare the buffers - expect(runner.hub.kafkaProducer.produce.mock.calls).toMatchSnapshot() + expect(mockProducer.queueMessages.mock.calls).toMatchSnapshot() }) it('additionally parses ', async () => { @@ -189,11 +190,11 @@ describe('extractHeatmapDataStep()', () => { // We don't delete scroll properties expect(response[0].properties.$prev_pageview_max_scroll).toEqual(225) - expect(response[1]).toHaveLength(17) + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) + const messages = (mockProducer.queueMessages.mock.calls[0][0] as TopicMessage).messages + expect(messages).toHaveLength(17) - const allParsedMessages = runner.hub.kafkaProducer.produce.mock.calls.map((call) => - JSON.parse(call[0].value.toString()) - ) + const allParsedMessages = messages.map((call) => JSON.parse(call.value!.toString())) expect(allParsedMessages.find((x) => x.type === 'scrolldepth')).toMatchInlineSnapshot(` { @@ -219,7 +220,7 @@ describe('extractHeatmapDataStep()', () => { expect(response[0]).toEqual(event) expect(response[0].properties.$heatmap_data).toBeUndefined() expect(response[1]).toHaveLength(0) - expect(runner.hub.kafkaProducer.produce).toBeCalledTimes(0) + expect(mockProducer.queueMessages).toHaveBeenCalledTimes(0) }) describe('validation', () => { From 2ac00218f7e167a7ffb8515202811c1ddd0cd2c8 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:37:00 +0100 Subject: [PATCH 16/58] Fixes --- plugin-server/tests/worker/ingestion/person-state.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-server/tests/worker/ingestion/person-state.test.ts b/plugin-server/tests/worker/ingestion/person-state.test.ts index e8e132b33814d..f13b39b599dba 100644 --- a/plugin-server/tests/worker/ingestion/person-state.test.ts +++ b/plugin-server/tests/worker/ingestion/person-state.test.ts @@ -180,7 +180,6 @@ describe('PersonState.update()', () => { }) it('overrides are created only when distinct_id is in posthog_personlessdistinctid', async () => { - const start = performance.now() // oldUserDistinctId exists, and 'old2' will merge into it, but not create an override await hub.db.createPerson(timestamp, {}, {}, {}, teamId, null, false, oldUserUuid, [ { distinctId: oldUserDistinctId }, From 8228d910176eb0930aa46aca7e59f32af9d2d14c Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:37:50 +0100 Subject: [PATCH 17/58] fix --- plugin-server/tests/worker/ingestion/person-state.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/tests/worker/ingestion/person-state.test.ts b/plugin-server/tests/worker/ingestion/person-state.test.ts index f13b39b599dba..a988f8cf55f4e 100644 --- a/plugin-server/tests/worker/ingestion/person-state.test.ts +++ b/plugin-server/tests/worker/ingestion/person-state.test.ts @@ -12,7 +12,7 @@ import { uuidFromDistinctId } from '../../../src/worker/ingestion/person-uuid' import { delayUntilEventIngested } from '../../helpers/clickhouse' import { createOrganization, createTeam, fetchPostgresPersons, insertRow } from '../../helpers/sql' -jest.setTimeout(30000) // 5 sec timeout +jest.setTimeout(30000) const timestamp = DateTime.fromISO('2020-01-01T12:00:05.200Z').toUTC() const timestamp2 = DateTime.fromISO('2020-02-02T12:00:05.200Z').toUTC() From e9a3ce75fc590bac964e950fb15f98134cfad4f9 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:51:44 +0100 Subject: [PATCH 18/58] Fix for different types --- .vscode/launch.json | 3 +- plugin-server/src/capabilities.ts | 48 +++++++++++++++++++------------ plugin-server/src/types.ts | 1 + 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9eb3fe62780f2..797c70ca6ae13 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -144,7 +144,8 @@ "OBJECT_STORAGE_ENABLED": "True", "HOG_HOOK_URL": "http://localhost:3300/hoghook", "CDP_ASYNC_FUNCTIONS_RUSTY_HOOK_TEAMS": "", - "CDP_CYCLOTRON_ENABLED_TEAMS": "*" + "CDP_CYCLOTRON_ENABLED_TEAMS": "*", + "PLUGIN_SERVER_MODE": "single-process-v2" }, "presentation": { "group": "main" diff --git a/plugin-server/src/capabilities.ts b/plugin-server/src/capabilities.ts index 23f18ea3accd2..c2a01b57c69f0 100644 --- a/plugin-server/src/capabilities.ts +++ b/plugin-server/src/capabilities.ts @@ -7,29 +7,41 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin : null const sharedCapabilities = !isTestEnv() ? { http: true } : {} + const singleProcessCapabilities: PluginServerCapabilities = { + mmdb: true, + ingestion: true, + ingestionOverflow: true, + ingestionHistorical: true, + eventsIngestionPipelines: true, // with null PluginServerMode we run all of them + pluginScheduledTasks: true, + processPluginJobs: true, + processAsyncOnEventHandlers: true, + processAsyncWebhooksHandlers: true, + sessionRecordingBlobIngestion: true, + sessionRecordingBlobOverflowIngestion: config.SESSION_RECORDING_OVERFLOW_ENABLED, + appManagementSingleton: true, + preflightSchedules: true, + cdpProcessedEvents: true, + cdpInternalEvents: true, + cdpFunctionCallbacks: true, + cdpCyclotronWorker: true, + syncInlinePlugins: true, + ...sharedCapabilities, + } + switch (mode) { case null: return { - mmdb: true, - ingestionV2Combined: true, - ingestionOverflow: true, - ingestionHistorical: true, - eventsIngestionPipelines: true, // with null PluginServerMode we run all of them - pluginScheduledTasks: true, - processPluginJobs: true, - processAsyncOnEventHandlers: true, - processAsyncWebhooksHandlers: true, - sessionRecordingBlobIngestion: true, - sessionRecordingBlobOverflowIngestion: config.SESSION_RECORDING_OVERFLOW_ENABLED, - appManagementSingleton: true, - preflightSchedules: true, - cdpProcessedEvents: true, - cdpInternalEvents: true, - cdpFunctionCallbacks: true, - cdpCyclotronWorker: true, - syncInlinePlugins: true, + ...singleProcessCapabilities, ...sharedCapabilities, } + case PluginServerMode.single_process_v2: + return { + ...singleProcessCapabilities, + ...sharedCapabilities, + ingestionV2Combined: true, + } + case PluginServerMode.ingestion_v2: // NOTE: this mode will be removed in the future and replaced with // `analytics-ingestion` and `recordings-ingestion` modes. diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index e0d6c4c0c0a22..056d7b4ef22d4 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -72,6 +72,7 @@ export enum KafkaSaslMechanism { } export enum PluginServerMode { + single_process_v2 = 'single-process-v2', ingestion = 'ingestion', ingestion_v2 = 'ingestion-v2', ingestion_overflow = 'ingestion-overflow', From 4a6575c6289ee2e10fd24815fe198dbf789b45a5 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:57:01 +0100 Subject: [PATCH 19/58] Fix --- .../src/ingestion/ingestion-consumer.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index bc63a817401dd..bdfe9b66d56f3 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -4,6 +4,7 @@ import { Histogram } from 'prom-client' import { BatchConsumer, startBatchConsumer } from '../kafka/batch-consumer' import { createRdConnectionConfigFromEnvVars } from '../kafka/config' +import { KafkaProducerWrapper } from '../kafka/producer' import { IngestionOverflowMode } from '../main/ingestion-queues/batch-processing/each-batch-ingestion' import { ingestionOverflowingMessagesTotal } from '../main/ingestion-queues/batch-processing/metrics' import { addSentryBreadcrumbsEventListeners } from '../main/ingestion-queues/kafka-metrics' @@ -15,8 +16,6 @@ import { } from '../main/ingestion-queues/metrics' import { runInstrumentedFunction } from '../main/utils' import { Hub, PipelineEvent, PluginServerService } from '../types' -import { createKafkaProducerWrapper } from '../utils/db/hub' -import { KafkaProducerWrapper } from '../utils/db/kafka-producer-wrapper' import { normalizeEvent } from '../utils/event' import { retryIfRetriable } from '../utils/retries' import { status } from '../utils/status' @@ -53,10 +52,10 @@ const KNOWN_SET_EVENTS = new Set([ abstract class IngestionConsumer { batchConsumer?: BatchConsumer isStopping = false - protected kafkaProducer?: KafkaProducerWrapper protected abstract name: string protected heartbeat = () => {} protected promises: Set> = new Set() + protected kafkaProducer?: KafkaProducerWrapper protected scheduleWork(promise: Promise): Promise { this.promises.add(promise) @@ -101,7 +100,7 @@ abstract class IngestionConsumer { }): Promise { this.batchConsumer = await startBatchConsumer({ ...options, - connectionConfig: createRdConnectionConfigFromEnvVars(this.hub), + connectionConfig: createRdConnectionConfigFromEnvVars(this.hub, 'consumer'), autoCommit: true, sessionTimeout: this.hub.KAFKA_CONSUMPTION_SESSION_TIMEOUT_MS, maxPollIntervalMs: this.hub.KAFKA_CONSUMPTION_MAX_POLL_INTERVAL_MS, @@ -148,13 +147,10 @@ abstract class IngestionConsumer { } public async start(): Promise { - // NOTE: This is only for starting shared services - await Promise.all([ - createKafkaProducerWrapper(this.hub).then((producer) => { - this.kafkaProducer = producer - this.kafkaProducer.producer.connect() - }), - ]) + await KafkaProducerWrapper.create(this.hub).then((producer) => { + this.kafkaProducer = producer + this.kafkaProducer.producer.connect() + }) } public async stop(): Promise { From e8f6a410fa2d177ff15c989e125ea2f915bca96b Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 11:57:28 +0100 Subject: [PATCH 20/58] Fixes --- plugin-server/src/ingestion/ingestion-consumer.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index bdfe9b66d56f3..08e12f6d03373 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -273,7 +273,6 @@ export class EventsIngestionConsumer extends IngestionConsumer { value: message.value, key: message.key ?? null, // avoid undefined, just to be safe headers: headers, - waitForAck: true, }) } catch (error) { // If we can't send to the DLQ and it's not retriable, just continue. We'll commit the @@ -342,7 +341,6 @@ export class EventsIngestionConsumer extends IngestionConsumer { // instead as that behavior is safer. key: useRandomPartitioning ? null : message.key ?? null, headers: message.headers, - waitForAck: true, }) ) ) From 704831e1eaf6f9ab01e5aba61c9c8e3c07dfeed6 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 12:04:15 +0100 Subject: [PATCH 21/58] Fixes --- .../src/ingestion/ingestion-consumer.ts | 355 +++++++++--------- plugin-server/src/main/pluginsServer.ts | 6 +- 2 files changed, 174 insertions(+), 187 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 08e12f6d03373..2ad14d47972d2 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -49,21 +49,33 @@ const KNOWN_SET_EVENTS = new Set([ 'survey sent', ]) -abstract class IngestionConsumer { +export class IngestionConsumer { + protected name = 'ingestion-consumer' + protected groupId: string + protected topic: string + protected dlqTopic: string + protected overflowTopic?: string + batchConsumer?: BatchConsumer isStopping = false - protected abstract name: string protected heartbeat = () => {} protected promises: Set> = new Set() protected kafkaProducer?: KafkaProducerWrapper - protected scheduleWork(promise: Promise): Promise { - this.promises.add(promise) - void promise.finally(() => this.promises.delete(promise)) - return promise - } + private tokensToDrop: string[] = [] + private tokenDistinctIdsToDrop: string[] = [] + + constructor(private hub: Hub) { + // The group and topic are configurable allowing for multiple ingestion consumers to be run in parallel + this.groupId = hub.INGESTION_CONSUMER_GROUP_ID + this.topic = hub.INGESTION_CONSUMER_CONSUME_TOPIC + this.overflowTopic = hub.INGESTION_CONSUMER_OVERFLOW_TOPIC + this.dlqTopic = hub.INGESTION_CONSUMER_DLQ_TOPIC + this.tokensToDrop = hub.DROP_EVENTS_BY_TOKEN.split(',') + this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',') - constructor(protected hub: Hub) {} + this.name = `ingestion-consumer-${this.topic}` + } public get service(): PluginServerService { return { @@ -74,83 +86,28 @@ abstract class IngestionConsumer { } } - protected async runWithHeartbeat(func: () => Promise | T): Promise { - // Helper function to ensure that looping over lots of hog functions doesn't block up the thread, killing the consumer - const res = await func() - this.heartbeat() - await new Promise((resolve) => process.nextTick(resolve)) - - return res - } - - protected async runManyWithHeartbeat(items: T[], func: (item: T) => Promise | R): Promise { - // Helper function to ensure that looping over lots of hog functions doesn't block up the event loop, leading to healthcheck failures - const results = [] - - for (const item of items) { - results.push(await this.runWithHeartbeat(() => func(item))) - } - return results - } - - protected async startKafkaConsumer(options: { - topic: string - groupId: string - handleBatch: (messages: Message[]) => Promise - }): Promise { - this.batchConsumer = await startBatchConsumer({ - ...options, - connectionConfig: createRdConnectionConfigFromEnvVars(this.hub, 'consumer'), - autoCommit: true, - sessionTimeout: this.hub.KAFKA_CONSUMPTION_SESSION_TIMEOUT_MS, - maxPollIntervalMs: this.hub.KAFKA_CONSUMPTION_MAX_POLL_INTERVAL_MS, - consumerMaxBytes: this.hub.KAFKA_CONSUMPTION_MAX_BYTES, - consumerMaxBytesPerPartition: this.hub.KAFKA_CONSUMPTION_MAX_BYTES_PER_PARTITION, - consumerMaxWaitMs: this.hub.KAFKA_CONSUMPTION_MAX_WAIT_MS, - consumerErrorBackoffMs: this.hub.KAFKA_CONSUMPTION_ERROR_BACKOFF_MS, - fetchBatchSize: this.hub.INGESTION_BATCH_SIZE, - batchingTimeoutMs: this.hub.KAFKA_CONSUMPTION_BATCHING_TIMEOUT_MS, - topicCreationTimeoutMs: this.hub.KAFKA_TOPIC_CREATION_TIMEOUT_MS, - topicMetadataRefreshInterval: this.hub.KAFKA_TOPIC_METADATA_REFRESH_INTERVAL_MS, - eachBatch: async (messages, { heartbeat }) => { - status.info('🔁', `${this.name} - handling batch`, { - size: messages.length, - }) - - this.heartbeat = heartbeat - - histogramKafkaBatchSize.observe(messages.length) - histogramKafkaBatchSizeKb.observe(messages.reduce((acc, m) => (m.value?.length ?? 0) + acc, 0) / 1024) - - return await runInstrumentedFunction({ - statsKey: `ingestionConsumer.handleEachBatch`, - sendTimeoutGuardToSentry: false, - func: async () => { - await options.handleBatch(messages) - }, - }) - }, - callEachBatchWhenEmpty: false, - }) - - addSentryBreadcrumbsEventListeners(this.batchConsumer.consumer) - - this.batchConsumer.consumer.on('disconnected', async (err) => { - if (!this.isStopping) { - return - } - // since we can't be guaranteed that the consumer will be stopped before some other code calls disconnect - // we need to listen to disconnect and make sure we're stopped - status.info('🔁', `${this.name} batch consumer disconnected, cleaning up`, { err }) - await this.stop() - }) - } - public async start(): Promise { - await KafkaProducerWrapper.create(this.hub).then((producer) => { - this.kafkaProducer = producer - this.kafkaProducer.producer.connect() - }) + await Promise.all([ + KafkaProducerWrapper.create(this.hub).then((producer) => { + this.kafkaProducer = producer + this.kafkaProducer.producer.connect() + }), + this.startKafkaConsumer({ + topic: this.topic, + groupId: this.groupId, + handleBatch: async (messages) => { + const invocationGlobals = await this.parseKafkaBatch(messages) + await this.processBatch(invocationGlobals) + for (const message of messages) { + if (message.timestamp) { + latestOffsetTimestampGauge + .labels({ partition: message.partition, topic: message.topic, groupId: this.groupId }) + .set(message.timestamp) + } + } + }, + }), + ]) } public async stop(): Promise { @@ -169,33 +126,11 @@ abstract class IngestionConsumer { public isHealthy() { return this.batchConsumer?.isHealthy() } -} -/** - * This consumer handles incoming events from the main kafka ingestion topic - */ -export class EventsIngestionConsumer extends IngestionConsumer { - protected name = 'EventsIngestionConsumer' - protected groupId: string - protected topic: string - protected dlqTopic: string - protected overflowTopic?: string - - private tokensToDrop: string[] = [] - private tokenDistinctIdsToDrop: string[] = [] - - constructor(hub: Hub) { - super(hub) - - // The group and topic are configurable allowing for multiple ingestion consumers to be run in parallel - this.groupId = hub.INGESTION_CONSUMER_GROUP_ID - this.topic = hub.INGESTION_CONSUMER_CONSUME_TOPIC - this.overflowTopic = hub.INGESTION_CONSUMER_OVERFLOW_TOPIC - this.dlqTopic = hub.INGESTION_CONSUMER_DLQ_TOPIC - this.tokensToDrop = hub.DROP_EVENTS_BY_TOKEN.split(',') - this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',') - - this.name = `ingestion-consumer-${this.topic}` + private scheduleWork(promise: Promise): Promise { + this.promises.add(promise) + void promise.finally(() => this.promises.delete(promise)) + return promise } public async processBatch(groupedIncomingEvents: GroupedIncomingEvents): Promise { @@ -246,6 +181,132 @@ export class EventsIngestionConsumer extends IngestionConsumer { await Promise.all(this.promises) } + private parseKafkaBatch(messages: Message[]): Promise { + return runInstrumentedFunction({ + statsKey: `ingestionConsumer.handleEachBatch.parseKafkaMessages`, + func: () => { + const batches: GroupedIncomingEvents = {} + + for (const message of messages) { + let distinctId: string | undefined + let token: string | undefined + + // Parse the headers so we can early exit if found and should be dropped + message.headers?.forEach((header) => { + if (header.key === 'distinct_id') { + distinctId = header.value.toString() + } + if (header.key === 'token') { + token = header.value.toString() + } + }) + + if (this.shouldDropEvent(token, distinctId)) { + this.logDroppedEvent(token, distinctId) + continue + } + + // Parse the message payload into the event object + const { data: dataStr, ...rawEvent } = JSON.parse(message.value!.toString()) + const combinedEvent: PipelineEvent = { ...JSON.parse(dataStr), ...rawEvent } + const event: PipelineEvent = normalizeEvent({ + ...combinedEvent, + }) + + // In case the headers were not set we check the parsed message now + if (this.shouldDropEvent(combinedEvent.token, combinedEvent.distinct_id)) { + this.logDroppedEvent(combinedEvent.token, combinedEvent.distinct_id) + continue + } + + const eventKey = `${event.token}:${event.distinct_id}` + + // We collect the events grouped by token and distinct_id so that we can process batches in parallel whilst keeping the order of events + // for a given distinct_id + if (!batches[eventKey]) { + batches[eventKey] = [] + } + + batches[eventKey].push({ message, event }) + } + + return Promise.resolve(batches) + }, + }) + } + + private async runWithHeartbeat(func: () => Promise | T): Promise { + // Helper function to ensure that looping over lots of hog functions doesn't block up the thread, killing the consumer + const res = await func() + this.heartbeat() + await new Promise((resolve) => process.nextTick(resolve)) + + return res + } + + private async runManyWithHeartbeat(items: T[], func: (item: T) => Promise | R): Promise { + // Helper function to ensure that looping over lots of hog functions doesn't block up the event loop, leading to healthcheck failures + const results = [] + + for (const item of items) { + results.push(await this.runWithHeartbeat(() => func(item))) + } + return results + } + + private async startKafkaConsumer(options: { + topic: string + groupId: string + handleBatch: (messages: Message[]) => Promise + }): Promise { + this.batchConsumer = await startBatchConsumer({ + ...options, + connectionConfig: createRdConnectionConfigFromEnvVars(this.hub, 'consumer'), + autoCommit: true, + sessionTimeout: this.hub.KAFKA_CONSUMPTION_SESSION_TIMEOUT_MS, + maxPollIntervalMs: this.hub.KAFKA_CONSUMPTION_MAX_POLL_INTERVAL_MS, + consumerMaxBytes: this.hub.KAFKA_CONSUMPTION_MAX_BYTES, + consumerMaxBytesPerPartition: this.hub.KAFKA_CONSUMPTION_MAX_BYTES_PER_PARTITION, + consumerMaxWaitMs: this.hub.KAFKA_CONSUMPTION_MAX_WAIT_MS, + consumerErrorBackoffMs: this.hub.KAFKA_CONSUMPTION_ERROR_BACKOFF_MS, + fetchBatchSize: this.hub.INGESTION_BATCH_SIZE, + batchingTimeoutMs: this.hub.KAFKA_CONSUMPTION_BATCHING_TIMEOUT_MS, + topicCreationTimeoutMs: this.hub.KAFKA_TOPIC_CREATION_TIMEOUT_MS, + topicMetadataRefreshInterval: this.hub.KAFKA_TOPIC_METADATA_REFRESH_INTERVAL_MS, + eachBatch: async (messages, { heartbeat }) => { + status.info('🔁', `${this.name} - handling batch`, { + size: messages.length, + }) + + this.heartbeat = heartbeat + + histogramKafkaBatchSize.observe(messages.length) + histogramKafkaBatchSizeKb.observe(messages.reduce((acc, m) => (m.value?.length ?? 0) + acc, 0) / 1024) + + return await runInstrumentedFunction({ + statsKey: `ingestionConsumer.handleEachBatch`, + sendTimeoutGuardToSentry: false, + func: async () => { + await options.handleBatch(messages) + }, + }) + }, + callEachBatchWhenEmpty: false, + }) + + addSentryBreadcrumbsEventListeners(this.batchConsumer.consumer) + + this.batchConsumer.consumer.on('disconnected', async (err) => { + if (!this.isStopping) { + return + } + // since we can't be guaranteed that the consumer will be stopped before some other code calls disconnect + // we need to listen to disconnect and make sure we're stopped + status.info('🔁', `${this.name} batch consumer disconnected, cleaning up`, { err }) + await this.stop() + }) + } + private async handleProcessingError(error: any, message: Message, event: PipelineEvent) { status.error('🔥', `Error processing message`, { stack: error.stack, @@ -345,78 +406,4 @@ export class EventsIngestionConsumer extends IngestionConsumer { ) ) } - - // This consumer always parses from kafka - public _parseKafkaBatch(messages: Message[]): Promise { - return runInstrumentedFunction({ - statsKey: `ingestionConsumer.handleEachBatch.parseKafkaMessages`, - func: () => { - const batches: GroupedIncomingEvents = {} - - for (const message of messages) { - let distinctId: string | undefined - let token: string | undefined - - // Parse the headers so we can early exit if found and should be dropped - message.headers?.forEach((header) => { - if (header.key === 'distinct_id') { - distinctId = header.value.toString() - } - if (header.key === 'token') { - token = header.value.toString() - } - }) - - if (this.shouldDropEvent(token, distinctId)) { - this.logDroppedEvent(token, distinctId) - continue - } - - // Parse the message payload into the event object - const { data: dataStr, ...rawEvent } = JSON.parse(message.value!.toString()) - const combinedEvent: PipelineEvent = { ...JSON.parse(dataStr), ...rawEvent } - const event: PipelineEvent = normalizeEvent({ - ...combinedEvent, - }) - - // In case the headers were not set we check the parsed message now - if (this.shouldDropEvent(combinedEvent.token, combinedEvent.distinct_id)) { - this.logDroppedEvent(combinedEvent.token, combinedEvent.distinct_id) - continue - } - - const eventKey = `${event.token}:${event.distinct_id}` - - // We collect the events grouped by token and distinct_id so that we can process batches in parallel whilst keeping the order of events - // for a given distinct_id - if (!batches[eventKey]) { - batches[eventKey] = [] - } - - batches[eventKey].push({ message, event }) - } - - return Promise.resolve(batches) - }, - }) - } - - public async start(): Promise { - await super.start() - await this.startKafkaConsumer({ - topic: this.topic, - groupId: this.groupId, - handleBatch: async (messages) => { - const invocationGlobals = await this._parseKafkaBatch(messages) - await this.processBatch(invocationGlobals) - for (const message of messages) { - if (message.timestamp) { - latestOffsetTimestampGauge - .labels({ partition: message.partition, topic: message.topic, groupId: this.groupId }) - .set(message.timestamp) - } - } - }, - }) - } } diff --git a/plugin-server/src/main/pluginsServer.ts b/plugin-server/src/main/pluginsServer.ts index b0b124d4762b7..6ad33b8809764 100644 --- a/plugin-server/src/main/pluginsServer.ts +++ b/plugin-server/src/main/pluginsServer.ts @@ -24,7 +24,7 @@ import { KAFKA_EVENTS_PLUGIN_INGESTION_HISTORICAL, KAFKA_EVENTS_PLUGIN_INGESTION_OVERFLOW, } from '../config/kafka-topics' -import { EventsIngestionConsumer } from '../ingestion/ingestion-consumer' +import { IngestionConsumer } from '../ingestion/ingestion-consumer' import { KafkaProducerWrapper } from '../kafka/producer' import { Hub, PluginServerCapabilities, PluginServerService, PluginsServerConfig } from '../types' import { closeHub, createHub, createKafkaClient } from '../utils/db/hub' @@ -299,14 +299,14 @@ export async function startPluginsServer( INGESTION_CONSUMER_CONSUME_TOPIC: consumerOption.topic, INGESTION_CONSUMER_GROUP_ID: consumerOption.group_id, } - const consumer = new EventsIngestionConsumer(modifiedHub) + const consumer = new IngestionConsumer(modifiedHub) await consumer.start() services.push(consumer.service) } } else { if (capabilities.ingestionV2) { const hub = await setupHub() - const consumer = new EventsIngestionConsumer(hub) + const consumer = new IngestionConsumer(hub) await consumer.start() services.push(consumer.service) } From a76761f652f8ee84961635abcb12a9c1bab36e79 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 12:05:00 +0100 Subject: [PATCH 22/58] Fixes --- .vscode/launch.json | 2 +- plugin-server/src/capabilities.ts | 2 +- plugin-server/src/types.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 797c70ca6ae13..dd756e6acc43d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -145,7 +145,7 @@ "HOG_HOOK_URL": "http://localhost:3300/hoghook", "CDP_ASYNC_FUNCTIONS_RUSTY_HOOK_TEAMS": "", "CDP_CYCLOTRON_ENABLED_TEAMS": "*", - "PLUGIN_SERVER_MODE": "single-process-v2" + "PLUGIN_SERVER_MODE": "all-v2" }, "presentation": { "group": "main" diff --git a/plugin-server/src/capabilities.ts b/plugin-server/src/capabilities.ts index c2a01b57c69f0..3049db9af336a 100644 --- a/plugin-server/src/capabilities.ts +++ b/plugin-server/src/capabilities.ts @@ -35,7 +35,7 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin ...singleProcessCapabilities, ...sharedCapabilities, } - case PluginServerMode.single_process_v2: + case PluginServerMode.all_v2: return { ...singleProcessCapabilities, ...sharedCapabilities, diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 056d7b4ef22d4..550c4e71b9fbd 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -72,7 +72,7 @@ export enum KafkaSaslMechanism { } export enum PluginServerMode { - single_process_v2 = 'single-process-v2', + all_v2 = 'all-v2', ingestion = 'ingestion', ingestion_v2 = 'ingestion-v2', ingestion_overflow = 'ingestion-overflow', From 76095040956fccd8bd1e7f6bb63081bf7a1d5980 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 12:22:44 +0100 Subject: [PATCH 23/58] Fixes --- plugin-server/jest.config.js | 2 +- .../src/ingestion/ingestion-consumer.test.ts | 90 +++++++++++++++++++ .../tests/cdp/cdp-events-consumer.test.ts | 4 +- plugin-server/tsconfig.json | 12 ++- 4 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 plugin-server/src/ingestion/ingestion-consumer.test.ts diff --git a/plugin-server/jest.config.js b/plugin-server/jest.config.js index 451e6f0f88fdb..692f694e456c1 100644 --- a/plugin-server/jest.config.js +++ b/plugin-server/jest.config.js @@ -6,7 +6,7 @@ module.exports = { clearMocks: true, coverageProvider: 'v8', setupFilesAfterEnv: ['./jest.setup.fetch-mock.js'], - testMatch: ['/tests/**/*.test.ts', '/src/cdp/**/*.test.ts'], + testMatch: ['/tests/**/*.test.ts', '/src/**/*.test.ts'], testTimeout: 60000, modulePathIgnorePatterns: ['/.tmp/'], } diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts new file mode 100644 index 0000000000000..6b143e5919439 --- /dev/null +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -0,0 +1,90 @@ +import { Hub, Team } from '../../src/types' +import { closeHub, createHub } from '../../src/utils/db/hub' +import { getParsedQueuedMessages, mockProducer } from '../../tests/helpers/mocks/producer.mock' +import { getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' +import { IngestionConsumer } from './ingestion-consumer' + +const mockConsumer = { + on: jest.fn(), + commitSync: jest.fn(), + commit: jest.fn(), + queryWatermarkOffsets: jest.fn(), + committed: jest.fn(), + assignments: jest.fn(), + isConnected: jest.fn(() => true), + getMetadata: jest.fn(), +} + +jest.mock('../../src/kafka/batch-consumer', () => { + return { + startBatchConsumer: jest.fn(() => + Promise.resolve({ + join: () => ({ + finally: jest.fn(), + }), + stop: jest.fn(), + consumer: mockConsumer, + }) + ), + } +}) + +jest.setTimeout(1000) + +type DecodedKafkaMessage = { + topic: string + key?: any + value: Record +} + +const decodeAllKafkaMessages = (): DecodedKafkaMessage[] => { + const queuedMessages = getParsedQueuedMessages() + + const result: DecodedKafkaMessage[] = [] + + for (const topicMessage of queuedMessages) { + for (const message of topicMessage.messages) { + result.push({ + topic: topicMessage.topic, + key: message.key, + value: message.value ?? {}, + }) + } + } + + return result +} + +describe('IngestionConsumer', () => { + let processor: IngestionConsumer + let hub: Hub + let team: Team + + beforeEach(async () => { + await resetTestDatabase() + hub = await createHub() + hub.kafkaProducer = mockProducer + team = await getFirstTeam(hub) + + processor = new IngestionConsumer(hub) + await processor.start() + }) + + afterEach(async () => { + jest.setTimeout(10000) + await processor.stop() + await closeHub(hub) + }) + + afterAll(() => { + jest.useRealTimers() + }) + + describe('general', () => { + beforeEach(async () => {}) + + it('should process events', () => { + expect(1).toEqual(2) + }) + }) +}) diff --git a/plugin-server/tests/cdp/cdp-events-consumer.test.ts b/plugin-server/tests/cdp/cdp-events-consumer.test.ts index 5294256a2862b..f716522311dd6 100644 --- a/plugin-server/tests/cdp/cdp-events-consumer.test.ts +++ b/plugin-server/tests/cdp/cdp-events-consumer.test.ts @@ -1,11 +1,9 @@ -// eslint-disable-next-line simple-import-sort/imports -import { getParsedQueuedMessages, mockProducer } from '../helpers/mocks/producer.mock' - import { CdpInternalEventsConsumer, CdpProcessedEventsConsumer } from '../../src/cdp/cdp-consumers' import { HogWatcherState } from '../../src/cdp/hog-watcher' import { HogFunctionInvocationGlobals, HogFunctionType } from '../../src/cdp/types' import { Hub, Team } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' +import { getParsedQueuedMessages, mockProducer } from '../helpers/mocks/producer.mock' import { getFirstTeam, resetTestDatabase } from '../helpers/sql' import { HOG_EXAMPLES, HOG_FILTERS_EXAMPLES, HOG_INPUTS_EXAMPLES } from './examples' import { createHogExecutionGlobals, insertHogFunction as _insertHogFunction } from './fixtures' diff --git a/plugin-server/tsconfig.json b/plugin-server/tsconfig.json index e1758868730f2..8feab712e86aa 100644 --- a/plugin-server/tsconfig.json +++ b/plugin-server/tsconfig.json @@ -10,15 +10,19 @@ "esModuleInterop": true, "allowJs": true, "sourceMap": true, - "baseUrl": "src/", - "rootDir": "src/", + "baseUrl": "./", + "rootDir": "./", "outDir": "dist/", "types": ["node", "jest", "long"], "resolveJsonModule": true, "strict": true, "noImplicitAny": true, - "useUnknownInCatchVariables": false + "useUnknownInCatchVariables": false, + "paths": { + "src/*": ["src/*"], + "tests/*": ["tests/*"] + } }, - "include": ["src"], + "include": ["src", "tests"], "exclude": ["node_modules", "dist", "bin"] } From db07b59d255488f0241c0050ea6d331960aa2370 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 12:41:19 +0100 Subject: [PATCH 24/58] Fixes --- plugin-server/jest.config.functional.js | 4 ++ plugin-server/jest.config.js | 4 ++ .../src/ingestion/ingestion-consumer.test.ts | 60 ++++++++++++++++--- .../src/ingestion/ingestion-consumer.ts | 24 ++++---- plugin-server/tsconfig.json | 3 +- 5 files changed, 74 insertions(+), 21 deletions(-) diff --git a/plugin-server/jest.config.functional.js b/plugin-server/jest.config.functional.js index 44c1a77ebe26f..b9a1cb1ae3fb1 100644 --- a/plugin-server/jest.config.functional.js +++ b/plugin-server/jest.config.functional.js @@ -18,4 +18,8 @@ module.exports = { testTimeout: 60000, maxConcurrency: 10, maxWorkers: 6, + + moduleNameMapper: { + '^~/(.*)$': '/$1', + }, } diff --git a/plugin-server/jest.config.js b/plugin-server/jest.config.js index 692f694e456c1..cca6bab6d2b99 100644 --- a/plugin-server/jest.config.js +++ b/plugin-server/jest.config.js @@ -9,4 +9,8 @@ module.exports = { testMatch: ['/tests/**/*.test.ts', '/src/**/*.test.ts'], testTimeout: 60000, modulePathIgnorePatterns: ['/.tmp/'], + + moduleNameMapper: { + '^~/(.*)$': '/$1', + }, } diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 6b143e5919439..0b78e0525fcda 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -1,6 +1,11 @@ -import { Hub, Team } from '../../src/types' +import { DateTime } from 'luxon' +import { Message } from 'node-rdkafka' + +import { UUIDT } from '~/src/utils/utils' +import { getParsedQueuedMessages, mockProducer } from '~/tests/helpers/mocks/producer.mock' + +import { Hub, PipelineEvent, Team } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' -import { getParsedQueuedMessages, mockProducer } from '../../tests/helpers/mocks/producer.mock' import { getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' import { IngestionConsumer } from './ingestion-consumer' @@ -55,24 +60,62 @@ const decodeAllKafkaMessages = (): DecodedKafkaMessage[] => { return result } +let offsetIncrementer = 0 + +const createKafkaMessages: (events: PipelineEvent[]) => Message[] = (events) => { + return events.map((event) => { + // TRICKY: This is the slightly different format that capture sends + const captureEvent = { + uuid: event.uuid, + distinct_id: event.distinct_id, + ip: event.ip, + now: event.now, + token: event.token, + data: JSON.stringify(event), + } + return { + value: Buffer.from(JSON.stringify(captureEvent)), + size: 1, + topic: 'test', + offset: offsetIncrementer++, + partition: 1, + } + }) +} + describe('IngestionConsumer', () => { - let processor: IngestionConsumer + let ingester: IngestionConsumer let hub: Hub let team: Team + const createEvent = (event?: Partial): PipelineEvent => ({ + distinct_id: 'user-1', + uuid: new UUIDT().toString(), + token: team.api_token, + ip: '127.0.0.1', + site_url: 'us.posthog.com', + now: DateTime.now().toISO(), + event: '$pageview', + properties: { + $current_url: 'http://localhost:8000', + }, + ...event, + }) + beforeEach(async () => { + offsetIncrementer = 0 await resetTestDatabase() hub = await createHub() hub.kafkaProducer = mockProducer team = await getFirstTeam(hub) - processor = new IngestionConsumer(hub) - await processor.start() + ingester = new IngestionConsumer(hub) + await ingester.start() }) afterEach(async () => { jest.setTimeout(10000) - await processor.stop() + await ingester.stop() await closeHub(hub) }) @@ -83,8 +126,9 @@ describe('IngestionConsumer', () => { describe('general', () => { beforeEach(async () => {}) - it('should process events', () => { - expect(1).toEqual(2) + it('should process events', async () => { + const messages = createKafkaMessages([createEvent()]) + await ingester.handleKafkaBatch(messages) }) }) }) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 2ad14d47972d2..cd647bc56dc77 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -95,17 +95,7 @@ export class IngestionConsumer { this.startKafkaConsumer({ topic: this.topic, groupId: this.groupId, - handleBatch: async (messages) => { - const invocationGlobals = await this.parseKafkaBatch(messages) - await this.processBatch(invocationGlobals) - for (const message of messages) { - if (message.timestamp) { - latestOffsetTimestampGauge - .labels({ partition: message.partition, topic: message.topic, groupId: this.groupId }) - .set(message.timestamp) - } - } - }, + handleBatch: async (messages) => this.handleKafkaBatch(messages), }), ]) } @@ -133,6 +123,18 @@ export class IngestionConsumer { return promise } + public async handleKafkaBatch(messages: Message[]) { + const parsedMessages = await this.parseKafkaBatch(messages) + await this.processBatch(parsedMessages) + for (const message of messages) { + if (message.timestamp) { + latestOffsetTimestampGauge + .labels({ partition: message.partition, topic: message.topic, groupId: this.groupId }) + .set(message.timestamp) + } + } + } + public async processBatch(groupedIncomingEvents: GroupedIncomingEvents): Promise { await this.runManyWithHeartbeat(Object.values(groupedIncomingEvents), async (eventsForDistinctId) => { // Process every message sequentially, stash promises to await on later diff --git a/plugin-server/tsconfig.json b/plugin-server/tsconfig.json index 8feab712e86aa..59a13d0c86725 100644 --- a/plugin-server/tsconfig.json +++ b/plugin-server/tsconfig.json @@ -19,8 +19,7 @@ "noImplicitAny": true, "useUnknownInCatchVariables": false, "paths": { - "src/*": ["src/*"], - "tests/*": ["tests/*"] + "~/*": ["./*"] } }, "include": ["src", "tests"], From 39f3277ad3df7f55796295e20defec1e66e6f59d Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 12:43:02 +0100 Subject: [PATCH 25/58] Fixes --- .../src/ingestion/ingestion-consumer.test.ts | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 0b78e0525fcda..bd36efe4c23d1 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -129,6 +129,60 @@ describe('IngestionConsumer', () => { it('should process events', async () => { const messages = createKafkaMessages([createEvent()]) await ingester.handleKafkaBatch(messages) + + expect(decodeAllKafkaMessages()).toMatchInlineSnapshot(` + [ + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-19 11:42:38", + "id": "1e7731c8-945c-520d-96b9-e7f088242010", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"01947e5f-3be8-0000-0507-06a17ba519e0","$initial_current_url":"http://localhost:8000"}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "user-1", + "is_deleted": 0, + "person_id": "1e7731c8-945c-520d-96b9-e7f088242010", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "events_dead_letter_queue_test", + "value": { + "distinct_id": "user-1", + "error": "Event ingestion failed. Error: Cannot read properties of undefined (reading 'catch')", + "error_location": "plugin_server_ingest_event:emitEventStep", + "error_timestamp": "2025-01-19 11:42:38", + "event": "$pageview", + "event_uuid": "01947e5f-3be8-0000-0507-06a17ba519e0", + "id": "01947e5f-3c08-0000-2bf7-132f2d57fae8", + "ip": "", + "now": "2025-01-19 11:42:38", + "properties": "{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}", + "raw_payload": "{"distinct_id":"user-1","uuid":"01947e5f-3be8-0000-0507-06a17ba519e0","token":"THIS IS NOT A TOKEN FOR TEAM 2","ip":null,"site_url":"us.posthog.com","now":"2025-01-19T12:42:38.056+01:00","event":"$pageview","properties":{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}}", + "site_url": "us.posthog.com", + "tags": [ + "plugin_server", + "ingest_event", + ], + "team_id": 2, + "token": "THIS IS NOT A TOKEN FOR TEAM 2", + "uuid": "01947e5f-3be8-0000-0507-06a17ba519e0", + }, + }, + ] + `) }) }) }) From 18bb3dddd8a752677a5f6694eacfb34030e9d34e Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 12:53:07 +0100 Subject: [PATCH 26/58] Started adding tests --- .../src/ingestion/ingestion-consumer.test.ts | 34 ++++--------------- .../tests/helpers/mocks/producer.mock.ts | 10 +++--- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index bd36efe4c23d1..0a6e03de0aa2c 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -124,7 +124,10 @@ describe('IngestionConsumer', () => { }) describe('general', () => { - beforeEach(async () => {}) + beforeEach(() => { + // TODO: Freeze time for tests + // TODO: Add helper to replace all UUIDs with simple strings for better test comaprisons + }) it('should process events', async () => { const messages = createKafkaMessages([createEvent()]) @@ -136,11 +139,11 @@ describe('IngestionConsumer', () => { "key": null, "topic": "clickhouse_person_test", "value": { - "created_at": "2025-01-19 11:42:38", + "created_at": "2025-01-19 11:52:53", "id": "1e7731c8-945c-520d-96b9-e7f088242010", "is_deleted": 0, "is_identified": 0, - "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"01947e5f-3be8-0000-0507-06a17ba519e0","$initial_current_url":"http://localhost:8000"}", + "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"01947e68-a1de-0000-a431-3b487e66a0c8","$initial_current_url":"http://localhost:8000"}", "team_id": 2, "version": 0, }, @@ -156,31 +159,6 @@ describe('IngestionConsumer', () => { "version": 0, }, }, - { - "key": null, - "topic": "events_dead_letter_queue_test", - "value": { - "distinct_id": "user-1", - "error": "Event ingestion failed. Error: Cannot read properties of undefined (reading 'catch')", - "error_location": "plugin_server_ingest_event:emitEventStep", - "error_timestamp": "2025-01-19 11:42:38", - "event": "$pageview", - "event_uuid": "01947e5f-3be8-0000-0507-06a17ba519e0", - "id": "01947e5f-3c08-0000-2bf7-132f2d57fae8", - "ip": "", - "now": "2025-01-19 11:42:38", - "properties": "{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}", - "raw_payload": "{"distinct_id":"user-1","uuid":"01947e5f-3be8-0000-0507-06a17ba519e0","token":"THIS IS NOT A TOKEN FOR TEAM 2","ip":null,"site_url":"us.posthog.com","now":"2025-01-19T12:42:38.056+01:00","event":"$pageview","properties":{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}}", - "site_url": "us.posthog.com", - "tags": [ - "plugin_server", - "ingest_event", - ], - "team_id": 2, - "token": "THIS IS NOT A TOKEN FOR TEAM 2", - "uuid": "01947e5f-3be8-0000-0507-06a17ba519e0", - }, - }, ] `) }) diff --git a/plugin-server/tests/helpers/mocks/producer.mock.ts b/plugin-server/tests/helpers/mocks/producer.mock.ts index 5bd3b0fe94d84..a452d6693b239 100644 --- a/plugin-server/tests/helpers/mocks/producer.mock.ts +++ b/plugin-server/tests/helpers/mocks/producer.mock.ts @@ -9,14 +9,14 @@ export type ParsedTopicMessage = { } jest.mock('../../../src/kafka/producer', () => { - const mockKafkaProducer = { - create: jest.fn(() => mockKafkaProducer), + const mockKafkaProducer: jest.Mocked = { producer: { connect: jest.fn(), - }, + } as any, disconnect: jest.fn(), - produce: jest.fn(), - queueMessages: jest.fn(() => Promise.resolve()), + produce: jest.fn().mockReturnValue(Promise.resolve()), + queueMessages: jest.fn().mockReturnValue(Promise.resolve()), + flush: jest.fn().mockReturnValue(Promise.resolve()), } const MockKafkaProducer = { From 63d909d96fe6d7fc3adad4f5eb1b2275a415626e Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 12:53:38 +0100 Subject: [PATCH 27/58] Fix --- plugin-server/tests/helpers/mocks/producer.mock.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin-server/tests/helpers/mocks/producer.mock.ts b/plugin-server/tests/helpers/mocks/producer.mock.ts index 5bd3b0fe94d84..a452d6693b239 100644 --- a/plugin-server/tests/helpers/mocks/producer.mock.ts +++ b/plugin-server/tests/helpers/mocks/producer.mock.ts @@ -9,14 +9,14 @@ export type ParsedTopicMessage = { } jest.mock('../../../src/kafka/producer', () => { - const mockKafkaProducer = { - create: jest.fn(() => mockKafkaProducer), + const mockKafkaProducer: jest.Mocked = { producer: { connect: jest.fn(), - }, + } as any, disconnect: jest.fn(), - produce: jest.fn(), - queueMessages: jest.fn(() => Promise.resolve()), + produce: jest.fn().mockReturnValue(Promise.resolve()), + queueMessages: jest.fn().mockReturnValue(Promise.resolve()), + flush: jest.fn().mockReturnValue(Promise.resolve()), } const MockKafkaProducer = { From 352b849ca0715bd18826a6d52db4241670fd39fc Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 13:02:06 +0100 Subject: [PATCH 28/58] Added helper for sanitizing snapshots --- .../ingestion-consumer.test.ts.snap | 30 ++++++++++++ .../src/ingestion/ingestion-consumer.test.ts | 47 ++++++++----------- 2 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap diff --git a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap new file mode 100644 index 0000000000000..87e23bad82c65 --- /dev/null +++ b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IngestionConsumer general should process events 1`] = ` +[ + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-19 12:01:36", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "user-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, +] +`; diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 0a6e03de0aa2c..1d5a3fa37b87a 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -60,6 +60,24 @@ const decodeAllKafkaMessages = (): DecodedKafkaMessage[] => { return result } +const UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi +const forSnapshot = (obj: any, idMap?: Record) => { + idMap = idMap ?? {} + + // To make snapshot testing way simpler this matches on UUIDs and replaces them with an incrementing ID + + let strData = JSON.stringify(obj) + + const matches = strData.match(UUID_REGEX) + + for (const match of matches ?? []) { + idMap[match] = `` + strData = strData.replace(match, idMap[match]) + } + + return JSON.parse(strData) +} + let offsetIncrementer = 0 const createKafkaMessages: (events: PipelineEvent[]) => Message[] = (events) => { @@ -133,34 +151,7 @@ describe('IngestionConsumer', () => { const messages = createKafkaMessages([createEvent()]) await ingester.handleKafkaBatch(messages) - expect(decodeAllKafkaMessages()).toMatchInlineSnapshot(` - [ - { - "key": null, - "topic": "clickhouse_person_test", - "value": { - "created_at": "2025-01-19 11:52:53", - "id": "1e7731c8-945c-520d-96b9-e7f088242010", - "is_deleted": 0, - "is_identified": 0, - "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"01947e68-a1de-0000-a431-3b487e66a0c8","$initial_current_url":"http://localhost:8000"}", - "team_id": 2, - "version": 0, - }, - }, - { - "key": null, - "topic": "clickhouse_person_distinct_id_test", - "value": { - "distinct_id": "user-1", - "is_deleted": 0, - "person_id": "1e7731c8-945c-520d-96b9-e7f088242010", - "team_id": 2, - "version": 0, - }, - }, - ] - `) + expect(forSnapshot(decodeAllKafkaMessages())).toMatchSnapshot() }) }) }) From 845b12fd0849e69140db8a35e5d865cff6b22621 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 14:11:43 +0100 Subject: [PATCH 29/58] Fixes --- .../ingestion-consumer.test.ts.snap | 27 ++- .../src/ingestion/ingestion-consumer.test.ts | 181 ++++++++++++------ .../src/ingestion/ingestion-consumer.ts | 6 +- .../tests/helpers/mocks/producer.mock.ts | 47 ++++- plugin-server/tests/helpers/snapshots.ts | 18 ++ 5 files changed, 216 insertions(+), 63 deletions(-) create mode 100644 plugin-server/tests/helpers/snapshots.ts diff --git a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap index 87e23bad82c65..73fe2bf013545 100644 --- a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap +++ b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap @@ -1,16 +1,35 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`IngestionConsumer general should process events 1`] = ` +exports[`IngestionConsumer general should process a standard event 1`] = ` [ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "user-1", + "elements_chain": "", + "event": "$pageview", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "project_id": 2, + "properties": "{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, { "key": null, "topic": "clickhouse_person_test", "value": { - "created_at": "2025-01-19 12:01:36", - "id": "", + "created_at": "2025-01-31 23:00:00", + "id": "", "is_deleted": 0, "is_identified": 0, - "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", "team_id": 2, "version": 0, }, diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 1d5a3fa37b87a..991461c787b3b 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -2,11 +2,16 @@ import { DateTime } from 'luxon' import { Message } from 'node-rdkafka' import { UUIDT } from '~/src/utils/utils' -import { getParsedQueuedMessages, mockProducer } from '~/tests/helpers/mocks/producer.mock' +import { + getProducedKafkaMessages, + getProducedKakfaMessagesForTopic, + mockProducer, +} from '~/tests/helpers/mocks/producer.mock' +import { forSnapshot } from '~/tests/helpers/snapshots' import { Hub, PipelineEvent, Team } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' -import { getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' +import { createTeam, createUserTeamAndOrganization, getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' import { IngestionConsumer } from './ingestion-consumer' const mockConsumer = { @@ -36,48 +41,6 @@ jest.mock('../../src/kafka/batch-consumer', () => { jest.setTimeout(1000) -type DecodedKafkaMessage = { - topic: string - key?: any - value: Record -} - -const decodeAllKafkaMessages = (): DecodedKafkaMessage[] => { - const queuedMessages = getParsedQueuedMessages() - - const result: DecodedKafkaMessage[] = [] - - for (const topicMessage of queuedMessages) { - for (const message of topicMessage.messages) { - result.push({ - topic: topicMessage.topic, - key: message.key, - value: message.value ?? {}, - }) - } - } - - return result -} - -const UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi -const forSnapshot = (obj: any, idMap?: Record) => { - idMap = idMap ?? {} - - // To make snapshot testing way simpler this matches on UUIDs and replaces them with an incrementing ID - - let strData = JSON.stringify(obj) - - const matches = strData.match(UUID_REGEX) - - for (const match of matches ?? []) { - idMap[match] = `` - strData = strData.replace(match, idMap[match]) - } - - return JSON.parse(strData) -} - let offsetIncrementer = 0 const createKafkaMessages: (events: PipelineEvent[]) => Message[] = (events) => { @@ -105,6 +68,7 @@ describe('IngestionConsumer', () => { let ingester: IngestionConsumer let hub: Hub let team: Team + let team2: Team const createEvent = (event?: Partial): PipelineEvent => ({ distinct_id: 'user-1', @@ -121,19 +85,24 @@ describe('IngestionConsumer', () => { }) beforeEach(async () => { + const now = new Date(2025, 1, 1).getTime() + jest.spyOn(Date, 'now').mockReturnValue(now) offsetIncrementer = 0 await resetTestDatabase() hub = await createHub() + hub.kafkaProducer = mockProducer team = await getFirstTeam(hub) - - ingester = new IngestionConsumer(hub) - await ingester.start() + const team2Id = await createTeam(hub.db.postgres, team.organization_id) + team2 = (await hub.db.fetchTeam(team2Id)) as Team }) afterEach(async () => { + jest.restoreAllMocks() jest.setTimeout(10000) - await ingester.stop() + if (ingester) { + await ingester.stop() + } await closeHub(hub) }) @@ -142,16 +111,118 @@ describe('IngestionConsumer', () => { }) describe('general', () => { - beforeEach(() => { - // TODO: Freeze time for tests - // TODO: Add helper to replace all UUIDs with simple strings for better test comaprisons + beforeEach(async () => { + ingester = new IngestionConsumer(hub) + await ingester.start() + }) + it('should process a standard event', async () => { + await ingester.handleKafkaBatch(createKafkaMessages([createEvent()])) + + expect(forSnapshot(getProducedKafkaMessages())).toMatchSnapshot() }) + }) - it('should process events', async () => { - const messages = createKafkaMessages([createEvent()]) - await ingester.handleKafkaBatch(messages) + describe('dropping events', () => { + describe.each(['headers', 'payload'] as const)('via %s', (kind) => { + const addMessageHeaders = (message: Message, token?: string, distinctId?: string) => { + if (kind !== 'headers') { + return + } + message.headers = [] + + if (distinctId) { + message.headers.push({ + key: 'distinct_id', + value: Buffer.from(distinctId), + }) + } + if (token) { + message.headers.push({ + key: 'token', + value: Buffer.from(token), + }) + } + } + + describe('with DROP_EVENTS_BY_TOKEN', () => { + beforeEach(async () => { + hub.DROP_EVENTS_BY_TOKEN = `${team.api_token},phc_other` + ingester = new IngestionConsumer(hub) + await ingester.start() + }) + it('should drop events with matching token', async () => { + const messages = createKafkaMessages([createEvent({}), createEvent({})]) + addMessageHeaders(messages[0], team.api_token) + await ingester.handleKafkaBatch(messages) + expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) + }) + + it('should not drop events for a different team token', async () => { + const messages = createKafkaMessages([createEvent({ token: team2.api_token })]) + addMessageHeaders(messages[0], team2.api_token) + await ingester.handleKafkaBatch(messages) + expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + }) + + it('should only drop events in batch matching', async () => { + const messages = createKafkaMessages([ + createEvent({ token: team.api_token }), + createEvent({ token: team2.api_token, distinct_id: 'team2-distinct-id' }), + createEvent({ token: team.api_token }), + ]) + addMessageHeaders(messages[0], team.api_token) + addMessageHeaders(messages[1], team2.api_token) + addMessageHeaders(messages[2], team.api_token) + await ingester.handleKafkaBatch(messages) + const eventsMessages = getProducedKakfaMessagesForTopic('clickhouse_events_json_test') + expect(eventsMessages).toHaveLength(1) + expect(eventsMessages[0].value).toMatchObject({ + team_id: team2.id, + distinct_id: 'team2-distinct-id', + }) + }) + }) - expect(forSnapshot(decodeAllKafkaMessages())).toMatchSnapshot() + describe('with DROP_EVENTS_BY_TOKEN_DISTINCT_ID', () => { + beforeEach(async () => { + hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID = `${team.api_token}:distinct-id-to-ignore,phc_other:distinct-id-to-ignore` + ingester = new IngestionConsumer(hub) + await ingester.start() + }) + it('should drop events with matching token and distinct_id', async () => { + const messages = createKafkaMessages([ + createEvent({ + distinct_id: 'distinct-id-to-ignore', + }), + ]) + addMessageHeaders(messages[0], team.api_token, 'distinct-id-to-ignore') + await ingester.handleKafkaBatch(messages) + expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) + }) + + it('should not drop events for a different team token', async () => { + const messages = createKafkaMessages([ + createEvent({ + token: team2.api_token, + distinct_id: 'distinct-id-to-ignore', + }), + ]) + addMessageHeaders(messages[0], team2.api_token, 'distinct-id-to-ignore') + await ingester.handleKafkaBatch(messages) + expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + }) + + it('should not drop events for a different distinct_id', async () => { + const messages = createKafkaMessages([ + createEvent({ + distinct_id: 'other-id', + }), + ]) + addMessageHeaders(messages[0], team.api_token, 'not-ignored') + await ingester.handleKafkaBatch(messages) + expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + }) + }) }) }) }) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index cd647bc56dc77..34a870cd4408d 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -71,8 +71,8 @@ export class IngestionConsumer { this.topic = hub.INGESTION_CONSUMER_CONSUME_TOPIC this.overflowTopic = hub.INGESTION_CONSUMER_OVERFLOW_TOPIC this.dlqTopic = hub.INGESTION_CONSUMER_DLQ_TOPIC - this.tokensToDrop = hub.DROP_EVENTS_BY_TOKEN.split(',') - this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',') + this.tokensToDrop = hub.DROP_EVENTS_BY_TOKEN.split(',').filter((x) => !!x) + this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',').filter((x) => !!x) this.name = `ingestion-consumer-${this.topic}` } @@ -372,7 +372,7 @@ export class IngestionConsumer { private shouldDropEvent(token?: string, distinctId?: string) { return ( (token && this.tokensToDrop.includes(token)) || - (distinctId && this.tokenDistinctIdsToDrop.includes(`${token}:${distinctId}`)) + (token && distinctId && this.tokenDistinctIdsToDrop.includes(`${token}:${distinctId}`)) ) } diff --git a/plugin-server/tests/helpers/mocks/producer.mock.ts b/plugin-server/tests/helpers/mocks/producer.mock.ts index a452d6693b239..2d3ab4db84f56 100644 --- a/plugin-server/tests/helpers/mocks/producer.mock.ts +++ b/plugin-server/tests/helpers/mocks/producer.mock.ts @@ -8,6 +8,12 @@ export type ParsedTopicMessage = { }[] } +export type DecodedKafkaMessage = { + topic: string + key?: any + value: Record +} + jest.mock('../../../src/kafka/producer', () => { const mockKafkaProducer: jest.Mocked = { producer: { @@ -36,8 +42,25 @@ export const getQueuedMessages = (): TopicMessage[] => { }, [] as TopicMessage[]) } +export const getProducedMessages = (): TopicMessage[] => { + return jest.mocked(mockProducer).produce.mock.calls.reduce((acc, call) => { + return acc.concat([ + { + topic: call[0].topic, + messages: [ + { + key: call[0].key, + value: call[0].value, + }, + ], + }, + ]) + }, [] as TopicMessage[]) +} + export const getParsedQueuedMessages = (): ParsedTopicMessage[] => { - return getQueuedMessages().map((topicMessage) => ({ + const allMessages = getProducedMessages().concat(getQueuedMessages()) + return allMessages.map((topicMessage) => ({ topic: topicMessage.topic, messages: topicMessage.messages.map((message) => ({ key: typeof message.key === 'string' ? message.key : null, @@ -45,3 +68,25 @@ export const getParsedQueuedMessages = (): ParsedTopicMessage[] => { })), })) } + +export const getProducedKafkaMessages = (): DecodedKafkaMessage[] => { + const queuedMessages = getParsedQueuedMessages() + + const result: DecodedKafkaMessage[] = [] + + for (const topicMessage of queuedMessages) { + for (const message of topicMessage.messages) { + result.push({ + topic: topicMessage.topic, + key: message.key, + value: message.value ?? {}, + }) + } + } + + return result +} + +export const getProducedKakfaMessagesForTopic = (topic: string): DecodedKafkaMessage[] => { + return getProducedKafkaMessages().filter((x) => x.topic === topic) +} diff --git a/plugin-server/tests/helpers/snapshots.ts b/plugin-server/tests/helpers/snapshots.ts new file mode 100644 index 0000000000000..6943a6802974a --- /dev/null +++ b/plugin-server/tests/helpers/snapshots.ts @@ -0,0 +1,18 @@ +const UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi + +/** + * Helper method that takes an object and replaces all UUIDs with placeholders + */ +export const forSnapshot = (obj: any) => { + const idMap: Record = {} + let strData = JSON.stringify(obj) + + const matches = strData.match(UUID_REGEX) + + for (const match of matches ?? []) { + idMap[match] = `` + strData = strData.replace(match, idMap[match]) + } + + return JSON.parse(strData) +} From d9c6b83e700b95330bcefa470e2e06abde226c7c Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 14:13:01 +0100 Subject: [PATCH 30/58] fixes --- .../src/ingestion/ingestion-consumer.test.ts | 2 +- .../tests/cdp/cdp-events-consumer.test.ts | 34 +++---------------- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 991461c787b3b..024d79f84a87b 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -11,7 +11,7 @@ import { forSnapshot } from '~/tests/helpers/snapshots' import { Hub, PipelineEvent, Team } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' -import { createTeam, createUserTeamAndOrganization, getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' +import { createTeam, getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' import { IngestionConsumer } from './ingestion-consumer' const mockConsumer = { diff --git a/plugin-server/tests/cdp/cdp-events-consumer.test.ts b/plugin-server/tests/cdp/cdp-events-consumer.test.ts index f716522311dd6..4a552840aad39 100644 --- a/plugin-server/tests/cdp/cdp-events-consumer.test.ts +++ b/plugin-server/tests/cdp/cdp-events-consumer.test.ts @@ -3,7 +3,7 @@ import { HogWatcherState } from '../../src/cdp/hog-watcher' import { HogFunctionInvocationGlobals, HogFunctionType } from '../../src/cdp/types' import { Hub, Team } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' -import { getParsedQueuedMessages, mockProducer } from '../helpers/mocks/producer.mock' +import { getProducedKafkaMessages, mockProducer } from '../helpers/mocks/producer.mock' import { getFirstTeam, resetTestDatabase } from '../helpers/sql' import { HOG_EXAMPLES, HOG_FILTERS_EXAMPLES, HOG_INPUTS_EXAMPLES } from './examples' import { createHogExecutionGlobals, insertHogFunction as _insertHogFunction } from './fixtures' @@ -49,30 +49,6 @@ const mockFetch: jest.Mock = require('../../src/utils/fetch').trackedFetch jest.setTimeout(1000) -type DecodedKafkaMessage = { - topic: string - key?: any - value: Record -} - -const decodeAllKafkaMessages = (): DecodedKafkaMessage[] => { - const queuedMessages = getParsedQueuedMessages() - - const result: DecodedKafkaMessage[] = [] - - for (const topicMessage of queuedMessages) { - for (const message of topicMessage.messages) { - result.push({ - topic: topicMessage.topic, - key: message.key, - value: message.value ?? {}, - }) - } - } - - return result -} - /** * NOTE: The internal and normal events consumers are very similar so we can test them together */ @@ -171,7 +147,7 @@ describe.each([ matchInvocation(fnPrinterPageviewFilters, globals), ]) - expect(decodeAllKafkaMessages()).toMatchObject([ + expect(getProducedKafkaMessages()).toMatchObject([ { topic: 'log_entries_test', value: { @@ -275,7 +251,7 @@ describe.each([ expect(invocations).toHaveLength(1) expect(invocations).toMatchObject([matchInvocation(fnFetchNoFilters, globals)]) - expect(decodeAllKafkaMessages()).toMatchObject([ + expect(getProducedKafkaMessages()).toMatchObject([ { key: expect.any(String), topic: 'clickhouse_app_metrics2_test', @@ -316,7 +292,7 @@ describe.each([ expect(invocations).toHaveLength(0) expect(mockProducer.queueMessages).toHaveBeenCalledTimes(1) - expect(decodeAllKafkaMessages()).toMatchObject([ + expect(getProducedKafkaMessages()).toMatchObject([ { topic: 'clickhouse_app_metrics2_test', value: { @@ -369,7 +345,7 @@ describe.each([ ...HOG_FILTERS_EXAMPLES.broken_filters, }) await processor.processBatch([globals]) - expect(decodeAllKafkaMessages()).toMatchObject([ + expect(getProducedKafkaMessages()).toMatchObject([ { key: expect.any(String), topic: 'clickhouse_app_metrics2_test', From aa4cdac8d0f5f06d1bd3156dce5a42db126ea5d6 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 14:14:23 +0100 Subject: [PATCH 31/58] fix config check --- plugin-server/src/ingestion/ingestion-consumer.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 024d79f84a87b..9cc10c05d5afe 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -115,6 +115,15 @@ describe('IngestionConsumer', () => { ingester = new IngestionConsumer(hub) await ingester.start() }) + + it('should have the correct config', () => { + expect(ingester['name']).toMatchInlineSnapshot(`"ingestion-consumer-events_plugin_ingestion_test"`) + expect(ingester['groupId']).toMatchInlineSnapshot(`"events-ingestion-consumer"`) + expect(ingester['topic']).toMatchInlineSnapshot(`"events_plugin_ingestion_test"`) + expect(ingester['dlqTopic']).toMatchInlineSnapshot(`"events_plugin_ingestion_dlq_test"`) + expect(ingester['overflowTopic']).toMatchInlineSnapshot(`"events_plugin_ingestion_overflow_test"`) + }) + it('should process a standard event', async () => { await ingester.handleKafkaBatch(createKafkaMessages([createEvent()])) From cb4f6ca374e2cc63a282dc38135d571701bafed5 Mon Sep 17 00:00:00 2001 From: Ben White Date: Sun, 19 Jan 2025 14:35:15 +0100 Subject: [PATCH 32/58] Added good tests for drpping logs --- .../src/ingestion/ingestion-consumer.test.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 9cc10c05d5afe..7abd0b3dfb410 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -12,6 +12,7 @@ import { forSnapshot } from '~/tests/helpers/snapshots' import { Hub, PipelineEvent, Team } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' import { createTeam, getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' +import { status } from '../utils/status' import { IngestionConsumer } from './ingestion-consumer' const mockConsumer = { @@ -153,17 +154,36 @@ describe('IngestionConsumer', () => { } } + beforeEach(() => { + jest.spyOn(status, 'debug') + }) + + const expectDropLogs = (pairs: [string, string | undefined][]) => { + expect(jest.mocked(status.debug)).toHaveBeenCalledTimes(pairs.length) + for (const [token, distinctId] of pairs) { + expect(jest.mocked(status.debug)).toHaveBeenCalledWith('🔁', 'Dropped event', { + distinctId, + token, + }) + } + } + describe('with DROP_EVENTS_BY_TOKEN', () => { beforeEach(async () => { hub.DROP_EVENTS_BY_TOKEN = `${team.api_token},phc_other` ingester = new IngestionConsumer(hub) await ingester.start() }) + it('should drop events with matching token', async () => { const messages = createKafkaMessages([createEvent({}), createEvent({})]) addMessageHeaders(messages[0], team.api_token) await ingester.handleKafkaBatch(messages) expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) + expectDropLogs([ + [team.api_token, 'user-1'], + [team.api_token, 'user-1'], + ]) }) it('should not drop events for a different team token', async () => { @@ -171,6 +191,7 @@ describe('IngestionConsumer', () => { addMessageHeaders(messages[0], team2.api_token) await ingester.handleKafkaBatch(messages) expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + expectDropLogs([]) }) it('should only drop events in batch matching', async () => { @@ -189,6 +210,10 @@ describe('IngestionConsumer', () => { team_id: team2.id, distinct_id: 'team2-distinct-id', }) + expectDropLogs([ + [team.api_token, kind === 'headers' ? undefined : 'user-1'], + [team.api_token, kind === 'headers' ? undefined : 'user-1'], + ]) }) }) @@ -207,6 +232,7 @@ describe('IngestionConsumer', () => { addMessageHeaders(messages[0], team.api_token, 'distinct-id-to-ignore') await ingester.handleKafkaBatch(messages) expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) + expectDropLogs([[team.api_token, 'distinct-id-to-ignore']]) }) it('should not drop events for a different team token', async () => { @@ -219,6 +245,7 @@ describe('IngestionConsumer', () => { addMessageHeaders(messages[0], team2.api_token, 'distinct-id-to-ignore') await ingester.handleKafkaBatch(messages) expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + expectDropLogs([]) }) it('should not drop events for a different distinct_id', async () => { @@ -230,6 +257,7 @@ describe('IngestionConsumer', () => { addMessageHeaders(messages[0], team.api_token, 'not-ignored') await ingester.handleKafkaBatch(messages) expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + expectDropLogs([]) }) }) }) From c4be5b34a0acff89b68d0578763e1be0977472b3 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 20 Jan 2025 15:23:02 +0100 Subject: [PATCH 33/58] Fixes --- .../session-recording-v2/batch-consumer-factory.ts | 2 +- .../src/main/ingestion-queues/session-recording-v2/consumer.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-server/src/main/ingestion-queues/session-recording-v2/batch-consumer-factory.ts b/plugin-server/src/main/ingestion-queues/session-recording-v2/batch-consumer-factory.ts index b6e3de2368ddd..b9afcee0613fc 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording-v2/batch-consumer-factory.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording-v2/batch-consumer-factory.ts @@ -27,7 +27,7 @@ export class DefaultBatchConsumerFactory implements BatchConsumerFactory { topic: string, eachBatch: EachBatchHandler ): Promise { - const connectionConfig = createRdConnectionConfigFromEnvVars(this.kafkaConfig) + const connectionConfig = createRdConnectionConfigFromEnvVars(this.kafkaConfig, 'consumer') // Create a node-rdkafka consumer that fetches batches of messages, runs // eachBatch with context, then commits offsets for the batch. // the batch consumer reads from the session replay kafka cluster diff --git a/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts b/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts index c9c6de557d34e..c8842c51032fc 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts @@ -1,10 +1,10 @@ import { captureException } from '@sentry/node' +import { KafkaProducerWrapper } from 'kafka/producer' import { CODES, features, KafkaConsumer, librdkafkaVersion, Message, TopicPartition } from 'node-rdkafka' import { buildIntegerMatcher } from '../../../config/config' import { BatchConsumer } from '../../../kafka/batch-consumer' import { PluginServerService, PluginsServerConfig, ValueMatcher } from '../../../types' -import { KafkaProducerWrapper } from '../../../utils/db/kafka-producer-wrapper' import { status as logger } from '../../../utils/status' import { captureIngestionWarning } from '../../../worker/ingestion/utils' import { runInstrumentedFunction } from '../../utils' From 0f80ba7650904c5533eab6ba3bb4381d24fb22fe Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 20 Jan 2025 15:30:19 +0100 Subject: [PATCH 34/58] Fixes imports --- plugin-server/src/ingestion/ingestion-consumer.test.ts | 2 +- .../src/main/ingestion-queues/session-recording-v2/consumer.ts | 3 ++- plugin-server/src/main/services/http-server.ts | 3 ++- plugin-server/src/types.ts | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 7abd0b3dfb410..c81935ca3f796 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -8,10 +8,10 @@ import { mockProducer, } from '~/tests/helpers/mocks/producer.mock' import { forSnapshot } from '~/tests/helpers/snapshots' +import { createTeam, getFirstTeam, resetTestDatabase } from '~/tests/helpers/sql' import { Hub, PipelineEvent, Team } from '../../src/types' import { closeHub, createHub } from '../../src/utils/db/hub' -import { createTeam, getFirstTeam, resetTestDatabase } from '../../tests/helpers/sql' import { status } from '../utils/status' import { IngestionConsumer } from './ingestion-consumer' diff --git a/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts b/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts index c8842c51032fc..183060b449372 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts @@ -1,7 +1,8 @@ import { captureException } from '@sentry/node' -import { KafkaProducerWrapper } from 'kafka/producer' import { CODES, features, KafkaConsumer, librdkafkaVersion, Message, TopicPartition } from 'node-rdkafka' +import { KafkaProducerWrapper } from '~/src/kafka/producer' + import { buildIntegerMatcher } from '../../../config/config' import { BatchConsumer } from '../../../kafka/batch-consumer' import { PluginServerService, PluginsServerConfig, ValueMatcher } from '../../../types' diff --git a/plugin-server/src/main/services/http-server.ts b/plugin-server/src/main/services/http-server.ts index f64bdde00cf36..8217a8d0fc881 100644 --- a/plugin-server/src/main/services/http-server.ts +++ b/plugin-server/src/main/services/http-server.ts @@ -1,7 +1,8 @@ import express, { Request, Response } from 'express' import { DateTime } from 'luxon' import * as prometheus from 'prom-client' -import { PluginServerService } from 'types' + +import { PluginServerService } from '~/src/types' import { status } from '../../utils/status' import { delay } from '../../utils/utils' diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 2c783ae10f079..f38c10ca1a646 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -13,12 +13,12 @@ import { } from '@posthog/plugin-scaffold' import { Pool as GenericPool } from 'generic-pool' import { Redis } from 'ioredis' -import { BatchConsumer } from 'kafka/batch-consumer' import { Kafka } from 'kafkajs' import { DateTime } from 'luxon' import { VM } from 'vm2' import { EncryptedFields } from './cdp/encryption-utils' +import { BatchConsumer } from './kafka/batch-consumer' import { KafkaProducerWrapper } from './kafka/producer' import { ObjectStorage } from './main/services/object_storage' import { Celery } from './utils/db/celery' From 87595164e3906a3815280a20f1269226447e8317 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 20 Jan 2025 17:20:21 +0100 Subject: [PATCH 35/58] Fix types compiling --- plugin-server/package.json | 3 +-- plugin-server/src/utils/db/utils.ts | 3 ++- .../worker/ingestion/event-pipeline/prepareEventStep.ts | 3 ++- .../worker/ingestion/event-pipeline/processPersonsStep.ts | 3 ++- plugin-server/src/worker/piscina.ts | 3 ++- plugin-server/src/worker/vm/extensions/posthog.ts | 3 ++- plugin-server/tests/helpers/sql.ts | 4 ++-- plugin-server/tsconfig.json | 7 +++++-- 8 files changed, 18 insertions(+), 11 deletions(-) diff --git a/plugin-server/package.json b/plugin-server/package.json index c324b9a8e94c5..f8fb582cd5295 100644 --- a/plugin-server/package.json +++ b/plugin-server/package.json @@ -12,11 +12,10 @@ "start:dist": "BASE_DIR=.. node dist/index.js", "start:dev": "NODE_ENV=dev BASE_DIR=.. nodemon --watch src/ --exec node -r @swc-node/register src/index.ts", "start:devNoWatch": "NODE_ENV=dev BASE_DIR=.. node -r @swc-node/register src/index.ts", - "build": "pnpm clean && pnpm compile", + "build": "pnpm clean && pnpm typescript:compile", "clean": "rm -rf dist/* && rm -rf ../rust/cyclotron-node/index.node", "typescript:compile": "tsc -b", "typescript:check": "tsc --noEmit -p .", - "compile": "pnpm typescript:compile", "lint": "eslint .", "lint:fix": "eslint --fix .", "prettier": "prettier --write .", diff --git a/plugin-server/src/utils/db/utils.ts b/plugin-server/src/utils/db/utils.ts index f0204f0ef4c77..946b3f68de1dc 100644 --- a/plugin-server/src/utils/db/utils.ts +++ b/plugin-server/src/utils/db/utils.ts @@ -1,8 +1,9 @@ import { Properties } from '@posthog/plugin-scaffold' import * as Sentry from '@sentry/node' -import { TopicMessage } from 'kafka/producer' import { Counter } from 'prom-client' +import { TopicMessage } from '~/src/kafka/producer' + import { defaultConfig } from '../../config/config' import { KAFKA_PERSON } from '../../config/kafka-topics' import { diff --git a/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts index 6725bbf345661..8754e2b744070 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/prepareEventStep.ts @@ -1,5 +1,6 @@ import { PluginEvent } from '@posthog/plugin-scaffold' -import { PreIngestionEvent } from 'types' + +import { PreIngestionEvent } from '~/src/types' import { parseEventTimestamp } from '../timestamps' import { captureIngestionWarning } from '../utils' diff --git a/plugin-server/src/worker/ingestion/event-pipeline/processPersonsStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/processPersonsStep.ts index 28f6961e36940..0abfb266a9fe0 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/processPersonsStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/processPersonsStep.ts @@ -1,6 +1,7 @@ import { PluginEvent } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' -import { Person } from 'types' + +import { Person } from '~/src/types' import { PersonState } from '../person-state' import { EventPipelineRunner } from './runner' diff --git a/plugin-server/src/worker/piscina.ts b/plugin-server/src/worker/piscina.ts index 87f3eff154eca..b8ab796c0a987 100644 --- a/plugin-server/src/worker/piscina.ts +++ b/plugin-server/src/worker/piscina.ts @@ -1,5 +1,6 @@ import * as Sentry from '@sentry/node' -import { Hub, PluginsServerConfig } from 'types' + +import { Hub, PluginsServerConfig } from '~/src/types' import { createWorker } from './worker' diff --git a/plugin-server/src/worker/vm/extensions/posthog.ts b/plugin-server/src/worker/vm/extensions/posthog.ts index 7cf98dd81a939..ff861ba35d12e 100644 --- a/plugin-server/src/worker/vm/extensions/posthog.ts +++ b/plugin-server/src/worker/vm/extensions/posthog.ts @@ -2,7 +2,8 @@ import { Properties } from '@posthog/plugin-scaffold' import crypto from 'crypto' import { DateTime } from 'luxon' import { Counter } from 'prom-client' -import { Hub, PluginConfig, RawEventMessage } from 'types' + +import { Hub, PluginConfig, RawEventMessage } from '~/src/types' import { UUIDT } from '../../../utils/utils' import { ApiExtension, createApi } from './api' diff --git a/plugin-server/tests/helpers/sql.ts b/plugin-server/tests/helpers/sql.ts index 751bdd9692c30..259f7055c9c42 100644 --- a/plugin-server/tests/helpers/sql.ts +++ b/plugin-server/tests/helpers/sql.ts @@ -50,7 +50,7 @@ export async function resetTestDatabase( { withExtendedTestData = true }: { withExtendedTestData?: boolean } = {} ): Promise { const config = { ...defaultConfig, ...extraServerConfig, POSTGRES_CONNECTION_POOL_SIZE: 1 } - const db = new PostgresRouter(config, undefined) + const db = new PostgresRouter(config) await db.query(PostgresUse.COMMON_WRITE, POSTGRES_DELETE_TABLES_QUERY, undefined, 'delete-tables') const mocks = makePluginObjects(code) @@ -271,7 +271,7 @@ export async function getTeams(hub: Hub): Promise { 'fetchAllTeams' ) for (const row of selectResult.rows) { - row.project_id = parseInt(row.project_id as unknown as string) + row.project_id = parseInt(row.project_id as unknown as string) as ProjectId } return selectResult.rows } diff --git a/plugin-server/tsconfig.json b/plugin-server/tsconfig.json index 59a13d0c86725..b0bf9f8ce348b 100644 --- a/plugin-server/tsconfig.json +++ b/plugin-server/tsconfig.json @@ -19,9 +19,12 @@ "noImplicitAny": true, "useUnknownInCatchVariables": false, "paths": { - "~/*": ["./*"] + "~/*": ["./*"], + "main/*": ["./src/main/*"], + "worker/*": ["./src/worker/*"], + "utils/*": ["./src/utils/*"] } }, - "include": ["src", "tests"], + "include": ["src"], "exclude": ["node_modules", "dist", "bin"] } From 6860d0deedf3738e25096aba6a6ebe3d9259f02d Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 20 Jan 2025 17:46:56 +0100 Subject: [PATCH 36/58] Fix --- plugin-server/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/tsconfig.json b/plugin-server/tsconfig.json index 6ffed7faa8d4d..02238bc1c63a5 100644 --- a/plugin-server/tsconfig.json +++ b/plugin-server/tsconfig.json @@ -24,5 +24,5 @@ } }, "include": ["src"], - "exclude": ["node_modules", "dist", "bin"] + "exclude": ["node_modules", "dist", "bin", "src/**/*.test.ts"] } From 154276006f29629e9fa51e60375276c4a6128557 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 20 Jan 2025 17:47:15 +0100 Subject: [PATCH 37/58] Fix --- plugin-server/src/types.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index e8b179ff07bb6..f38c10ca1a646 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -17,8 +17,6 @@ import { Kafka } from 'kafkajs' import { DateTime } from 'luxon' import { VM } from 'vm2' -import { BatchConsumer } from '~/src/kafka/batch-consumer' - import { EncryptedFields } from './cdp/encryption-utils' import { BatchConsumer } from './kafka/batch-consumer' import { KafkaProducerWrapper } from './kafka/producer' From b8c1bf9b4c5e608b85453dff6b9bafdeddc746d9 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:01:49 +0000 Subject: [PATCH 38/58] Update UI snapshots for `chromium` (1) --- ...uccess--second-recording-in-list--dark.png | Bin 118501 -> 119204 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png b/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png index 4d5c533689f81c2f3f543857d28626df7d450702..0dafd0bfb09a955d74046cbc052becae0449097b 100644 GIT binary patch literal 119204 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 z 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

b6=;qLFslN6a)R5EsE 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 Date: Tue, 21 Jan 2025 11:18:12 +0100 Subject: [PATCH 39/58] fix --- plugin-server/src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index a445de20602c6..44a2f53d5190f 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -18,6 +18,7 @@ import { DateTime } from 'luxon' import { VM } from 'vm2' import { EncryptedFields } from './cdp/encryption-utils' +import { BatchConsumer } from './kafka/batch-consumer' import { KafkaProducerWrapper } from './kafka/producer' import { ObjectStorage } from './main/services/object_storage' import { Celery } from './utils/db/celery' From c3b47c912b2169658b0acff657381463a7f90b27 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 11:18:55 +0100 Subject: [PATCH 40/58] fix --- .../src/main/ingestion-queues/session-recording-v2/consumer.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts b/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts index 18a513b29ab0b..183060b449372 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording-v2/consumer.ts @@ -1,5 +1,4 @@ import { captureException } from '@sentry/node' -import { KafkaProducerWrapper } from 'kafka/producer' import { CODES, features, KafkaConsumer, librdkafkaVersion, Message, TopicPartition } from 'node-rdkafka' import { KafkaProducerWrapper } from '~/src/kafka/producer' From 1fa3395254149e1078b90119523c8ce51067126a Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 10:19:41 +0000 Subject: [PATCH 41/58] Update UI snapshots for `chromium` (1) --- ...uccess--second-recording-in-list--dark.png | Bin 119204 -> 118591 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png b/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png index 0dafd0bfb09a955d74046cbc052becae0449097b..d0d0da1839a6d088138af82e0e3d943cf85893de 100644 GIT binary patch delta 65141 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

>>3J!S1z*Ai|Z4s4lBfdqg87C}Z}Y!N>9 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%0A=Wl$QlM)wy#LzH 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 F{|EE&c7Xr@ From d46a653aaa8d48bcd016719ea660d629ca3245db Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 10:38:27 +0000 Subject: [PATCH 42/58] Update UI snapshots for `chromium` (1) --- ...uccess--second-recording-in-list--dark.png | Bin 118591 -> 119234 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png b/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png index d0d0da1839a6d088138af82e0e3d943cf85893de..b32bad3a8af4f4d7e66c7cbd816a2ed9345b148c 100644 GIT binary patch delta 65894 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

>>3J!S1z*Ai|Z4s4lBfdqg87C}Z}Y!N>9 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

(@GK2lV;XIIHiTCw<8j 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 delta 65141 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 From 0353b863024af5221e0b5cd1b6ed9feccc943d41 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 11:51:57 +0100 Subject: [PATCH 43/58] Fix skip logic --- plugin-server/src/config/config.ts | 1 + plugin-server/src/types.ts | 2 ++ plugin-server/src/utils/db/hub.ts | 3 +++ .../ingestion/event-pipeline/populateTeamDataStep.ts | 7 ++++++- .../src/worker/ingestion/event-pipeline/runner.ts | 1 + 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/plugin-server/src/config/config.ts b/plugin-server/src/config/config.ts index 4c2ae5eba4f7a..ee1a27d4204cd 100644 --- a/plugin-server/src/config/config.ts +++ b/plugin-server/src/config/config.ts @@ -127,6 +127,7 @@ export function getDefaultConfig(): PluginsServerConfig { EXTERNAL_REQUEST_TIMEOUT_MS: 10 * 1000, // 10 seconds DROP_EVENTS_BY_TOKEN_DISTINCT_ID: '', DROP_EVENTS_BY_TOKEN: '', + SKIP_PERSONS_PROCESSING_BY_TOKEN_DISTINCT_ID: '', PIPELINE_STEP_STALLED_LOG_TIMEOUT: 30, RELOAD_PLUGIN_JITTER_MAX_MS: 60000, RUSTY_HOOK_FOR_TEAMS: '', diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index bbfdbef38d4cc..9bf236ebe0aeb 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -250,6 +250,7 @@ export interface PluginsServerConfig extends CdpConfig { EXTERNAL_REQUEST_TIMEOUT_MS: number DROP_EVENTS_BY_TOKEN_DISTINCT_ID: string DROP_EVENTS_BY_TOKEN: string + SKIP_PERSONS_PROCESSING_BY_TOKEN_DISTINCT_ID: string RELOAD_PLUGIN_JITTER_MAX_MS: number RUSTY_HOOK_FOR_TEAMS: string RUSTY_HOOK_ROLLOUT_PERCENTAGE: number @@ -349,6 +350,7 @@ export interface Hub extends PluginsServerConfig { pluginConfigsToSkipElementsParsing: ValueMatcher // lookups eventsToDropByToken: Map + eventsToSkipPersonsProcessingByToken: Map encryptedFields: EncryptedFields } diff --git a/plugin-server/src/utils/db/hub.ts b/plugin-server/src/utils/db/hub.ts index c646d5cb62046..b01f7b0afb2ea 100644 --- a/plugin-server/src/utils/db/hub.ts +++ b/plugin-server/src/utils/db/hub.ts @@ -189,6 +189,9 @@ export async function createHub( actionManager, pluginConfigsToSkipElementsParsing: buildIntegerMatcher(process.env.SKIP_ELEMENTS_PARSING_PLUGINS, true), eventsToDropByToken: createEventsToDropByToken(process.env.DROP_EVENTS_BY_TOKEN_DISTINCT_ID), + eventsToSkipPersonsProcessingByToken: createEventsToDropByToken( + process.env.SKIP_PERSONS_PROCESSING_BY_TOKEN_DISTINCT_ID + ), appMetrics: new AppMetrics( kafkaProducer, serverConfig.APP_METRICS_FLUSH_FREQUENCY_MS, diff --git a/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts index 042eb197122a3..9b9bcd20b9fea 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts @@ -68,11 +68,16 @@ export async function populateTeamDataStep( throw new Error(`Not a valid UUID: "${event.uuid}"`) } + const skipPersonsProcessingForDistinctIds = runner.hub.eventsToSkipPersonsProcessingByToken.get(event.token!) + + const forceOptOutPersonProfiles = + !!team.person_processing_opt_out || skipPersonsProcessingForDistinctIds?.includes(event.distinct_id) + // We allow teams to set the person processing mode on a per-event basis, but override // it with the team-level setting, if it's set to opt-out (since this is billing related, // we go with preferring not to do the processing even if the event says to do it, if the // setting says not to). - if (team.person_processing_opt_out) { + if (forceOptOutPersonProfiles) { if (event.properties) { event.properties.$process_person_profile = false } else { diff --git a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts index 6d70e62398f5a..e920bec7f9300 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts @@ -143,6 +143,7 @@ export class EventPipelineRunner { const kafkaAcks: Promise[] = [] let processPerson = true // The default. + // Set either at capture time, or in the populateTeamData step, if team-level opt-out is enabled. if (event.properties && '$process_person_profile' in event.properties) { const propValue = event.properties.$process_person_profile From d97f65f4084cf23ebbcc1a01b09e075c78e5b7ae Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 11:58:48 +0100 Subject: [PATCH 44/58] Added test --- .../event-pipeline/populateTeamDataStep.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/populateTeamDataStep.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/populateTeamDataStep.test.ts index 294dc34854937..6bef5b6248ffd 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/populateTeamDataStep.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/populateTeamDataStep.test.ts @@ -1,4 +1,5 @@ import { PipelineEvent, Team } from '../../../../src/types' +import { createEventsToDropByToken } from '../../../../src/utils/db/hub' import { UUIDT } from '../../../../src/utils/utils' import { populateTeamDataStep } from '../../../../src/worker/ingestion/event-pipeline/populateTeamDataStep' import { getMetricValues, resetMetrics } from '../../../helpers/metrics' @@ -34,6 +35,7 @@ beforeEach(() => { resetMetrics() runner = { hub: { + eventsToSkipPersonsProcessingByToken: createEventsToDropByToken('2:distinct_id_to_drop'), teamManager: { getTeamByToken: jest.fn((token) => { return token === teamTwoToken ? teamTwo : null @@ -108,7 +110,13 @@ describe('populateTeamDataStep()', () => { it('event with a team_id whose team is opted-out from person processing', async () => { const input = { ...pipelineEvent, team_id: 3 } const response = await populateTeamDataStep(runner, input) - expect(response.properties.$process_person_profile).toBe(false) + expect(response?.properties?.$process_person_profile).toBe(false) + }) + + it('event that is in the skip list', async () => { + const input = { ...pipelineEvent, team_id: 2, distinct_id: 'distinct_id_to_drop' } + const response = await populateTeamDataStep(runner, input) + expect(response?.properties?.$process_person_profile).toBe(false) }) it('PG errors are propagated up to trigger retries', async () => { From 00ceb0961cee28896cf4863f217093dc28f9a98c Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 12:24:22 +0100 Subject: [PATCH 45/58] fix --- plugin-server/bin/ci_functional_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/bin/ci_functional_tests.sh b/plugin-server/bin/ci_functional_tests.sh index ac5136ff98a12..ee7f90f520ad9 100755 --- a/plugin-server/bin/ci_functional_tests.sh +++ b/plugin-server/bin/ci_functional_tests.sh @@ -24,7 +24,7 @@ LOG_FILE=$(mktemp) echo '::group::Starting plugin server' -NODE_OPTIONS='--max_old_space_size=4096' ./node_modules/.bin/c8 --reporter html node dist/index.js >"$LOG_FILE" 2>&1 & +NODE_OPTIONS='--max_old_space_size=4096' ./node_modules/.bin/c8 --reporter html node dist/src/index.js >"$LOG_FILE" 2>&1 & SERVER_PID=$! SECONDS=0 From 1c7439e376e84604f0ba5c383060c96e1559d28d Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 12:36:35 +0100 Subject: [PATCH 46/58] fix --- plugin-server/bin/ci_functional_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/bin/ci_functional_tests.sh b/plugin-server/bin/ci_functional_tests.sh index ee7f90f520ad9..ac5136ff98a12 100755 --- a/plugin-server/bin/ci_functional_tests.sh +++ b/plugin-server/bin/ci_functional_tests.sh @@ -24,7 +24,7 @@ LOG_FILE=$(mktemp) echo '::group::Starting plugin server' -NODE_OPTIONS='--max_old_space_size=4096' ./node_modules/.bin/c8 --reporter html node dist/src/index.js >"$LOG_FILE" 2>&1 & +NODE_OPTIONS='--max_old_space_size=4096' ./node_modules/.bin/c8 --reporter html node dist/index.js >"$LOG_FILE" 2>&1 & SERVER_PID=$! SECONDS=0 From d9fc72f89485e9698b0470dde92e024adffca2b5 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 13:27:03 +0100 Subject: [PATCH 47/58] Fix --- .../src/worker/ingestion/event-pipeline/populateTeamDataStep.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts index 9b9bcd20b9fea..abda4f009296c 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/populateTeamDataStep.ts @@ -71,7 +71,7 @@ export async function populateTeamDataStep( const skipPersonsProcessingForDistinctIds = runner.hub.eventsToSkipPersonsProcessingByToken.get(event.token!) const forceOptOutPersonProfiles = - !!team.person_processing_opt_out || skipPersonsProcessingForDistinctIds?.includes(event.distinct_id) + team.person_processing_opt_out || skipPersonsProcessingForDistinctIds?.includes(event.distinct_id) // We allow teams to set the person processing mode on a per-event basis, but override // it with the team-level setting, if it's set to opt-out (since this is billing related, From 03b5078e154310e6d4ed3d75d5e0143951e1d9d3 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 14:29:36 +0100 Subject: [PATCH 48/58] Fix --- plugin-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/package.json b/plugin-server/package.json index 85030b9be36b9..88efbae6934c0 100644 --- a/plugin-server/package.json +++ b/plugin-server/package.json @@ -12,7 +12,7 @@ "start:dist": "BASE_DIR=.. node dist/index.js", "start:dev": "NODE_ENV=dev BASE_DIR=.. nodemon --watch src/ --exec node -r @swc-node/register src/index.ts", "start:devNoWatch": "NODE_ENV=dev BASE_DIR=.. node -r @swc-node/register src/index.ts", - "build": "pnpm clean && pnpm typescript:compile && && ls dist/ mv dist/src/* dist/", + "build": "pnpm clean && pnpm typescript:compile && ls dist/ && mv dist/src/* dist/", "clean": "rm -rf dist/* && rm -rf ../rust/cyclotron-node/index.node", "typescript:compile": "tsc -b", "typescript:check": "tsc --noEmit -p .", From 705783581a71756a68edd03459152c51fab4b818 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 14:30:17 +0100 Subject: [PATCH 49/58] Fixes --- plugin-server/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/tsconfig.json b/plugin-server/tsconfig.json index 02238bc1c63a5..6ffed7faa8d4d 100644 --- a/plugin-server/tsconfig.json +++ b/plugin-server/tsconfig.json @@ -24,5 +24,5 @@ } }, "include": ["src"], - "exclude": ["node_modules", "dist", "bin", "src/**/*.test.ts"] + "exclude": ["node_modules", "dist", "bin"] } From 4e80a9293056bc245ceeb3a369c954ee0c77854b Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 15:07:35 +0100 Subject: [PATCH 50/58] Fixes --- .../ingestion-consumer.test.ts.snap | 29 ++++++++ .../src/ingestion/ingestion-consumer.test.ts | 68 +++++++++++++++++-- .../src/ingestion/ingestion-consumer.ts | 10 ++- .../{tests => src}/utils/token-bucket.test.ts | 2 +- plugin-server/src/utils/token-bucket.ts | 3 +- .../tests/helpers/mocks/producer.mock.ts | 2 +- 6 files changed, 102 insertions(+), 12 deletions(-) rename plugin-server/{tests => src}/utils/token-bucket.test.ts (98%) diff --git a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap index 73fe2bf013545..5f9ae43a96433 100644 --- a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap +++ b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap @@ -1,5 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`IngestionConsumer general overflow should allow some events to pass 1`] = ` +[ + { + "key": null, + "topic": "events_plugin_ingestion_overflow_test", + "value": { + "data": "{"distinct_id":"overflow-distinct-id","uuid":"","token":"THIS IS NOT A TOKEN FOR TEAM 2","ip":"127.0.0.1","site_url":"us.posthog.com","now":"2025-02-01T00:00:00.000+01:00","event":"$pageview","properties":{"$current_url":"http://localhost:8000"}}", + "distinct_id": "overflow-distinct-id", + "ip": "127.0.0.1", + "now": "2025-02-01T00:00:00.000+01:00", + "token": "THIS IS NOT A TOKEN FOR TEAM 2", + "uuid": "", + }, + }, + { + "key": null, + "topic": "events_plugin_ingestion_overflow_test", + "value": { + "data": "{"distinct_id":"overflow-distinct-id","uuid":"","token":"THIS IS NOT A TOKEN FOR TEAM 2","ip":"127.0.0.1","site_url":"us.posthog.com","now":"2025-02-01T00:00:00.000+01:00","event":"$pageview","properties":{"$current_url":"http://localhost:8000"}}", + "distinct_id": "overflow-distinct-id", + "ip": "127.0.0.1", + "now": "2025-02-01T00:00:00.000+01:00", + "token": "THIS IS NOT A TOKEN FOR TEAM 2", + "uuid": "", + }, + }, +] +`; + exports[`IngestionConsumer general should process a standard event 1`] = ` [ { diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index c81935ca3f796..58ef5a8fb44d8 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -4,7 +4,7 @@ import { Message } from 'node-rdkafka' import { UUIDT } from '~/src/utils/utils' import { getProducedKafkaMessages, - getProducedKakfaMessagesForTopic, + getProducedKafkaMessagesForTopic, mockProducer, } from '~/tests/helpers/mocks/producer.mock' import { forSnapshot } from '~/tests/helpers/snapshots' @@ -60,6 +60,7 @@ const createKafkaMessages: (events: PipelineEvent[]) => Message[] = (events) => size: 1, topic: 'test', offset: offsetIncrementer++, + timestamp: DateTime.now().toMillis(), partition: 1, } }) @@ -130,6 +131,40 @@ describe('IngestionConsumer', () => { expect(forSnapshot(getProducedKafkaMessages())).toMatchSnapshot() }) + + describe('overflow', () => { + const now = () => DateTime.now().toMillis() + beforeEach(() => { + // Just to make it easy to see what is configured + expect(hub.EVENT_OVERFLOW_BUCKET_CAPACITY).toEqual(1000) + }) + + it('should emit to overflow if token and distinct_id are overflowed', async () => { + ingester['overflowRateLimiter'].consume(`${team.api_token}:overflow-distinct-id`, 1000, now()) + const overflowMessages = createKafkaMessages([createEvent({ distinct_id: 'overflow-distinct-id' })]) + await ingester.handleKafkaBatch(overflowMessages) + expect(getProducedKafkaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) + expect(getProducedKafkaMessagesForTopic('events_plugin_ingestion_overflow_test')).toHaveLength(1) + expect( + forSnapshot(getProducedKafkaMessagesForTopic('events_plugin_ingestion_overflow_test')) + ).toMatchSnapshot() + }) + + it('should allow some events to pass', async () => { + const manyOverflowedMessages = createKafkaMessages([ + createEvent({ distinct_id: 'overflow-distinct-id' }), + createEvent({ distinct_id: 'overflow-distinct-id' }), + createEvent({ distinct_id: 'overflow-distinct-id' }), + ]) + ingester['overflowRateLimiter'].consume(`${team.api_token}:overflow-distinct-id`, 998, now()) + await ingester.handleKafkaBatch(manyOverflowedMessages) + expect(getProducedKafkaMessagesForTopic('events_plugin_ingestion_overflow_test')).toHaveLength(2) + + expect( + forSnapshot(getProducedKafkaMessagesForTopic('events_plugin_ingestion_overflow_test')) + ).toMatchSnapshot() + }) + }) }) describe('dropping events', () => { @@ -179,7 +214,7 @@ describe('IngestionConsumer', () => { const messages = createKafkaMessages([createEvent({}), createEvent({})]) addMessageHeaders(messages[0], team.api_token) await ingester.handleKafkaBatch(messages) - expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) + expect(getProducedKafkaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) expectDropLogs([ [team.api_token, 'user-1'], [team.api_token, 'user-1'], @@ -190,7 +225,7 @@ describe('IngestionConsumer', () => { const messages = createKafkaMessages([createEvent({ token: team2.api_token })]) addMessageHeaders(messages[0], team2.api_token) await ingester.handleKafkaBatch(messages) - expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + expect(getProducedKafkaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) expectDropLogs([]) }) @@ -204,7 +239,7 @@ describe('IngestionConsumer', () => { addMessageHeaders(messages[1], team2.api_token) addMessageHeaders(messages[2], team.api_token) await ingester.handleKafkaBatch(messages) - const eventsMessages = getProducedKakfaMessagesForTopic('clickhouse_events_json_test') + const eventsMessages = getProducedKafkaMessagesForTopic('clickhouse_events_json_test') expect(eventsMessages).toHaveLength(1) expect(eventsMessages[0].value).toMatchObject({ team_id: team2.id, @@ -231,7 +266,7 @@ describe('IngestionConsumer', () => { ]) addMessageHeaders(messages[0], team.api_token, 'distinct-id-to-ignore') await ingester.handleKafkaBatch(messages) - expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) + expect(getProducedKafkaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(0) expectDropLogs([[team.api_token, 'distinct-id-to-ignore']]) }) @@ -244,7 +279,7 @@ describe('IngestionConsumer', () => { ]) addMessageHeaders(messages[0], team2.api_token, 'distinct-id-to-ignore') await ingester.handleKafkaBatch(messages) - expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + expect(getProducedKafkaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) expectDropLogs([]) }) @@ -256,10 +291,29 @@ describe('IngestionConsumer', () => { ]) addMessageHeaders(messages[0], team.api_token, 'not-ignored') await ingester.handleKafkaBatch(messages) - expect(getProducedKakfaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) + expect(getProducedKafkaMessagesForTopic('clickhouse_events_json_test')).not.toHaveLength(0) expectDropLogs([]) }) }) }) }) + + describe('event batching', () => { + it('should batch events based on the distinct_id', async () => { + const messages = createKafkaMessages([ + createEvent({ distinct_id: 'distinct-id-1' }), + createEvent({ distinct_id: 'distinct-id-1' }), + createEvent({ distinct_id: 'distinct-id-2' }), + createEvent({ distinct_id: 'distinct-id-1' }), + createEvent({ token: team2.api_token, distinct_id: 'distinct-id-1' }), + ]) + + const batches = await ingester['parseKafkaBatch'](messages) + + expect(Object.keys(batches)).toHaveLength(3) + expect(batches[`${team.api_token}:distinct-id-1`]).toHaveLength(3) + expect(batches[`${team.api_token}:distinct-id-2`]).toHaveLength(1) + expect(batches[`${team2.api_token}:distinct-id-1`]).toHaveLength(1) + }) + }) }) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 34a870cd4408d..2d20b73c4fd35 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -19,7 +19,7 @@ import { Hub, PipelineEvent, PluginServerService } from '../types' import { normalizeEvent } from '../utils/event' import { retryIfRetriable } from '../utils/retries' import { status } from '../utils/status' -import { ConfiguredLimiter, LoggingLimiter } from '../utils/token-bucket' +import { Limiter, LoggingLimiter } from '../utils/token-bucket' import { EventPipelineRunner } from '../worker/ingestion/event-pipeline/runner' // Must require as `tsc` strips unused `import` statements and just requiring this seems to init some globals @@ -62,6 +62,7 @@ export class IngestionConsumer { protected promises: Set> = new Set() protected kafkaProducer?: KafkaProducerWrapper + private overflowRateLimiter: Limiter private tokensToDrop: string[] = [] private tokenDistinctIdsToDrop: string[] = [] @@ -75,6 +76,10 @@ export class IngestionConsumer { this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',').filter((x) => !!x) this.name = `ingestion-consumer-${this.topic}` + this.overflowRateLimiter = new Limiter( + this.hub.EVENT_OVERFLOW_BUCKET_CAPACITY, + this.hub.EVENT_OVERFLOW_BUCKET_REPLENISH_RATE + ) } public get service(): PluginServerService { @@ -152,7 +157,8 @@ export class IngestionConsumer { try { const eventKey = `${event.token}:${event.distinct_id}` // Check the rate limiter and emit to overflow if necessary - if (this.overflowEnabled() && !ConfiguredLimiter.consume(eventKey, 1, message.timestamp)) { + const isBelowRateLimit = this.overflowRateLimiter.consume(eventKey, 1, message.timestamp) + if (this.overflowEnabled() && !isBelowRateLimit) { ingestionPartitionKeyOverflowed.labels(`${event.team_id ?? event.token}`).inc() if (LoggingLimiter.consume(eventKey, 1)) { status.warn('🪣', `Local overflow detection triggered on key ${eventKey}`) diff --git a/plugin-server/tests/utils/token-bucket.test.ts b/plugin-server/src/utils/token-bucket.test.ts similarity index 98% rename from plugin-server/tests/utils/token-bucket.test.ts rename to plugin-server/src/utils/token-bucket.test.ts index 8b12ccdf29dcd..6a767d0577c58 100644 --- a/plugin-server/tests/utils/token-bucket.test.ts +++ b/plugin-server/src/utils/token-bucket.test.ts @@ -1,4 +1,4 @@ -import { BucketKeyMissingError, Limiter, Storage } from '../../src/utils/token-bucket' +import { BucketKeyMissingError, Limiter, Storage } from './token-bucket' describe('Storage', () => { describe('replenish()', () => { diff --git a/plugin-server/src/utils/token-bucket.ts b/plugin-server/src/utils/token-bucket.ts index 81409a70e0c85..f492546f124c4 100644 --- a/plugin-server/src/utils/token-bucket.ts +++ b/plugin-server/src/utils/token-bucket.ts @@ -44,11 +44,12 @@ export class Storage { throw new BucketKeyMissingError(key) } + bucket[0] -= tokens + if (bucket[0] < tokens) { return false } - bucket[0] -= tokens return true } } diff --git a/plugin-server/tests/helpers/mocks/producer.mock.ts b/plugin-server/tests/helpers/mocks/producer.mock.ts index 2d3ab4db84f56..04c211e98fbbb 100644 --- a/plugin-server/tests/helpers/mocks/producer.mock.ts +++ b/plugin-server/tests/helpers/mocks/producer.mock.ts @@ -87,6 +87,6 @@ export const getProducedKafkaMessages = (): DecodedKafkaMessage[] => { return result } -export const getProducedKakfaMessagesForTopic = (topic: string): DecodedKafkaMessage[] => { +export const getProducedKafkaMessagesForTopic = (topic: string): DecodedKafkaMessage[] => { return getProducedKafkaMessages().filter((x) => x.topic === topic) } From 59b03804fa05646a8392a52d569cfaab48fbef84 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 15:16:39 +0100 Subject: [PATCH 51/58] Fix --- plugin-server/src/capabilities.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin-server/src/capabilities.ts b/plugin-server/src/capabilities.ts index 6fea0b214ba00..d412ca4367f42 100644 --- a/plugin-server/src/capabilities.ts +++ b/plugin-server/src/capabilities.ts @@ -35,12 +35,10 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin case null: return { ...singleProcessCapabilities, - ...sharedCapabilities, } case PluginServerMode.all_v2: return { ...singleProcessCapabilities, - ...sharedCapabilities, ingestionV2Combined: true, } From e6199283511081f09008e3bea10c34c67169d7b9 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 18:27:44 +0100 Subject: [PATCH 52/58] Fix tests --- plugin-server/src/utils/token-bucket.test.ts | 2 +- plugin-server/src/utils/token-bucket.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-server/src/utils/token-bucket.test.ts b/plugin-server/src/utils/token-bucket.test.ts index 6a767d0577c58..e2a77be6f61dc 100644 --- a/plugin-server/src/utils/token-bucket.test.ts +++ b/plugin-server/src/utils/token-bucket.test.ts @@ -111,7 +111,7 @@ describe('Storage', () => { storage.replenish(key) expect(storage.consume(key, 11)).toEqual(false) - expect(storage.buckets.get(key)![0]).toEqual(10) + expect(storage.buckets.get(key)![0]).toEqual(-1) }) it('throws error on missing bucket key', () => { diff --git a/plugin-server/src/utils/token-bucket.ts b/plugin-server/src/utils/token-bucket.ts index f492546f124c4..0202d61a9b79a 100644 --- a/plugin-server/src/utils/token-bucket.ts +++ b/plugin-server/src/utils/token-bucket.ts @@ -46,7 +46,7 @@ export class Storage { bucket[0] -= tokens - if (bucket[0] < tokens) { + if (bucket[0] <= 0) { return false } From 6b21bd5bb6261d5b9147d3deb5029d2e4b9aedaa Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 18:42:59 +0100 Subject: [PATCH 53/58] Fixes --- .../src/ingestion/ingestion-consumer.test.ts | 2 +- .../src/ingestion/ingestion-consumer.ts | 11 +- plugin-server/src/utils/token-bucket.test.ts | 159 ++---------------- plugin-server/src/utils/token-bucket.ts | 54 ++---- 4 files changed, 39 insertions(+), 187 deletions(-) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 58ef5a8fb44d8..25b9e61a4b057 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -156,7 +156,7 @@ describe('IngestionConsumer', () => { createEvent({ distinct_id: 'overflow-distinct-id' }), createEvent({ distinct_id: 'overflow-distinct-id' }), ]) - ingester['overflowRateLimiter'].consume(`${team.api_token}:overflow-distinct-id`, 998, now()) + ingester['overflowRateLimiter'].consume(`${team.api_token}:overflow-distinct-id`, 999, now()) await ingester.handleKafkaBatch(manyOverflowedMessages) expect(getProducedKafkaMessagesForTopic('events_plugin_ingestion_overflow_test')).toHaveLength(2) diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 2d20b73c4fd35..52a34ac3243f3 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -19,7 +19,7 @@ import { Hub, PipelineEvent, PluginServerService } from '../types' import { normalizeEvent } from '../utils/event' import { retryIfRetriable } from '../utils/retries' import { status } from '../utils/status' -import { Limiter, LoggingLimiter } from '../utils/token-bucket' +import { MemoryRateLimiter } from '../utils/token-bucket' import { EventPipelineRunner } from '../worker/ingestion/event-pipeline/runner' // Must require as `tsc` strips unused `import` statements and just requiring this seems to init some globals @@ -62,7 +62,8 @@ export class IngestionConsumer { protected promises: Set> = new Set() protected kafkaProducer?: KafkaProducerWrapper - private overflowRateLimiter: Limiter + private overflowRateLimiter: MemoryRateLimiter + private ingestionWarningLimiter: MemoryRateLimiter private tokensToDrop: string[] = [] private tokenDistinctIdsToDrop: string[] = [] @@ -76,10 +77,12 @@ export class IngestionConsumer { this.tokenDistinctIdsToDrop = hub.DROP_EVENTS_BY_TOKEN_DISTINCT_ID.split(',').filter((x) => !!x) this.name = `ingestion-consumer-${this.topic}` - this.overflowRateLimiter = new Limiter( + this.overflowRateLimiter = new MemoryRateLimiter( this.hub.EVENT_OVERFLOW_BUCKET_CAPACITY, this.hub.EVENT_OVERFLOW_BUCKET_REPLENISH_RATE ) + + this.ingestionWarningLimiter = new MemoryRateLimiter(1, 1.0 / 3600) } public get service(): PluginServerService { @@ -160,7 +163,7 @@ export class IngestionConsumer { const isBelowRateLimit = this.overflowRateLimiter.consume(eventKey, 1, message.timestamp) if (this.overflowEnabled() && !isBelowRateLimit) { ingestionPartitionKeyOverflowed.labels(`${event.team_id ?? event.token}`).inc() - if (LoggingLimiter.consume(eventKey, 1)) { + if (this.ingestionWarningLimiter.consume(eventKey, 1)) { status.warn('🪣', `Local overflow detection triggered on key ${eventKey}`) } diff --git a/plugin-server/src/utils/token-bucket.test.ts b/plugin-server/src/utils/token-bucket.test.ts index e2a77be6f61dc..9c5575175b810 100644 --- a/plugin-server/src/utils/token-bucket.test.ts +++ b/plugin-server/src/utils/token-bucket.test.ts @@ -1,176 +1,45 @@ -import { BucketKeyMissingError, Limiter, Storage } from './token-bucket' +import { MemoryRateLimiter } from './token-bucket' -describe('Storage', () => { - describe('replenish()', () => { - afterEach(() => { - jest.useRealTimers() - }) +describe('MemoryRateLimiter', () => { + describe('consume()', () => { + const key = 'test' + let limiter: MemoryRateLimiter + let now = new Date('2025-01-01T01:00:00') - it('adds capacity to new key', () => { - const key = 'test' - const storage = new Storage(10, 1) - const now = new Date('2023-02-08T08:00:00') + const advanceTime = (seconds: number) => { + now = new Date(now.valueOf() + seconds * 1000) jest.useFakeTimers().setSystemTime(now) + } - storage.replenish(key) - - expect(storage.buckets.has(key)).toEqual(true) - expect(storage.buckets.get(key)![0]).toEqual(10) - expect(storage.buckets.get(key)![1]).toEqual(now.valueOf()) - }) - - it('adds rate to existing key', () => { - const key = 'test' - const storage = new Storage(10, 1) - const now = new Date('2023-02-08T08:00:00') + beforeEach(() => { + limiter = new MemoryRateLimiter(10, 2) jest.useFakeTimers().setSystemTime(now) - - storage.replenish(key) - storage.consume(key, 5) - now.setSeconds(now.getSeconds() + 2) - jest.setSystemTime(now) - storage.replenish(key) - - expect(storage.buckets.has(key)).toEqual(true) - expect(storage.buckets.get(key)![0]).toEqual(7) - expect(storage.buckets.get(key)![1]).toEqual(now.valueOf()) - }) - - it('adds rate to existing key with argument now', () => { - const key = 'test' - const storage = new Storage(10, 1) - const now = Date.now() - - storage.replenish(key, now) - storage.consume(key, 9) - storage.replenish(key, now + 2000) - - expect(storage.buckets.has(key)).toEqual(true) - expect(storage.buckets.get(key)![0]).toEqual(3) - expect(storage.buckets.get(key)![1]).toEqual(now + 2000) }) - it('does not add more than capacity tokens', () => { - const key = 'test' - const storage = new Storage(10, 1) - const now = new Date('2023-02-08T08:00:00') - - storage.replenish(key, now.valueOf()) - expect(storage.buckets.get(key)![0]).toEqual(10) - expect(storage.buckets.get(key)![1]).toEqual(now.valueOf()) - - // get two tokens to be replenished - storage.consume(key, 2) - expect(storage.buckets.get(key)![0]).toEqual(8) - - // 20 seconds would exceed capacity of 10 tokens at 1 token/sec. - storage.replenish(key, now.valueOf() + 20000) - - expect(storage.buckets.has(key)).toEqual(true) - expect(storage.buckets.get(key)![0]).toEqual(10) - expect(storage.buckets.get(key)![1]).toEqual(now.valueOf() + 20000) - }) - - it('does not add if now is in the past', () => { - const key = 'test' - const storage = new Storage(10, 1) - const now = new Date('2023-02-08T08:00:00') - - storage.replenish(key, now.valueOf()) - expect(storage.buckets.get(key)![0]).toEqual(10) - expect(storage.buckets.get(key)![1]).toEqual(now.valueOf()) - - // get two tokens to be replenished - storage.consume(key, 2) - expect(storage.buckets.get(key)![0]).toEqual(8) - - // Will be a no-op due to a lower now value - storage.replenish(key, now.valueOf() - 20000) - - expect(storage.buckets.has(key)).toEqual(true) - expect(storage.buckets.get(key)![0]).toEqual(8) - expect(storage.buckets.get(key)![1]).toEqual(now.valueOf()) - }) - }) - - describe('consume()', () => { - it('consumes when tokens are less than capacity', () => { - const key = 'test' - const storage = new Storage(10, 1) - - storage.replenish(key) - - expect(storage.consume(key, 9)).toEqual(true) - expect(storage.buckets.get(key)![0]).toEqual(1) - }) - - it('rejects when tokens are more than capacity', () => { - const key = 'test' - const storage = new Storage(10, 1) - - storage.replenish(key) - - expect(storage.consume(key, 11)).toEqual(false) - expect(storage.buckets.get(key)![0]).toEqual(-1) - }) - - it('throws error on missing bucket key', () => { - const key = 'test' - const storage = new Storage(10, 1) - - expect(storage.buckets.has(key)).toEqual(false) - expect(() => storage.consume(key, 1)).toThrow(BucketKeyMissingError) - }) - }) -}) - -describe('Limiter', () => { - describe('consume()', () => { afterEach(() => { jest.useRealTimers() }) - it('consumes when tokens available', () => { - const key = 'test' - const limiter = new Limiter(10, 2) - const now = new Date('2023-02-08T08:00:00') - jest.useFakeTimers().setSystemTime(now) - + it('consumes and returns true when tokens available', () => { expect(limiter.consume(key, 9)).toEqual(true) }) - it('rejects when tokens run out', () => { - const key = 'test' - const limiter = new Limiter(10, 2) - const now = new Date('2023-02-08T08:00:00') - jest.useFakeTimers().setSystemTime(now) - + it('returns false when tokens run out', () => { expect(limiter.consume(key, 10)).toEqual(true) - // We are not advancing time, so no tokens should have been replenished expect(limiter.consume(key, 1)).toEqual(false) }) it('consumes when tokens have been replenished', () => { - const key = 'test' - const limiter = new Limiter(10, 2) - const now = new Date('2023-02-08T08:00:00') - - jest.useFakeTimers().setSystemTime(now) limiter.consume(key, 10) expect(limiter.consume(key, 1)).toEqual(false) - jest.setSystemTime(now.valueOf() + 1000) + advanceTime(1) // Now that we have advanced 1 second, we can consume 1 token expect(limiter.consume(key, 1)).toEqual(true) }) it('consumes when tokens have been replenished with now argument', () => { - const key = 'test' - const limiter = new Limiter(10, 2) - const now = new Date('2023-02-08T08:00:00') - jest.useFakeTimers().setSystemTime(now) - limiter.consume(key, 10, now.valueOf()) expect(limiter.consume(key, 1)).toEqual(false) // Even though we are not advancing time, we are passing the time to use with now diff --git a/plugin-server/src/utils/token-bucket.ts b/plugin-server/src/utils/token-bucket.ts index 0202d61a9b79a..ee7520edf27e3 100644 --- a/plugin-server/src/utils/token-bucket.ts +++ b/plugin-server/src/utils/token-bucket.ts @@ -2,14 +2,7 @@ import { defaultConfig } from './../config/config' type Bucket = [tokens: number, lastReplenishedTimestamp: number] -export class BucketKeyMissingError extends Error { - constructor(key: string) { - super('Bucket with key ' + key + ' is missing. Did you forget to call replenish first?') - this.name = 'BucketKeyMissingError' - } -} - -export class Storage { +export class MemoryRateLimiter { public buckets: Map public replenishRate: number public bucketCapacity: number @@ -20,13 +13,17 @@ export class Storage { this.replenishRate = replenishRate } - replenish(key: string, now?: number): void { - const replenish_timestamp: number = now ?? Date.now() - const bucket = this.buckets.get(key) + private getBucket(key: string): Bucket { + let bucket = this.buckets.get(key) if (bucket === undefined) { - this.buckets.set(key, [this.bucketCapacity, replenish_timestamp]) - return + bucket = [this.bucketCapacity, Date.now()] + this.buckets.set(key, bucket) } + return bucket + } + + private replenish(bucket: Bucket, now?: number): void { + const replenish_timestamp: number = now ?? Date.now() // Replenish the bucket if replenish_timestamp is higher than lastReplenishedTimestamp const secondsToReplenish = (replenish_timestamp - bucket[1]) / 1000 @@ -37,16 +34,13 @@ export class Storage { } } - consume(key: string, tokens: number): boolean { - const bucket = this.buckets.get(key) - - if (bucket === undefined) { - throw new BucketKeyMissingError(key) - } + consume(key: string, tokens: number, now?: number): boolean { + const bucket = this.getBucket(key) + this.replenish(bucket, now) bucket[0] -= tokens - if (bucket[0] <= 0) { + if (bucket[0] < 0) { return false } @@ -54,25 +48,11 @@ export class Storage { } } -export class Limiter { - public storage: Storage - - constructor(bucketCapacity: number, replenishRate: number) { - this.storage = new Storage(bucketCapacity, replenishRate) - } - - consume(key: string, tokens: number, now?: number): boolean { - this.storage.replenish(key, now) - - return this.storage.consume(key, tokens) - } -} - -export const ConfiguredLimiter: Limiter = new Limiter( +export const ConfiguredLimiter: MemoryRateLimiter = new MemoryRateLimiter( defaultConfig.EVENT_OVERFLOW_BUCKET_CAPACITY, defaultConfig.EVENT_OVERFLOW_BUCKET_REPLENISH_RATE ) -export const IngestionWarningLimiter: Limiter = new Limiter(1, 1.0 / 3600) +export const IngestionWarningLimiter: MemoryRateLimiter = new MemoryRateLimiter(1, 1.0 / 3600) -export const LoggingLimiter: Limiter = new Limiter(1, 1.0 / 60) +export const LoggingLimiter: MemoryRateLimiter = new MemoryRateLimiter(1, 1.0 / 60) From 1618c1776f88e0a32a51520805ab956b3a2d4044 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 18:45:12 +0100 Subject: [PATCH 54/58] Fix --- .../src/ingestion/ingestion-consumer.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index 25b9e61a4b057..e7faa39afc17d 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -164,6 +164,17 @@ describe('IngestionConsumer', () => { forSnapshot(getProducedKafkaMessagesForTopic('events_plugin_ingestion_overflow_test')) ).toMatchSnapshot() }) + + it('does not overflow if it is consuming from the overflow topic', async () => { + ingester['topic'] = 'events_plugin_ingestion_overflow_test' + ingester['overflowRateLimiter'].consume(`${team.api_token}:overflow-distinct-id`, 1000, now()) + + const overflowMessages = createKafkaMessages([createEvent({ distinct_id: 'overflow-distinct-id' })]) + await ingester.handleKafkaBatch(overflowMessages) + + expect(getProducedKafkaMessagesForTopic('events_plugin_ingestion_overflow_test')).toHaveLength(0) + expect(getProducedKafkaMessagesForTopic('clickhouse_events_json_test')).toHaveLength(1) + }) }) }) From 7d1b5444f7f9391cb8f25fc4054e6be8f7b10a7f Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 19:13:05 +0100 Subject: [PATCH 55/58] Added happy path tests --- .../ingestion-consumer.test.ts.snap | 451 ++++++++++++++++++ .../src/ingestion/ingestion-consumer.test.ts | 113 +++++ 2 files changed, 564 insertions(+) diff --git a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap index 97a5cda746b43..57d29dcce29e0 100644 --- a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap +++ b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap @@ -93,3 +93,454 @@ exports[`IngestionConsumer general should process a standard event 1`] = ` }, ] `; + +exports[`IngestionConsumer typical event processing $identify event 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "user-1", + "elements_chain": "", + "event": "$identify", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$email":"test@test.com","$creator_event_uuid":""}", + "project_id": 2, + "properties": "{"$set":{"$email":"test@test.com"},"$ip":"127.0.0.1"}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$email":"test@test.com","$creator_event_uuid":""}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "user-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing ai event 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "user-1", + "elements_chain": "", + "event": "$ai_generation", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$creator_event_uuid":""}", + "project_id": 2, + "properties": "{"$ai_model":"gpt-4","$ai_provider":"openai","$ai_input_tokens":100,"$ai_output_tokens":50,"$ip":"127.0.0.1","$ai_input_cost_usd":0.003,"$ai_output_cost_usd":0.003,"$ai_total_cost_usd":0.006}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$creator_event_uuid":""}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "user-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing client ingestion warning 1`] = ` +[ + { + "key": null, + "topic": "clickhouse_ingestion_warnings_test", + "value": { + "details": "{"eventUuid":"","event":"$$client_ingestion_warning","distinctId":"user-1","message":"test"}", + "source": "plugin-server", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "type": "client_ingestion_warning", + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing event with common distinct_id that gets dropped 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "distinct_id", + "elements_chain": "", + "event": "$pageview", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "project_id": 2, + "properties": "{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "distinct_id", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing malformed event 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "user-1", + "elements_chain": "", + "event": "", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "project_id": 2, + "properties": "{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "user-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing malformed person information 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "distinct-id-1", + "elements_chain": "", + "event": "$pageview", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"0":"I","1":"N","2":"V","3":"A","4":"L","5":"I","6":"D","$creator_event_uuid":""}", + "project_id": 2, + "properties": "{"$set":"INVALID","$unset":[[[["definitel invalid"]]]],"$ip":"127.0.0.1"}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"0":"I","1":"N","2":"V","3":"A","4":"L","5":"I","6":"D","$creator_event_uuid":""}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "distinct-id-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing multiple events 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "anonymous-id-1", + "elements_chain": "", + "event": "$pageview", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$current_url":"https://example.com/page1","$creator_event_uuid":"","$initial_current_url":"https://example.com/page1"}", + "project_id": 2, + "properties": "{"$current_url":"https://example.com/page1","$ip":"127.0.0.1","$set":{"$current_url":"https://example.com/page1"},"$set_once":{"$initial_current_url":"https://example.com/page1"}}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "identified-id-1", + "elements_chain": "", + "event": "$identify", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$email":"test@test.com","$creator_event_uuid":""}", + "project_id": 2, + "properties": "{"$set":{"$email":"test@test.com"},"$anonymous_distinct_id":"anonymous-id-1","$ip":"127.0.0.1"}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "identified-id-1", + "elements_chain": "", + "event": "$pageview", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$email":"test@test.com","$current_url":"https://example.com/page2","$creator_event_uuid":"","$initial_current_url":"https://example.com/page2"}", + "project_id": 2, + "properties": "{"$current_url":"https://example.com/page2","$ip":"127.0.0.1","$set":{"$current_url":"https://example.com/page2"},"$set_once":{"$initial_current_url":"https://example.com/page2"}}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$current_url":"https://example.com/page1","$creator_event_uuid":"","$initial_current_url":"https://example.com/page1"}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "anonymous-id-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$email":"test@test.com","$creator_event_uuid":""}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "identified-id-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$email":"test@test.com","$current_url":"https://example.com/page2","$creator_event_uuid":"","$initial_current_url":"https://example.com/page2"}", + "team_id": 2, + "version": 1, + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing normal event 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "user-1", + "elements_chain": "", + "event": "$pageview", + "person_created_at": "2025-01-31 23:00:00", + "person_id": "", + "person_mode": "full", + "person_properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "project_id": 2, + "properties": "{"$current_url":"http://localhost:8000","$ip":"127.0.0.1","$set":{"$current_url":"http://localhost:8000"},"$set_once":{"$initial_current_url":"http://localhost:8000"}}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, + { + "key": null, + "topic": "clickhouse_person_test", + "value": { + "created_at": "2025-01-31 23:00:00", + "id": "", + "is_deleted": 0, + "is_identified": 0, + "properties": "{"$current_url":"http://localhost:8000","$creator_event_uuid":"","$initial_current_url":"http://localhost:8000"}", + "team_id": 2, + "version": 0, + }, + }, + { + "key": null, + "topic": "clickhouse_person_distinct_id_test", + "value": { + "distinct_id": "user-1", + "is_deleted": 0, + "person_id": "", + "team_id": 2, + "version": 0, + }, + }, +] +`; + +exports[`IngestionConsumer typical event processing person processing off 1`] = ` +[ + { + "key": "", + "topic": "clickhouse_events_json_test", + "value": { + "created_at": "2025-01-31 23:00:00.000", + "distinct_id": "user-1", + "elements_chain": "", + "event": "$pageview", + "person_created_at": "1970-01-01 00:00:05", + "person_id": "", + "person_mode": "propertyless", + "person_properties": "{}", + "project_id": 2, + "properties": "{"$process_person_profile":false,"$ip":"127.0.0.1"}", + "team_id": 2, + "timestamp": "2025-01-31 23:00:00.000", + "uuid": "", + }, + }, +] +`; diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index e7faa39afc17d..d3c4b13076e45 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -327,4 +327,117 @@ describe('IngestionConsumer', () => { expect(batches[`${team2.api_token}:distinct-id-1`]).toHaveLength(1) }) }) + + describe('typical event processing', () => { + /** + * NOTE: The majority of these tests should be done in the event pipeline runner but + * this is a good place to have some high level happy paths + */ + + beforeEach(async () => { + ingester = new IngestionConsumer(hub) + await ingester.start() + }) + + const eventTests: [string, () => PipelineEvent[]][] = [ + ['normal event', () => [createEvent()]], + [ + '$identify event', + () => [createEvent({ event: '$identify', properties: { $set: { $email: 'test@test.com' } } })], + ], + [ + 'multiple events', + () => [ + createEvent({ + event: '$pageview', + distinct_id: 'anonymous-id-1', + properties: { $current_url: 'https://example.com/page1' }, + }), + createEvent({ + event: '$identify', + distinct_id: 'identified-id-1', + properties: { $set: { $email: 'test@test.com' }, $anonymous_distinct_id: 'anonymous-id-1' }, + }), + createEvent({ + event: '$pageview', + distinct_id: 'identified-id-1', + properties: { $current_url: 'https://example.com/page2' }, + }), + ], + ], + // [ + // 'heatmap event', + // () => [ + // createEvent({ + // distinct_id: 'distinct-id-1', + // event: '$$heatmap', + // properties: { + // $heatmap_data: { + // 'http://localhost:3000/': [ + // { + // x: 1020, + // y: 363, + // target_fixed: false, + // type: 'mousemove', + // }, + // { + // x: 634, + // y: 460, + // target_fixed: false, + // type: 'click', + // }, + // ], + // }, + // }, + // }), + // ], + // ], + [ + // NOTE: This currently returns as is - for now we keep this broken but once we release the new ingester we should fix this + 'malformed person information', + () => [ + createEvent({ + distinct_id: 'distinct-id-1', + properties: { $set: 'INVALID', $unset: [[[['definitel invalid']]]] }, + }), + ], + ], + ['malformed event', () => [createEvent({ event: '' })]], + ['event with common distinct_id that gets dropped', () => [createEvent({ distinct_id: 'distinct_id' })]], + [ + 'ai event', + () => [ + createEvent({ + event: '$ai_generation', + properties: { + $ai_model: 'gpt-4', + $ai_provider: 'openai', + $ai_input_tokens: 100, + $ai_output_tokens: 50, + }, + }), + ], + ], + [ + 'person processing off', + () => [createEvent({ event: '$pageview', properties: { $process_person_profile: false } })], + ], + [ + 'client ingestion warning', + () => [ + createEvent({ + event: '$$client_ingestion_warning', + properties: { $$client_ingestion_warning_message: 'test' }, + }), + ], + ], + ] + + it.each(eventTests)('%s', async (_, createEvents) => { + const messages = createKafkaMessages(createEvents()) + await ingester.handleKafkaBatch(messages) + + expect(forSnapshot(getProducedKafkaMessages())).toMatchSnapshot() + }) + }) }) From e9a10b0b2daf40fb7dc709dc8479d3d4ba93e80e Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:19:20 +0000 Subject: [PATCH 56/58] Update UI snapshots for `chromium` (1) --- ...uccess--second-recording-in-list--dark.png | Bin 119234 -> 118535 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png b/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png index b32bad3a8af4f4d7e66c7cbd816a2ed9345b148c..4bc3370cb3f950393bc7338ab7c53f3786423b5c 100644 GIT binary patch literal 118535 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

b6=;qLFslN6a)R5EsE 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 z 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 From 1002c844fb9a1f0ad8e74d7a9f01fe13c5f81ff2 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 19:29:48 +0100 Subject: [PATCH 57/58] Fixes --- .../ingestion-consumer.test.ts.snap | 17 ++++++++ .../src/ingestion/ingestion-consumer.test.ts | 39 +++++++++++++++++++ .../src/ingestion/ingestion-consumer.ts | 15 ++++--- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap index 57d29dcce29e0..fe1aa509e49af 100644 --- a/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap +++ b/plugin-server/src/ingestion/__snapshots__/ingestion-consumer.test.ts.snap @@ -1,5 +1,22 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`IngestionConsumer error handling should handle explicitly non retriable errors by sending to DLQ 1`] = ` +[ + { + "key": null, + "topic": "events_plugin_ingestion_dlq_test", + "value": { + "data": "{"distinct_id":"user-1","uuid":"","token":"THIS IS NOT A TOKEN FOR TEAM 2","ip":"127.0.0.1","site_url":"us.posthog.com","now":"2025-02-01T00:00:00.000+01:00","event":"$pageview","properties":{"$current_url":"http://localhost:8000"}}", + "distinct_id": "user-1", + "ip": "127.0.0.1", + "now": "2025-02-01T00:00:00.000+01:00", + "token": "THIS IS NOT A TOKEN FOR TEAM 2", + "uuid": "", + }, + }, +] +`; + exports[`IngestionConsumer general overflow should allow some events to pass 1`] = ` [ { diff --git a/plugin-server/src/ingestion/ingestion-consumer.test.ts b/plugin-server/src/ingestion/ingestion-consumer.test.ts index d3c4b13076e45..7a3cb98685f85 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.test.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.test.ts @@ -328,6 +328,45 @@ describe('IngestionConsumer', () => { }) }) + describe('error handling', () => { + let messages: Message[] + + beforeEach(async () => { + ingester = new IngestionConsumer(hub) + await ingester.start() + // Simulate some sort of error happening by mocking out the runner + messages = createKafkaMessages([createEvent()]) + jest.spyOn(status, 'error').mockImplementation(() => {}) + }) + + afterEach(() => { + jest.restoreAllMocks() + }) + + it('should handle explicitly non retriable errors by sending to DLQ', async () => { + // NOTE: I don't think this makes a lot of sense but currently is just mimicing existing behavior for the migration + // We should figure this out better and have more explictly named errors + + const error: any = new Error('test') + error.isRetriable = false + jest.spyOn(ingester as any, 'runEventPipeline').mockRejectedValue(error) + + await ingester.handleKafkaBatch(messages) + + expect(jest.mocked(status.error)).toHaveBeenCalledWith('🔥', 'Error processing message', expect.any(Object)) + + expect(forSnapshot(getProducedKafkaMessages())).toMatchSnapshot() + }) + + it.each([undefined, true])('should throw if isRetriable is set to %s', async (isRetriable) => { + const error: any = new Error('test') + error.isRetriable = isRetriable + jest.spyOn(ingester as any, 'runEventPipeline').mockRejectedValue(error) + + await expect(ingester.handleKafkaBatch(messages)).rejects.toThrow() + }) + }) + describe('typical event processing', () => { /** * NOTE: The majority of these tests should be done in the event pipeline runner but diff --git a/plugin-server/src/ingestion/ingestion-consumer.ts b/plugin-server/src/ingestion/ingestion-consumer.ts index 52a34ac3243f3..e5da20798c106 100644 --- a/plugin-server/src/ingestion/ingestion-consumer.ts +++ b/plugin-server/src/ingestion/ingestion-consumer.ts @@ -20,7 +20,7 @@ import { normalizeEvent } from '../utils/event' import { retryIfRetriable } from '../utils/retries' import { status } from '../utils/status' import { MemoryRateLimiter } from '../utils/token-bucket' -import { EventPipelineRunner } from '../worker/ingestion/event-pipeline/runner' +import { EventPipelineResult, EventPipelineRunner } from '../worker/ingestion/event-pipeline/runner' // Must require as `tsc` strips unused `import` statements and just requiring this seems to init some globals require('@sentry/tracing') @@ -171,10 +171,7 @@ export class IngestionConsumer { continue } - const result = await retryIfRetriable(async () => { - const runner = new EventPipelineRunner(this.hub, event) - return await runner.runEventPipeline(event) - }) + const result = await this.runEventPipeline(event) result.ackPromises?.forEach((promise) => { void this.scheduleWork( @@ -192,6 +189,13 @@ export class IngestionConsumer { await Promise.all(this.promises) } + private async runEventPipeline(event: PipelineEvent): Promise { + return await retryIfRetriable(async () => { + const runner = new EventPipelineRunner(this.hub, event) + return await runner.runEventPipeline(event) + }) + } + private parseKafkaBatch(messages: Message[]): Promise { return runInstrumentedFunction({ statsKey: `ingestionConsumer.handleEachBatch.parseKafkaMessages`, @@ -334,6 +338,7 @@ export class IngestionConsumer { // // TODO: property abstract out this `isRetriable` error logic. This is currently relying on the // fact that node-rdkafka adheres to the `isRetriable` interface. + if (error?.isRetriable === false) { const sentryEventId = Sentry.captureException(error) const headers: MessageHeader[] = message.headers ?? [] From 4ad069e33802e57e2a4601174e84d83e02fef311 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 21 Jan 2025 20:06:48 +0100 Subject: [PATCH 58/58] fix --- .../session-recording/services/overflow-manager.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin-server/src/main/ingestion-queues/session-recording/services/overflow-manager.ts b/plugin-server/src/main/ingestion-queues/session-recording/services/overflow-manager.ts index b1722f9d640a7..7ed921b4b188e 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/services/overflow-manager.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/services/overflow-manager.ts @@ -3,7 +3,7 @@ import LRUCache from 'lru-cache' import { Gauge } from 'prom-client' import { status } from '../../../../utils/status' -import { Limiter } from '../../../../utils/token-bucket' +import { MemoryRateLimiter } from '../../../../utils/token-bucket' export const overflowTriggeredGauge = new Gauge({ name: 'overflow_detection_triggered_total', @@ -20,7 +20,7 @@ export const overflowTriggeredGauge = new Gauge({ * calls will return early until cooldownSeconds is reached. */ export class OverflowManager { - private limiter: Limiter + private limiter: MemoryRateLimiter private triggered: LRUCache constructor( @@ -31,7 +31,7 @@ export class OverflowManager { private redisKey: string, private redisClient: Redis ) { - this.limiter = new Limiter(burstCapacity, replenishRate) + this.limiter = new MemoryRateLimiter(burstCapacity, replenishRate) this.triggered = new LRUCache({ max: 1_000_000, maxAge: cooldownSeconds * 1000 }) status.info('🚛 ', '[overflow-manager] manager stated', { redis_key: this.redisKey,