From 7e02fc890d1f9f2344997ea48c3bef5d2d3575d8 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 16:13:42 +0100 Subject: [PATCH 01/46] added initial work --- .../cdp-cyclotron-plugins-worker.consumer.ts | 110 ++++++++++++++++++ .../cdp-cyclotron-worker.consumer.ts | 27 +++-- .../src/cdp/legacy-plugins/manager.ts | 5 + plugin-server/src/cdp/legacy-plugins/types.ts | 9 ++ .../services/hog-function-manager.service.ts | 1 + plugin-server/src/cdp/types.ts | 3 +- 6 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts create mode 100644 plugin-server/src/cdp/legacy-plugins/manager.ts create mode 100644 plugin-server/src/cdp/legacy-plugins/types.ts diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts new file mode 100644 index 0000000000000..dfb8eca718f0c --- /dev/null +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -0,0 +1,110 @@ +import { Meta, ProcessedPluginEvent } from '@posthog/plugin-scaffold' +import { DateTime } from 'luxon' + +import { PLUGINS_BY_ID } from '../legacy-plugins/manager' +import { HogFunctionInvocation, HogFunctionInvocationResult, HogFunctionTypeType } from '../types' +import { CdpCyclotronWorker } from './cdp-cyclotron-worker.consumer' + +type PluginState = { + setupPromise: Promise + meta: Meta +} + +const PLUGIN_STATE: Record = {} + +/** + * NOTE: This is a consumer to take care of legacy plugins. + */ +export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { + protected name = 'CdpCyclotronWorkerPlugins' + protected queue = 'plugins' as const + protected hogTypes: HogFunctionTypeType[] = ['destination'] + + public async processInvocations(invocations: HogFunctionInvocation[]): Promise { + return await this.runManyWithHeartbeat(invocations, (item) => this.executePluginInvocation(item)) + } + + private async executePluginInvocation(invocation: HogFunctionInvocation): Promise { + const result: HogFunctionInvocationResult = { + invocation, + finished: true, + capturedPostHogEvents: [], + logs: [], + } + + const pluginId = invocation.hogFunction.template_id?.startsWith('plugin-') + ? invocation.hogFunction.template_id + : `plugin-${invocation.hogFunction.template_id}` + + result.logs.push({ + level: 'debug', + timestamp: DateTime.now(), + message: `Executing plugin ${pluginId}`, + }) + const plugin = PLUGINS_BY_ID[pluginId] + + if (!plugin) { + result.error = new Error(`Plugin ${pluginId} not found`) + result.logs.push({ + level: 'error', + timestamp: DateTime.now(), + message: `Plugin ${pluginId} not found`, + }) + return result + } + + // Convert the invocation into the right interface for the plugin + + const inputs = invocation.globals.inputs + + const event: ProcessedPluginEvent = { + distinct_id: invocation.globals.event.distinct_id, + ip: invocation.globals.event.properties.$ip, + team_id: invocation.hogFunction.team_id, + event: invocation.globals.event.event, + properties: invocation.globals.event.properties, + timestamp: invocation.globals.event.timestamp, + $set: invocation.globals.event.properties.$set, + $set_once: invocation.globals.event.properties.$set_once, + uuid: invocation.globals.event.uuid, + person: invocation.globals.person + ? { + uuid: invocation.globals.person.id, + team_id: invocation.hogFunction.team_id, + properties: invocation.globals.person.properties, + created_at: '', // NOTE: We don't have this anymore - see if any plugin uses it... + } + : undefined, + } + + let state = PLUGIN_STATE[pluginId] + + if (!state) { + const meta: Meta = { + global: inputs, + attachments: {}, + config: {}, + jobs: {}, + metrics: {}, + cache: {} as any, + storage: {} as any, // NOTE: Figuree out what to do about storage as that is used... + geoip: {} as any, + utils: {} as any, + } + + state = PLUGIN_STATE[pluginId] = { + setupPromise: plugin.setupPlugin?.(meta) ?? Promise.resolve(), + meta, + } + } + + await state.setupPromise + + await plugin.onEvent?.(event, { + ...state.meta, + global: inputs, + }) + + return result + } +} diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts index 89e752d9cb7f3..5fd0d1981dc45 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts @@ -13,9 +13,13 @@ export class CdpCyclotronWorker extends CdpConsumerBase { protected name = 'CdpCyclotronWorker' private cyclotronWorker?: CyclotronWorker private runningWorker: Promise | undefined - protected queue: 'hog' | 'fetch' = 'hog' + protected queue: 'hog' | 'fetch' | 'plugins' = 'hog' protected hogTypes: HogFunctionTypeType[] = ['destination', 'internal_destination'] + public async processInvocations(invocations: HogFunctionInvocation[]): Promise { + return await this.runManyWithHeartbeat(invocations, (item) => this.hogExecutor.execute(item)) + } + public async processBatch(invocations: HogFunctionInvocation[]): Promise { if (!invocations.length) { return @@ -23,19 +27,7 @@ export class CdpCyclotronWorker extends CdpConsumerBase { const invocationResults = await runInstrumentedFunction({ statsKey: `cdpConsumer.handleEachBatch.executeInvocations`, - func: async () => { - // NOTE: this service will never do fetching (unless we decide we want to do it in node at some point, its only used for e2e testing) - // fetchExecutor would use rusty-hook to send a fetch request but thats no longer the case - // we are currentyl going to execute the fetch locally for testing purposes - // as nothing should ever land on the deprecated fetch queue this should be safe. - const fetchQueue = invocations.filter((item) => item.queue === 'fetch') - const fetchResults = await this.runManyWithHeartbeat(fetchQueue, (item) => - this.fetchExecutor.execute(item) - ) - const hogQueue = invocations.filter((item) => item.queue === 'hog') - const hogResults = await this.runManyWithHeartbeat(hogQueue, (item) => this.hogExecutor.execute(item)) - return [...hogResults, ...(fetchResults.filter(Boolean) as HogFunctionInvocationResult[])] - }, + func: async () => await this.processInvocations(invocations), }) await this.processInvocationResults(invocationResults) @@ -140,4 +132,11 @@ export class CdpCyclotronWorker extends CdpConsumerBase { export class CdpCyclotronWorkerFetch extends CdpCyclotronWorker { protected name = 'CdpCyclotronWorkerFetch' protected queue = 'fetch' as const + + public async processInvocations(invocations: HogFunctionInvocation[]): Promise { + // NOTE: this service will never do fetching (unless we decide we want to do it in node at some point, its only used for e2e testing) + return (await this.runManyWithHeartbeat(invocations, (item) => this.fetchExecutor.execute(item))).filter( + Boolean + ) as HogFunctionInvocationResult[] + } } diff --git a/plugin-server/src/cdp/legacy-plugins/manager.ts b/plugin-server/src/cdp/legacy-plugins/manager.ts new file mode 100644 index 0000000000000..f6de65c90608b --- /dev/null +++ b/plugin-server/src/cdp/legacy-plugins/manager.ts @@ -0,0 +1,5 @@ +import { customerioPlugin } from './customerio' + +export const PLUGINS_BY_ID = { + [customerioPlugin.id]: customerioPlugin, +} diff --git a/plugin-server/src/cdp/legacy-plugins/types.ts b/plugin-server/src/cdp/legacy-plugins/types.ts new file mode 100644 index 0000000000000..cde9ed0529317 --- /dev/null +++ b/plugin-server/src/cdp/legacy-plugins/types.ts @@ -0,0 +1,9 @@ +import { Plugin } from '@posthog/plugin-scaffold' + +export type LegacyPlugin = { + id: string + name: string + description: string + onEvent: Plugin['onEvent'] + setupPlugin: Plugin['setupPlugin'] +} diff --git a/plugin-server/src/cdp/services/hog-function-manager.service.ts b/plugin-server/src/cdp/services/hog-function-manager.service.ts index 0c4a693b22f46..0c3b6d04052c1 100644 --- a/plugin-server/src/cdp/services/hog-function-manager.service.ts +++ b/plugin-server/src/cdp/services/hog-function-manager.service.ts @@ -25,6 +25,7 @@ const HOG_FUNCTION_FIELDS = [ 'bytecode', 'masking', 'type', + 'template_id', ] export class HogFunctionManagerService { diff --git a/plugin-server/src/cdp/types.ts b/plugin-server/src/cdp/types.ts index bd154a2c2d29c..1a0cd607c7a36 100644 --- a/plugin-server/src/cdp/types.ts +++ b/plugin-server/src/cdp/types.ts @@ -212,7 +212,7 @@ export type HogFunctionInvocation = { teamId: Team['id'] hogFunction: HogFunctionType priority: number - queue: 'hog' | 'fetch' + queue: 'hog' | 'fetch' | 'plugins' queueParameters?: HogFunctionInvocationQueueParameters // The current vmstate (set if the invocation is paused) vmState?: VMState @@ -305,6 +305,7 @@ export type HogFunctionType = { mappings?: HogFunctionMappingType[] | null masking?: HogFunctionMasking | null depends_on_integration_ids?: Set + template_id?: string } export type HogFunctionInputType = { From 99e5b7274cb8d1becf0ded204c578c9195624420 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 16:50:27 +0100 Subject: [PATCH 02/46] Fix up new plugins --- ...-cyclotron-plugins-worker.consumer.test.ts | 160 ++++++++++++++++++ .../cdp-cyclotron-plugins-worker.consumer.ts | 89 ++++++---- .../src/cdp/legacy-plugins/manager.ts | 3 +- plugin-server/src/cdp/legacy-plugins/types.ts | 13 +- 4 files changed, 229 insertions(+), 36 deletions(-) create mode 100644 plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts new file mode 100644 index 0000000000000..c45d2eedc521f --- /dev/null +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts @@ -0,0 +1,160 @@ +import { DateTime } from 'luxon' + +import { + createHogExecutionGlobals, + createInvocation, + insertHogFunction as _insertHogFunction, +} from '~/tests/cdp/fixtures' +import { forSnapshot } from '~/tests/helpers/snapshots' +import { getFirstTeam, resetTestDatabase } from '~/tests/helpers/sql' + +import { Hub, Team } from '../../types' +import { closeHub, createHub } from '../../utils/db/hub' +import { PLUGINS_BY_ID } from '../legacy-plugins/manager' +import { HogFunctionInvocationGlobalsWithInputs, HogFunctionType } from '../types' +import { CdpCyclotronWorkerPlugins } from './cdp-cyclotron-plugins-worker.consumer' + +jest.mock('../../../src/utils/fetch', () => { + return { + trackedFetch: jest.fn(() => + Promise.resolve({ + status: 200, + text: () => Promise.resolve(JSON.stringify({ success: true })), + json: () => Promise.resolve({ success: true }), + }) + ), + } +}) + +const mockFetch: jest.Mock = require('../../../src/utils/fetch').trackedFetch + +jest.setTimeout(1000) + +/** + * NOTE: The internal and normal events consumers are very similar so we can test them together + */ +describe('CdpCyclotronWorkerPlugins', () => { + let processor: CdpCyclotronWorkerPlugins + let hub: Hub + let team: Team + let fn: HogFunctionType + let globals: HogFunctionInvocationGlobalsWithInputs + + const insertHogFunction = async (hogFunction: Partial) => { + const item = await _insertHogFunction(hub.postgres, team.id, { + ...hogFunction, + type: 'destination', + }) + // Trigger the reload that django would do + await processor.hogFunctionManager.reloadAllHogFunctions() + return item + } + + beforeEach(async () => { + await resetTestDatabase() + hub = await createHub() + + team = await getFirstTeam(hub) + + processor = new CdpCyclotronWorkerPlugins(hub) + await processor.start() + + mockFetch.mockClear() + + const fixedTime = DateTime.fromObject({ year: 2025, month: 1, day: 1 }, { zone: 'UTC' }) + jest.spyOn(Date, 'now').mockReturnValue(fixedTime.toMillis()) + + fn = await insertHogFunction({ + name: 'Plugin test', + template_id: 'plugin-intercom', + }) + globals = { + ...createHogExecutionGlobals({ + project: { + id: team.id, + } as any, + event: { + uuid: 'b3a1fe86-b10c-43cc-acaf-d208977608d0', + event: '$pageview', + properties: { + $current_url: 'https://posthog.com', + $lib_version: '1.0.0', + }, + } as any, + }), + inputs: { + intercomApiKey: '1234567890', + triggeringEvents: '$identify,mycustomevent', + ignoredEmailDomains: 'posthog.com,dev.posthog.com', + useEuropeanDataStorage: 'No', + }, + } + }) + + afterEach(async () => { + jest.setTimeout(10000) + await processor.stop() + await closeHub(hub) + }) + + afterAll(() => { + jest.useRealTimers() + }) + + describe('setupPlugin', () => { + it('should setup a plugin on first call', async () => { + jest.spyOn(PLUGINS_BY_ID['intercom'], 'setupPlugin') + + const results = [] + + results.push(processor.executePluginInvocation(createInvocation(fn, globals))) + results.push(processor.executePluginInvocation(createInvocation(fn, globals))) + results.push(processor.executePluginInvocation(createInvocation(fn, globals))) + + expect(await Promise.all(results)).toMatchObject([ + { finished: true }, + { finished: true }, + { finished: true }, + ]) + + expect(PLUGINS_BY_ID['intercom'].setupPlugin).toHaveBeenCalledTimes(1) + expect(jest.mocked(PLUGINS_BY_ID['intercom'].setupPlugin!).mock.calls[0][0]).toMatchInlineSnapshot(` + { + "attachments": {}, + "cache": {}, + "config": {}, + "fetch": [Function], + "geoip": {}, + "global": { + "ignoredEmailDomains": "posthog.com,dev.posthog.com", + "intercomApiKey": "1234567890", + "triggeringEvents": "$identify,mycustomevent", + "useEuropeanDataStorage": "No", + }, + "jobs": {}, + "metrics": {}, + "storage": {}, + "utils": {}, + } + `) + }) + }) + + describe('onEvent', () => { + it('should call the plugin onEvent method', async () => { + jest.spyOn(PLUGINS_BY_ID['intercom'], 'onEvent') + + const results = [] + + results.push(processor.executePluginInvocation(createInvocation(fn, globals))) + results.push(processor.executePluginInvocation(createInvocation(fn, globals))) + results.push(processor.executePluginInvocation(createInvocation(fn, globals))) + + expect(await Promise.all(results)).toMatchObject([ + { finished: true }, + { finished: true }, + { finished: true }, + ]) + }) + }) +}) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index dfb8eca718f0c..9ec7216dce02c 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -2,16 +2,16 @@ import { Meta, ProcessedPluginEvent } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' import { PLUGINS_BY_ID } from '../legacy-plugins/manager' +import { FetchType, MetaWithFetch } from '../legacy-plugins/types' import { HogFunctionInvocation, HogFunctionInvocationResult, HogFunctionTypeType } from '../types' import { CdpCyclotronWorker } from './cdp-cyclotron-worker.consumer' type PluginState = { setupPromise: Promise + errored: boolean meta: Meta } -const PLUGIN_STATE: Record = {} - /** * NOTE: This is a consumer to take care of legacy plugins. */ @@ -20,11 +20,18 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { protected queue = 'plugins' as const protected hogTypes: HogFunctionTypeType[] = ['destination'] + private pluginState: Record = {} + public async processInvocations(invocations: HogFunctionInvocation[]): Promise { return await this.runManyWithHeartbeat(invocations, (item) => this.executePluginInvocation(item)) } - private async executePluginInvocation(invocation: HogFunctionInvocation): Promise { + public fetch(...args: Parameters) { + // TOOD: THis better + return this.fetchExecutor.fetch(...args) + } + + public async executePluginInvocation(invocation: HogFunctionInvocation): Promise { const result: HogFunctionInvocationResult = { invocation, finished: true, @@ -33,17 +40,17 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { } const pluginId = invocation.hogFunction.template_id?.startsWith('plugin-') - ? invocation.hogFunction.template_id - : `plugin-${invocation.hogFunction.template_id}` + ? invocation.hogFunction.template_id.replace('plugin-', '') + : null result.logs.push({ level: 'debug', timestamp: DateTime.now(), message: `Executing plugin ${pluginId}`, }) - const plugin = PLUGINS_BY_ID[pluginId] + const plugin = pluginId ? PLUGINS_BY_ID[pluginId] : null - if (!plugin) { + if (!plugin || !pluginId) { result.error = new Error(`Plugin ${pluginId} not found`) result.logs.push({ level: 'error', @@ -53,9 +60,43 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { return result } - // Convert the invocation into the right interface for the plugin + let state = this.pluginState[pluginId] - const inputs = invocation.globals.inputs + if (!state) { + const meta: MetaWithFetch = { + global: invocation.globals.inputs, + attachments: {}, + config: {}, + jobs: {}, + metrics: {}, + cache: {} as any, + storage: {} as any, // NOTE: Figuree out what to do about storage as that is used... + geoip: {} as any, + utils: {} as any, + fetch: this.fetch, + } + + state = this.pluginState[pluginId] = { + setupPromise: plugin.setupPlugin?.(meta) ?? Promise.resolve(), + meta, + errored: false, + } + } + + try { + await state.setupPromise + } catch (e) { + state.errored = true + result.error = e + result.logs.push({ + level: 'error', + timestamp: DateTime.now(), + message: `Plugin ${pluginId} setup failed`, + }) + return result + } + + // Convert the invocation into the right interface for the plugin const event: ProcessedPluginEvent = { distinct_id: invocation.globals.event.distinct_id, @@ -77,32 +118,12 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { : undefined, } - let state = PLUGIN_STATE[pluginId] - - if (!state) { - const meta: Meta = { - global: inputs, - attachments: {}, - config: {}, - jobs: {}, - metrics: {}, - cache: {} as any, - storage: {} as any, // NOTE: Figuree out what to do about storage as that is used... - geoip: {} as any, - utils: {} as any, - } - - state = PLUGIN_STATE[pluginId] = { - setupPromise: plugin.setupPlugin?.(meta) ?? Promise.resolve(), - meta, - } - } - - await state.setupPromise + await plugin.onEvent?.(event, state.meta) - await plugin.onEvent?.(event, { - ...state.meta, - global: inputs, + result.logs.push({ + level: 'debug', + timestamp: DateTime.now(), + message: `Plugin ${pluginId} execution successful`, }) return result diff --git a/plugin-server/src/cdp/legacy-plugins/manager.ts b/plugin-server/src/cdp/legacy-plugins/manager.ts index f6de65c90608b..45861c579c4ff 100644 --- a/plugin-server/src/cdp/legacy-plugins/manager.ts +++ b/plugin-server/src/cdp/legacy-plugins/manager.ts @@ -1,5 +1,6 @@ import { customerioPlugin } from './customerio' - +import { intercomPlugin } from './intercom' export const PLUGINS_BY_ID = { [customerioPlugin.id]: customerioPlugin, + [intercomPlugin.id]: intercomPlugin, } diff --git a/plugin-server/src/cdp/legacy-plugins/types.ts b/plugin-server/src/cdp/legacy-plugins/types.ts index cde9ed0529317..739079116e8b6 100644 --- a/plugin-server/src/cdp/legacy-plugins/types.ts +++ b/plugin-server/src/cdp/legacy-plugins/types.ts @@ -1,4 +1,5 @@ -import { Plugin } from '@posthog/plugin-scaffold' +import { Meta, Plugin } from '@posthog/plugin-scaffold' +import fetch from 'node-fetch' export type LegacyPlugin = { id: string @@ -7,3 +8,13 @@ export type LegacyPlugin = { onEvent: Plugin['onEvent'] setupPlugin: Plugin['setupPlugin'] } + +export type FetchType = typeof fetch + +export type MetaWithFetch = Meta & { + fetch: FetchType +} + +export type PluginWithFetch = Plugin & { + fetch: FetchType +} From 52792bf16ec7c5901c80b54fcb3d9755a2579772 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 17:51:14 +0100 Subject: [PATCH 03/46] Fixes --- ...-cyclotron-plugins-worker.consumer.test.ts | 50 ++++++++++++++----- .../cdp-cyclotron-plugins-worker.consumer.ts | 10 ++-- .../legacy-plugins/{manager.ts => index.ts} | 1 + 3 files changed, 45 insertions(+), 16 deletions(-) rename plugin-server/src/cdp/legacy-plugins/{manager.ts => index.ts} (99%) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts index c45d2eedc521f..08685c32a3ea0 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts @@ -5,12 +5,11 @@ import { createInvocation, insertHogFunction as _insertHogFunction, } from '~/tests/cdp/fixtures' -import { forSnapshot } from '~/tests/helpers/snapshots' import { getFirstTeam, resetTestDatabase } from '~/tests/helpers/sql' import { Hub, Team } from '../../types' import { closeHub, createHub } from '../../utils/db/hub' -import { PLUGINS_BY_ID } from '../legacy-plugins/manager' +import { PLUGINS_BY_ID } from '../legacy-plugins' import { HogFunctionInvocationGlobalsWithInputs, HogFunctionType } from '../types' import { CdpCyclotronWorkerPlugins } from './cdp-cyclotron-plugins-worker.consumer' @@ -57,6 +56,7 @@ describe('CdpCyclotronWorkerPlugins', () => { team = await getFirstTeam(hub) processor = new CdpCyclotronWorkerPlugins(hub) + await processor.start() mockFetch.mockClear() @@ -79,13 +79,16 @@ describe('CdpCyclotronWorkerPlugins', () => { properties: { $current_url: 'https://posthog.com', $lib_version: '1.0.0', + $set: { + email: 'test@posthog.com', + }, }, } as any, }), inputs: { intercomApiKey: '1234567890', triggeringEvents: '$identify,mycustomevent', - ignoredEmailDomains: 'posthog.com,dev.posthog.com', + ignoredEmailDomains: 'dev.posthog.com', useEuropeanDataStorage: 'No', }, } @@ -144,17 +147,40 @@ describe('CdpCyclotronWorkerPlugins', () => { it('should call the plugin onEvent method', async () => { jest.spyOn(PLUGINS_BY_ID['intercom'], 'onEvent') - const results = [] + const invocation = createInvocation(fn, globals) + invocation.globals.event.event = 'mycustomevent' + invocation.globals.event.properties = { + email: 'test@posthog.com', + } + await processor.executePluginInvocation(invocation) - results.push(processor.executePluginInvocation(createInvocation(fn, globals))) - results.push(processor.executePluginInvocation(createInvocation(fn, globals))) - results.push(processor.executePluginInvocation(createInvocation(fn, globals))) + expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) + expect(jest.mocked(PLUGINS_BY_ID['intercom'].onEvent!).mock.calls[0][0]).toMatchInlineSnapshot(` + { + "$set": undefined, + "$set_once": undefined, + "distinct_id": "distinct_id", + "event": "mycustomevent", + "ip": undefined, + "person": { + "created_at": "", + "properties": { + "email": "test@posthog.com", + "first_name": "Pumpkin", + }, + "team_id": 2, + "uuid": "uuid", + }, + "properties": { + "email": "test@posthog.com", + }, + "team_id": 2, + "timestamp": "2025-01-23T15:59:22.483Z", + "uuid": "b3a1fe86-b10c-43cc-acaf-d208977608d0", + } + `) - expect(await Promise.all(results)).toMatchObject([ - { finished: true }, - { finished: true }, - { finished: true }, - ]) + expect(mockFetch).toHaveBeenCalledTimes(1) }) }) }) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 9ec7216dce02c..c9d3af0a695f1 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -1,7 +1,9 @@ import { Meta, ProcessedPluginEvent } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' -import { PLUGINS_BY_ID } from '../legacy-plugins/manager' +import { trackedFetch } from '~/src/utils/fetch' + +import { PLUGINS_BY_ID } from '../legacy-plugins' import { FetchType, MetaWithFetch } from '../legacy-plugins/types' import { HogFunctionInvocation, HogFunctionInvocationResult, HogFunctionTypeType } from '../types' import { CdpCyclotronWorker } from './cdp-cyclotron-worker.consumer' @@ -28,7 +30,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { public fetch(...args: Parameters) { // TOOD: THis better - return this.fetchExecutor.fetch(...args) + return trackedFetch(...args) } public async executePluginInvocation(invocation: HogFunctionInvocation): Promise { @@ -64,9 +66,9 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { if (!state) { const meta: MetaWithFetch = { - global: invocation.globals.inputs, + config: invocation.globals.inputs, attachments: {}, - config: {}, + globalwu: {}, jobs: {}, metrics: {}, cache: {} as any, diff --git a/plugin-server/src/cdp/legacy-plugins/manager.ts b/plugin-server/src/cdp/legacy-plugins/index.ts similarity index 99% rename from plugin-server/src/cdp/legacy-plugins/manager.ts rename to plugin-server/src/cdp/legacy-plugins/index.ts index 45861c579c4ff..f15927da6081b 100644 --- a/plugin-server/src/cdp/legacy-plugins/manager.ts +++ b/plugin-server/src/cdp/legacy-plugins/index.ts @@ -1,5 +1,6 @@ import { customerioPlugin } from './customerio' import { intercomPlugin } from './intercom' + export const PLUGINS_BY_ID = { [customerioPlugin.id]: customerioPlugin, [intercomPlugin.id]: intercomPlugin, From dfb9e0ddab900afab23922bf660f7e1a772e672f Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 17:56:03 +0100 Subject: [PATCH 04/46] Fixes --- ...-cyclotron-plugins-worker.consumer.test.ts | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts index 08685c32a3ea0..da5a95800a254 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts @@ -5,6 +5,7 @@ import { createInvocation, insertHogFunction as _insertHogFunction, } from '~/tests/cdp/fixtures' +import { forSnapshot } from '~/tests/helpers/snapshots' import { getFirstTeam, resetTestDatabase } from '~/tests/helpers/sql' import { Hub, Team } from '../../types' @@ -83,6 +84,7 @@ describe('CdpCyclotronWorkerPlugins', () => { email: 'test@posthog.com', }, }, + timestamp: fixedTime.toISO(), } as any, }), inputs: { @@ -152,16 +154,20 @@ describe('CdpCyclotronWorkerPlugins', () => { invocation.globals.event.properties = { email: 'test@posthog.com', } + + mockFetch.mockResolvedValue({ + status: 200, + json: () => Promise.resolve({ total_count: 1 }), + }) + await processor.executePluginInvocation(invocation) expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) - expect(jest.mocked(PLUGINS_BY_ID['intercom'].onEvent!).mock.calls[0][0]).toMatchInlineSnapshot(` + expect(forSnapshot(jest.mocked(PLUGINS_BY_ID['intercom'].onEvent!).mock.calls[0][0])) + .toMatchInlineSnapshot(` { - "$set": undefined, - "$set_once": undefined, "distinct_id": "distinct_id", "event": "mycustomevent", - "ip": undefined, "person": { "created_at": "", "properties": { @@ -175,12 +181,40 @@ describe('CdpCyclotronWorkerPlugins', () => { "email": "test@posthog.com", }, "team_id": 2, - "timestamp": "2025-01-23T15:59:22.483Z", - "uuid": "b3a1fe86-b10c-43cc-acaf-d208977608d0", + "timestamp": "2025-01-01T00:00:00.000Z", + "uuid": "", } `) - expect(mockFetch).toHaveBeenCalledTimes(1) + expect(mockFetch).toHaveBeenCalledTimes(2) + expect(forSnapshot(mockFetch.mock.calls[0])).toMatchInlineSnapshot(` + [ + "https://api.intercom.io/contacts/search", + { + "body": "{"query":{"field":"email","operator":"=","value":"test@posthog.com"}}", + "headers": { + "Accept": "application/json", + "Authorization": "Bearer 1234567890", + "Content-Type": "application/json", + }, + "method": "POST", + }, + ] + `) + expect(forSnapshot(mockFetch.mock.calls[1])).toMatchInlineSnapshot(` + [ + "https://api.intercom.io/events", + { + "body": "{"event_name":"mycustomevent","created_at":null,"email":"test@posthog.com","id":"distinct_id"}", + "headers": { + "Accept": "application/json", + "Authorization": "Bearer 1234567890", + "Content-Type": "application/json", + }, + "method": "POST", + }, + ] + `) }) }) }) From 6c2575adca1b40cb1221c5ae2f885bdfa18d07f6 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 17:59:40 +0100 Subject: [PATCH 05/46] Fixes --- ...-cyclotron-plugins-worker.consumer.test.ts | 42 ++++++++++++++++--- .../cdp-cyclotron-plugins-worker.consumer.ts | 27 ++++++++---- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts index da5a95800a254..8cff66d917e7a 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts @@ -127,15 +127,15 @@ describe('CdpCyclotronWorkerPlugins', () => { { "attachments": {}, "cache": {}, - "config": {}, - "fetch": [Function], - "geoip": {}, - "global": { - "ignoredEmailDomains": "posthog.com,dev.posthog.com", + "config": { + "ignoredEmailDomains": "dev.posthog.com", "intercomApiKey": "1234567890", "triggeringEvents": "$identify,mycustomevent", "useEuropeanDataStorage": "No", }, + "fetch": [Function], + "geoip": {}, + "globalwu": {}, "jobs": {}, "metrics": {}, "storage": {}, @@ -216,5 +216,37 @@ describe('CdpCyclotronWorkerPlugins', () => { ] `) }) + + it('should handle and collect errors', async () => { + jest.spyOn(PLUGINS_BY_ID['intercom'], 'onEvent') + + const invocation = createInvocation(fn, globals) + invocation.globals.event.event = 'mycustomevent' + invocation.globals.event.properties = { + email: 'test@posthog.com', + } + + mockFetch.mockRejectedValue(new Error('Test error')) + + const res = await processor.executePluginInvocation(invocation) + + expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) + + expect(res.error).toBeInstanceOf(Error) + expect(forSnapshot(res.logs)).toMatchInlineSnapshot(` + [ + { + "level": "debug", + "message": "Executing plugin intercom", + "timestamp": "2025-01-01T01:00:00.000+01:00", + }, + { + "level": "error", + "message": "Plugin intercom execution failed", + "timestamp": "2025-01-01T01:00:00.000+01:00", + }, + ] + `) + }) }) }) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index c9d3af0a695f1..fa8c18a43c5e0 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -1,4 +1,4 @@ -import { Meta, ProcessedPluginEvent } from '@posthog/plugin-scaffold' +import { Meta, ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' import { trackedFetch } from '~/src/utils/fetch' @@ -120,13 +120,24 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { : undefined, } - await plugin.onEvent?.(event, state.meta) - - result.logs.push({ - level: 'debug', - timestamp: DateTime.now(), - message: `Plugin ${pluginId} execution successful`, - }) + try { + await plugin.onEvent?.(event, state.meta) + result.logs.push({ + level: 'debug', + timestamp: DateTime.now(), + message: `Plugin ${pluginId} execution successful`, + }) + } catch (e) { + if (e instanceof RetryError) { + // NOTE: Schedule as a retry to cyclotron? + } + result.error = e + result.logs.push({ + level: 'error', + timestamp: DateTime.now(), + message: `Plugin ${pluginId} execution failed`, + }) + } return result } From f7db6e5883c846e87dccbde7209aede8064c4f59 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 18:00:06 +0100 Subject: [PATCH 06/46] Fix --- .../cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts | 2 +- .../src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts index 8cff66d917e7a..d74f12d73705c 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts @@ -135,7 +135,7 @@ describe('CdpCyclotronWorkerPlugins', () => { }, "fetch": [Function], "geoip": {}, - "globalwu": {}, + "global": {}, "jobs": {}, "metrics": {}, "storage": {}, diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index fa8c18a43c5e0..e202d9e2bea30 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -68,7 +68,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { const meta: MetaWithFetch = { config: invocation.globals.inputs, attachments: {}, - globalwu: {}, + global: {}, jobs: {}, metrics: {}, cache: {} as any, From 835d8fb3b77bad0a1b1b01c6a4ae45ff5af988e3 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 18:04:54 +0100 Subject: [PATCH 07/46] Fixes --- .../cdp-processed-events.consumer.ts | 2 +- plugin-server/tests/cdp/cdp-e2e.test.ts | 114 ++++++++++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts b/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts index 52b6e558c41e6..67b434c9979b2 100644 --- a/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts @@ -41,7 +41,7 @@ export class CdpProcessedEventsConsumer extends CdpConsumerBase { return { teamId: item.globals.project.id, functionId: item.hogFunction.id, - queueName: 'hog', + queueName: item.hogFunction.template_id?.startsWith('plugin-') ? 'plugin' : 'hog', priority: item.priority, vmState: serializeHogFunctionInvocation(item), } diff --git a/plugin-server/tests/cdp/cdp-e2e.test.ts b/plugin-server/tests/cdp/cdp-e2e.test.ts index cce755643caa9..50db3eb85f189 100644 --- a/plugin-server/tests/cdp/cdp-e2e.test.ts +++ b/plugin-server/tests/cdp/cdp-e2e.test.ts @@ -3,6 +3,7 @@ import { getProducedKafkaMessages, getProducedKafkaMessagesForTopic } from '../h import { CdpCyclotronWorker, CdpCyclotronWorkerFetch } from '../../src/cdp/consumers/cdp-cyclotron-worker.consumer' import { CdpProcessedEventsConsumer } from '../../src/cdp/consumers/cdp-processed-events.consumer' +import { CdpCyclotronWorkerPlugins } from '../../src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer' import { HogFunctionInvocationGlobals, HogFunctionType } from '../../src/cdp/types' import { KAFKA_APP_METRICS_2, KAFKA_LOG_ENTRIES } from '../../src/config/kafka-topics' import { Hub, Team } from '../../src/types' @@ -34,6 +35,8 @@ describe('CDP Consumer loop', () => { let processedEventsConsumer: CdpProcessedEventsConsumer let cyclotronWorker: CdpCyclotronWorker | undefined let cyclotronFetchWorker: CdpCyclotronWorkerFetch | undefined + let cdpCyclotronWorkerPlugins: CdpCyclotronWorkerPlugins | undefined + let hub: Hub let team: Team let fnFetchNoFilters: HogFunctionType @@ -62,6 +65,8 @@ describe('CDP Consumer loop', () => { cyclotronWorker = new CdpCyclotronWorker(hub) await cyclotronWorker.start() + cdpCyclotronWorkerPlugins = new CdpCyclotronWorkerPlugins(hub) + await cdpCyclotronWorkerPlugins.start() cyclotronFetchWorker = new CdpCyclotronWorkerFetch(hub) await cyclotronFetchWorker.start() @@ -88,6 +93,7 @@ describe('CDP Consumer loop', () => { processedEventsConsumer?.stop().then(() => console.log('Stopped processedEventsConsumer')), cyclotronWorker?.stop().then(() => console.log('Stopped cyclotronWorker')), cyclotronFetchWorker?.stop().then(() => console.log('Stopped cyclotronFetchWorker')), + cdpCyclotronWorkerPlugins?.stop().then(() => console.log('Stopped cdpCyclotronWorkerPlugins')), ] await Promise.all(stoppers) @@ -210,5 +216,113 @@ describe('CDP Consumer loop', () => { }, ]) }) + + it('should invoke a legacy plugin in the worker loop until completed', async () => { + const invocations = await processedEventsConsumer.processBatch([globals]) + expect(invocations).toHaveLength(1) + + await waitForExpect(() => { + expect(getProducedKafkaMessages()).toHaveLength(7) + }, 5000) + + expect(mockFetch).toHaveBeenCalledTimes(1) + + expect(mockFetch.mock.calls[0]).toMatchInlineSnapshot(` + [ + "https://example.com/posthog-webhook", + { + "body": "{"event":{"uuid":"b3a1fe86-b10c-43cc-acaf-d208977608d0","event":"$pageview","elements_chain":"","distinct_id":"distinct_id","url":"http://localhost:8000/events/1","properties":{"$current_url":"https://posthog.com","$lib_version":"1.0.0"},"timestamp":"2024-09-03T09:00:00Z"},"groups":{},"nested":{"foo":"http://localhost:8000/events/1"},"person":{"id":"uuid","name":"test","url":"http://localhost:8000/persons/1","properties":{"email":"test@posthog.com","first_name":"Pumpkin"}},"event_url":"http://localhost:8000/events/1-test"}", + "headers": { + "version": "v=1.0.0", + }, + "method": "POST", + "timeout": 10000, + }, + ] + `) + + const logMessages = getProducedKafkaMessagesForTopic(KAFKA_LOG_ENTRIES) + const metricsMessages = getProducedKafkaMessagesForTopic(KAFKA_APP_METRICS_2) + + expect(metricsMessages).toMatchObject([ + { + topic: 'clickhouse_app_metrics2_test', + value: { + app_source: 'hog_function', + app_source_id: fnFetchNoFilters.id.toString(), + count: 1, + metric_kind: 'other', + metric_name: 'fetch', + team_id: 2, + }, + }, + { + topic: 'clickhouse_app_metrics2_test', + value: { + app_source: 'hog_function', + app_source_id: fnFetchNoFilters.id.toString(), + count: 1, + metric_kind: 'success', + metric_name: 'succeeded', + team_id: 2, + }, + }, + ]) + + expect(logMessages).toMatchObject([ + { + topic: 'log_entries_test', + value: { + level: 'debug', + log_source: 'hog_function', + log_source_id: fnFetchNoFilters.id.toString(), + message: 'Executing function', + team_id: 2, + }, + }, + { + topic: 'log_entries_test', + value: { + level: 'debug', + log_source: 'hog_function', + log_source_id: fnFetchNoFilters.id.toString(), + message: expect.stringContaining( + "Suspending function due to async function call 'fetch'. Payload:" + ), + team_id: 2, + }, + }, + { + topic: 'log_entries_test', + value: { + level: 'debug', + log_source: 'hog_function', + log_source_id: fnFetchNoFilters.id.toString(), + message: 'Resuming function', + team_id: 2, + }, + }, + { + topic: 'log_entries_test', + value: { + level: 'info', + log_source: 'hog_function', + log_source_id: fnFetchNoFilters.id.toString(), + message: `Fetch response:, {"status":200,"body":{"success":true}}`, + team_id: 2, + }, + }, + { + topic: 'log_entries_test', + value: { + level: 'debug', + log_source: 'hog_function', + log_source_id: fnFetchNoFilters.id.toString(), + message: expect.stringContaining('Function completed in'), + team_id: 2, + }, + }, + ]) + }) }) }) From dcc8b2fc1faa1b9bde7e6d0a1e3f76e2c84fea7f Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 22:21:50 +0100 Subject: [PATCH 08/46] Fixes --- .../consumers/cdp-cyclotron-plugins-worker.consumer.test.ts | 6 +++--- .../cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts | 2 +- plugin-server/src/utils/fetch.ts | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts index d74f12d73705c..ebb5fca6c9a9a 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts @@ -108,7 +108,7 @@ describe('CdpCyclotronWorkerPlugins', () => { describe('setupPlugin', () => { it('should setup a plugin on first call', async () => { - jest.spyOn(PLUGINS_BY_ID['intercom'], 'setupPlugin') + jest.spyOn(PLUGINS_BY_ID['intercom'] as any, 'setupPlugin') const results = [] @@ -147,7 +147,7 @@ describe('CdpCyclotronWorkerPlugins', () => { describe('onEvent', () => { it('should call the plugin onEvent method', async () => { - jest.spyOn(PLUGINS_BY_ID['intercom'], 'onEvent') + jest.spyOn(PLUGINS_BY_ID['intercom'] as any, 'onEvent') const invocation = createInvocation(fn, globals) invocation.globals.event.event = 'mycustomevent' @@ -218,7 +218,7 @@ describe('CdpCyclotronWorkerPlugins', () => { }) it('should handle and collect errors', async () => { - jest.spyOn(PLUGINS_BY_ID['intercom'], 'onEvent') + jest.spyOn(PLUGINS_BY_ID['intercom'] as any, 'onEvent') const invocation = createInvocation(fn, globals) invocation.globals.event.event = 'mycustomevent' diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index e202d9e2bea30..6e5626ed408ef 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -75,7 +75,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { storage: {} as any, // NOTE: Figuree out what to do about storage as that is used... geoip: {} as any, utils: {} as any, - fetch: this.fetch, + fetch: this.fetch as any, } state = this.pluginState[pluginId] = { diff --git a/plugin-server/src/utils/fetch.ts b/plugin-server/src/utils/fetch.ts index 96358d8ec2864..0fcd39cd20dc1 100644 --- a/plugin-server/src/utils/fetch.ts +++ b/plugin-server/src/utils/fetch.ts @@ -9,6 +9,8 @@ import net from 'node:net' import fetch, { type RequestInfo, type RequestInit, type Response, FetchError, Request } from 'node-fetch' import { URL } from 'url' +export type { Response } + import { runInSpan } from '../sentry' import { isProdEnv } from './env-utils' From 18ef79b43b6134b4ea3e717d3f55ad957995fc8a Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 23 Jan 2025 22:25:43 +0100 Subject: [PATCH 09/46] Fix --- ...rker.consumer.test.ts => cdp-cyclotron-plugins-worker.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugin-server/src/cdp/consumers/{cdp-cyclotron-plugins-worker.consumer.test.ts => cdp-cyclotron-plugins-worker.test.ts} (100%) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts similarity index 100% rename from plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.test.ts rename to plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts From 9317b33fd4a1efe59df4850ab29b0328f63e3ee6 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 09:22:07 +0100 Subject: [PATCH 10/46] Fixes --- .../cdp-cyclotron-plugins-worker.consumer.ts | 16 ++++++---------- .../consumers/cdp-cyclotron-worker.consumer.ts | 2 +- plugin-server/src/cdp/legacy-plugins/types.ts | 13 +------------ 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 6e5626ed408ef..82c22c9da616c 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -1,10 +1,7 @@ import { Meta, ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' -import { trackedFetch } from '~/src/utils/fetch' - import { PLUGINS_BY_ID } from '../legacy-plugins' -import { FetchType, MetaWithFetch } from '../legacy-plugins/types' import { HogFunctionInvocation, HogFunctionInvocationResult, HogFunctionTypeType } from '../types' import { CdpCyclotronWorker } from './cdp-cyclotron-worker.consumer' @@ -25,12 +22,12 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { private pluginState: Record = {} public async processInvocations(invocations: HogFunctionInvocation[]): Promise { - return await this.runManyWithHeartbeat(invocations, (item) => this.executePluginInvocation(item)) - } + const results = await this.runManyWithHeartbeat(invocations, (item) => this.executePluginInvocation(item)) + + await this.processInvocationResults(results) + await this.updateJobs(results) - public fetch(...args: Parameters) { - // TOOD: THis better - return trackedFetch(...args) + return results } public async executePluginInvocation(invocation: HogFunctionInvocation): Promise { @@ -65,7 +62,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { let state = this.pluginState[pluginId] if (!state) { - const meta: MetaWithFetch = { + const meta: Meta = { config: invocation.globals.inputs, attachments: {}, global: {}, @@ -75,7 +72,6 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { storage: {} as any, // NOTE: Figuree out what to do about storage as that is used... geoip: {} as any, utils: {} as any, - fetch: this.fetch as any, } state = this.pluginState[pluginId] = { diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts index 5fd0d1981dc45..1d96123162969 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts @@ -35,7 +35,7 @@ export class CdpCyclotronWorker extends CdpConsumerBase { await this.produceQueuedMessages() } - private async updateJobs(invocations: HogFunctionInvocationResult[]) { + protected async updateJobs(invocations: HogFunctionInvocationResult[]) { await Promise.all( invocations.map((item) => { if (item.invocation.queue === 'fetch') { diff --git a/plugin-server/src/cdp/legacy-plugins/types.ts b/plugin-server/src/cdp/legacy-plugins/types.ts index 739079116e8b6..cde9ed0529317 100644 --- a/plugin-server/src/cdp/legacy-plugins/types.ts +++ b/plugin-server/src/cdp/legacy-plugins/types.ts @@ -1,5 +1,4 @@ -import { Meta, Plugin } from '@posthog/plugin-scaffold' -import fetch from 'node-fetch' +import { Plugin } from '@posthog/plugin-scaffold' export type LegacyPlugin = { id: string @@ -8,13 +7,3 @@ export type LegacyPlugin = { onEvent: Plugin['onEvent'] setupPlugin: Plugin['setupPlugin'] } - -export type FetchType = typeof fetch - -export type MetaWithFetch = Meta & { - fetch: FetchType -} - -export type PluginWithFetch = Plugin & { - fetch: FetchType -} From e47eb3c8c837152f88cd367d4be53fc9d6163708 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 09:23:42 +0100 Subject: [PATCH 11/46] Fix --- .../src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index ebb5fca6c9a9a..05bf5cadb4b4b 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -133,7 +133,6 @@ describe('CdpCyclotronWorkerPlugins', () => { "triggeringEvents": "$identify,mycustomevent", "useEuropeanDataStorage": "No", }, - "fetch": [Function], "geoip": {}, "global": {}, "jobs": {}, From 365c1b898f1120eeb55967e5720a00ace0b92625 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 09:55:33 +0100 Subject: [PATCH 12/46] Added check for metrics production --- .../cdp-cyclotron-plugins-worker.test.ts.snap | 45 +++++++++++++++ .../cdp-cyclotron-plugins-worker.consumer.ts | 1 + .../cdp-cyclotron-plugins-worker.test.ts | 56 ++++++++++--------- 3 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap diff --git a/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap new file mode 100644 index 0000000000000..d509f563624b2 --- /dev/null +++ b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CdpCyclotronWorkerPlugins onEvent should handle and collect errors 3`] = ` +[ + { + "key": "", + "topic": "clickhouse_app_metrics2_test", + "value": { + "app_source": "hog_function", + "app_source_id": "", + "count": 1, + "metric_kind": "failure", + "metric_name": "failed", + "team_id": 2, + "timestamp": "2025-01-01 00:00:00.000", + }, + }, + { + "key": "", + "topic": "log_entries_test", + "value": { + "instance_id": "", + "level": "debug", + "log_source": "hog_function", + "log_source_id": "", + "message": "Executing plugin intercom", + "team_id": 2, + "timestamp": "2025-01-01 00:00:00.000", + }, + }, + { + "key": "", + "topic": "log_entries_test", + "value": { + "instance_id": "", + "level": "error", + "log_source": "hog_function", + "log_source_id": "", + "message": "Plugin intercom execution failed", + "team_id": 2, + "timestamp": "2025-01-01 00:00:00.001", + }, + }, +] +`; diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 82c22c9da616c..14f39d509181b 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -26,6 +26,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { await this.processInvocationResults(results) await this.updateJobs(results) + await this.produceQueuedMessages() return results } diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index 05bf5cadb4b4b..1a2e040c7a6cd 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -5,6 +5,7 @@ import { createInvocation, insertHogFunction as _insertHogFunction, } from '~/tests/cdp/fixtures' +import { getProducedKafkaMessages } from '~/tests/helpers/mocks/producer.mock' import { forSnapshot } from '~/tests/helpers/snapshots' import { getFirstTeam, resetTestDatabase } from '~/tests/helpers/sql' @@ -55,11 +56,13 @@ describe('CdpCyclotronWorkerPlugins', () => { hub = await createHub() team = await getFirstTeam(hub) - processor = new CdpCyclotronWorkerPlugins(hub) await processor.start() + jest.spyOn(processor['cyclotronWorker']!, 'updateJob').mockImplementation(() => {}) + jest.spyOn(processor['cyclotronWorker']!, 'releaseJob').mockImplementation(() => Promise.resolve()) + mockFetch.mockClear() const fixedTime = DateTime.fromObject({ year: 2025, month: 1, day: 1 }, { zone: 'UTC' }) @@ -110,18 +113,14 @@ describe('CdpCyclotronWorkerPlugins', () => { it('should setup a plugin on first call', async () => { jest.spyOn(PLUGINS_BY_ID['intercom'] as any, 'setupPlugin') - const results = [] - - results.push(processor.executePluginInvocation(createInvocation(fn, globals))) - results.push(processor.executePluginInvocation(createInvocation(fn, globals))) - results.push(processor.executePluginInvocation(createInvocation(fn, globals))) - - expect(await Promise.all(results)).toMatchObject([ - { finished: true }, - { finished: true }, - { finished: true }, + const results = processor.processInvocations([ + createInvocation(fn, globals), + createInvocation(fn, globals), + createInvocation(fn, globals), ]) + expect(await results).toMatchObject([{ finished: true }, { finished: true }, { finished: true }]) + expect(PLUGINS_BY_ID['intercom'].setupPlugin).toHaveBeenCalledTimes(1) expect(jest.mocked(PLUGINS_BY_ID['intercom'].setupPlugin!).mock.calls[0][0]).toMatchInlineSnapshot(` { @@ -159,7 +158,7 @@ describe('CdpCyclotronWorkerPlugins', () => { json: () => Promise.resolve({ total_count: 1 }), }) - await processor.executePluginInvocation(invocation) + await processor.processInvocations([invocation]) expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) expect(forSnapshot(jest.mocked(PLUGINS_BY_ID['intercom'].onEvent!).mock.calls[0][0])) @@ -214,6 +213,15 @@ describe('CdpCyclotronWorkerPlugins', () => { }, ] `) + + expect(forSnapshot(jest.mocked(processor['cyclotronWorker']!.updateJob).mock.calls)).toMatchInlineSnapshot(` + [ + [ + "", + "completed", + ], + ] + `) }) it('should handle and collect errors', async () => { @@ -227,25 +235,23 @@ describe('CdpCyclotronWorkerPlugins', () => { mockFetch.mockRejectedValue(new Error('Test error')) - const res = await processor.executePluginInvocation(invocation) + const res = await processor.processInvocations([invocation]) expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) - expect(res.error).toBeInstanceOf(Error) - expect(forSnapshot(res.logs)).toMatchInlineSnapshot(` + expect(res[0].error).toBeInstanceOf(Error) + expect(forSnapshot(res[0].logs)).toMatchInlineSnapshot(`[]`) + + expect(forSnapshot(jest.mocked(processor['cyclotronWorker']!.updateJob).mock.calls)).toMatchInlineSnapshot(` [ - { - "level": "debug", - "message": "Executing plugin intercom", - "timestamp": "2025-01-01T01:00:00.000+01:00", - }, - { - "level": "error", - "message": "Plugin intercom execution failed", - "timestamp": "2025-01-01T01:00:00.000+01:00", - }, + [ + "", + "failed", + ], ] `) + + expect(forSnapshot(getProducedKafkaMessages())).toMatchSnapshot() }) }) }) From 20a304c15ed1071b2f4e909298a8f489b8aed293 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 10:28:21 +0100 Subject: [PATCH 13/46] fixed frontend --- .../hogfunctions/HogFunctionConfiguration.tsx | 22 +++++++++---- .../filters/HogFunctionFilters.tsx | 4 ++- .../_internal/template_legacy_plugin.py | 31 +++++++++++++++++++ posthog/models/hog_functions/hog_function.py | 4 +++ 4 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 posthog/cdp/templates/_internal/template_legacy_plugin.py diff --git a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx index 6f6a9962a1ed4..86dce22800f2b 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx @@ -100,6 +100,8 @@ export function HogFunctionConfiguration({ return } + const isLegacyPlugin = hogFunction?.template?.id?.startsWith('plugin-') + const headerButtons = ( <> {!templateId && ( @@ -107,9 +109,11 @@ export function HogFunctionConfiguration({ - duplicate()}> - Duplicate - + {!isLegacyPlugin && ( + duplicate()}> + Duplicate + + )} deleteHogFunction()}> Delete @@ -174,11 +178,12 @@ export function HogFunctionConfiguration({ ) const canEditSource = displayOptions.canEditSource ?? - ['destination', 'email', 'site_destination', 'site_app', 'transformation'].includes(type) + (['destination', 'email', 'site_destination', 'site_app', 'transformation'].includes(type) && !isLegacyPlugin) const showPersonsCount = displayOptions.showPersonsCount ?? ['broadcast'].includes(type) const showTesting = displayOptions.showTesting ?? - ['destination', 'internal_destination', 'transformation', 'broadcast', 'email'].includes(type) + (['destination', 'internal_destination', 'transformation', 'broadcast', 'email'].includes(type) && + !isLegacyPlugin) return (
@@ -259,7 +264,12 @@ export function HogFunctionConfiguration({ - {hogFunction?.template && !hogFunction.template.id.startsWith('template-blank-') ? ( + {isLegacyPlugin ? ( + + This destination is one of our legacy plugins. It will be deprecated and you + should instead upgrade + + ) : hogFunction?.template && !hogFunction.template.id.startsWith('template-blank-') ? ( } - const showMasking = type === 'destination' + const isLegacyPlugin = configuration?.template?.id?.startsWith('plugin-') + + const showMasking = type === 'destination' && !isLegacyPlugin const showDropEvents = type === 'transformation' return ( diff --git a/posthog/cdp/templates/_internal/template_legacy_plugin.py b/posthog/cdp/templates/_internal/template_legacy_plugin.py new file mode 100644 index 0000000000000..cef66400e47a7 --- /dev/null +++ b/posthog/cdp/templates/_internal/template_legacy_plugin.py @@ -0,0 +1,31 @@ +from posthog.cdp.templates.hog_function_template import HogFunctionTemplate + +legacy_plugin_template: HogFunctionTemplate = HogFunctionTemplate( + status="alpha", + type="destination", + id="template-legacy-plugin", + name="Legacy plugin", + description="Legacy plugins", + icon_url="/static/hedgehog/builder-hog-01.png", + category=["Custom", "Analytics"], + hog=""" +print('not used') +""".strip(), + inputs_schema=[], +) + + +def create_legacy_plugin_template(template_id: str) -> HogFunctionTemplate: + return HogFunctionTemplate( + status="alpha", + type="destination", + id=f"{template_id}", + name=f"Legacy plugin {template_id}", + description="Legacy plugins", + icon_url="/static/hedgehog/builder-hog-01.png", + category=["Custom"], + hog=""" + print('not used') + """.strip(), + inputs_schema=[], + ) diff --git a/posthog/models/hog_functions/hog_function.py b/posthog/models/hog_functions/hog_function.py index a715f10b86b7b..244f887d3724c 100644 --- a/posthog/models/hog_functions/hog_function.py +++ b/posthog/models/hog_functions/hog_function.py @@ -6,6 +6,7 @@ from django.dispatch.dispatcher import receiver import structlog +from posthog.cdp.templates._internal.template_legacy_plugin import create_legacy_plugin_template from posthog.cdp.templates.hog_function_template import HogFunctionTemplate from posthog.helpers.encrypted_fields import EncryptedJSONStringField from posthog.models.action.action import Action @@ -96,6 +97,9 @@ class Meta: def template(self) -> Optional[HogFunctionTemplate]: from posthog.cdp.templates import ALL_HOG_FUNCTION_TEMPLATES_BY_ID + if self.template_id and self.template_id.startswith("plugin-"): + return create_legacy_plugin_template(self.template_id) + return ALL_HOG_FUNCTION_TEMPLATES_BY_ID.get(self.template_id, None) @property From 693bf59d1eb76adb823fc1485160b00af8432673 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 10:31:05 +0100 Subject: [PATCH 14/46] Fixes --- plugin-server/src/capabilities.ts | 6 ++++++ plugin-server/src/main/pluginsServer.ts | 8 ++++++++ plugin-server/src/types.ts | 2 ++ 3 files changed, 16 insertions(+) diff --git a/plugin-server/src/capabilities.ts b/plugin-server/src/capabilities.ts index bb7f34eb39163..55aa5ed25cc4c 100644 --- a/plugin-server/src/capabilities.ts +++ b/plugin-server/src/capabilities.ts @@ -26,6 +26,7 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin cdpProcessedEvents: true, cdpInternalEvents: true, cdpCyclotronWorker: true, + cdpCyclotronWorkerPlugins: true, syncInlinePlugins: true, ...sharedCapabilities, } @@ -139,6 +140,11 @@ export function getPluginServerCapabilities(config: PluginsServerConfig): Plugin cdpCyclotronWorker: true, ...sharedCapabilities, } + case PluginServerMode.cdp_cyclotron_worker_plugins: + return { + cdpCyclotronWorkerPlugins: true, + ...sharedCapabilities, + } // This is only for functional tests, which time out if all capabilities are used // ideally we'd run just the specific capability needed per test, but that's not easy to do atm case PluginServerMode.functional_tests: diff --git a/plugin-server/src/main/pluginsServer.ts b/plugin-server/src/main/pluginsServer.ts index d6c8251b294c5..274e3231e35f3 100644 --- a/plugin-server/src/main/pluginsServer.ts +++ b/plugin-server/src/main/pluginsServer.ts @@ -11,6 +11,7 @@ import v8Profiler from 'v8-profiler-next' import { getPluginServerCapabilities } from '../capabilities' import { CdpApi } from '../cdp/cdp-api' +import { CdpCyclotronWorkerPlugins } from '../cdp/consumers/cdp-cyclotron-plugins-worker.consumer' import { CdpCyclotronWorker, CdpCyclotronWorkerFetch } from '../cdp/consumers/cdp-cyclotron-worker.consumer' import { CdpInternalEventsConsumer } from '../cdp/consumers/cdp-internal-event.consumer' import { CdpProcessedEventsConsumer } from '../cdp/consumers/cdp-processed-events.consumer' @@ -547,6 +548,13 @@ export async function startPluginsServer( } } + if (capabilities.cdpCyclotronWorkerPlugins) { + const hub = await setupHub() + const worker = new CdpCyclotronWorkerPlugins(hub) + await worker.start() + services.push(worker.service) + } + if (capabilities.http) { const app = setupCommonRoutes(services) diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 9cf3d1bdf7f92..5682796f0817c 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -90,6 +90,7 @@ export enum PluginServerMode { cdp_processed_events = 'cdp-processed-events', cdp_internal_events = 'cdp-internal-events', cdp_cyclotron_worker = 'cdp-cyclotron-worker', + cdp_cyclotron_worker_plugins = 'cdp-cyclotron-worker-plugins', functional_tests = 'functional-tests', } @@ -386,6 +387,7 @@ export interface PluginServerCapabilities { cdpProcessedEvents?: boolean cdpInternalEvents?: boolean cdpCyclotronWorker?: boolean + cdpCyclotronWorkerPlugins?: boolean appManagementSingleton?: boolean preflightSchedules?: boolean // Used for instance health checks on hobby deploy, not useful on cloud http?: boolean From 4e8267dc38e8cd44485cf6af0a187d93a90eb430 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 10:38:43 +0100 Subject: [PATCH 15/46] Fix up --- .../src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts | 2 +- .../src/cdp/consumers/cdp-cyclotron-worker.consumer.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 14f39d509181b..a416bad2380b9 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -16,7 +16,7 @@ type PluginState = { */ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { protected name = 'CdpCyclotronWorkerPlugins' - protected queue = 'plugins' as const + protected queue = 'plugin' as const protected hogTypes: HogFunctionTypeType[] = ['destination'] private pluginState: Record = {} diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts index 1d96123162969..185d186a9f2b8 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts @@ -13,7 +13,7 @@ export class CdpCyclotronWorker extends CdpConsumerBase { protected name = 'CdpCyclotronWorker' private cyclotronWorker?: CyclotronWorker private runningWorker: Promise | undefined - protected queue: 'hog' | 'fetch' | 'plugins' = 'hog' + protected queue: 'hog' | 'fetch' | 'plugin' = 'hog' protected hogTypes: HogFunctionTypeType[] = ['destination', 'internal_destination'] public async processInvocations(invocations: HogFunctionInvocation[]): Promise { From 8d2f00b918a76554c0bcbe3d5f29f8dd29a547bf Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 10:39:58 +0100 Subject: [PATCH 16/46] Fix --- .../src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index a416bad2380b9..7c13606539c7d 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -90,7 +90,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { result.logs.push({ level: 'error', timestamp: DateTime.now(), - message: `Plugin ${pluginId} setup failed`, + message: `Plugin ${pluginId} setup failed: ${e.message}`, }) return result } From e3a1ca9a9f1f7c3e640b325ccc1aba0d06b6f34b Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:44:31 +0000 Subject: [PATCH 17/46] Update query snapshots --- .../models/test/__snapshots__/test_cohort.ambr | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr b/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr index 250798eb5711c..bc44a6b098e26 100644 --- a/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr +++ b/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr @@ -233,7 +233,7 @@ WHERE equals(person_distinct_id_overrides.team_id, 99999) GROUP BY person_distinct_id_overrides.distinct_id HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id) - WHERE and(equals(e.team_id, 99999), greaterOrEquals(timestamp, toDateTime64('2023-01-23 00:00:00.000000', 6, 'UTC')), lessOrEquals(timestamp, toDateTime64('2025-01-23 23:59:59.999999', 6, 'UTC')), equals(e.event, '$pageview'))) + WHERE and(equals(e.team_id, 99999), greaterOrEquals(timestamp, toDateTime64('2023-01-27 00:00:00.000000', 6, 'UTC')), lessOrEquals(timestamp, toDateTime64('2025-01-27 23:59:59.999999', 6, 'UTC')), equals(e.event, '$pageview'))) GROUP BY actor_id) AS source ORDER BY source.id ASC LIMIT 100 SETTINGS optimize_aggregation_in_order=1, @@ -374,7 +374,7 @@ actor_id AS id FROM (SELECT min(toTimeZone(e.timestamp, 'UTC')) AS min_timestamp, - minIf(toTimeZone(e.timestamp, 'UTC'), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-08 00:00:00.000000', 6, 'UTC'))) AS min_timestamp_with_condition, + minIf(toTimeZone(e.timestamp, 'UTC'), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-12 00:00:00.000000', 6, 'UTC'))) AS min_timestamp_with_condition, if(not(empty(e__override.distinct_id)), e__override.person_id, e.person_id) AS actor_id, argMin(e.uuid, toTimeZone(e.timestamp, 'UTC')) AS uuid, argMin(e.distinct_id, toTimeZone(e.timestamp, 'UTC')) AS distinct_id @@ -386,7 +386,7 @@ WHERE equals(person_distinct_id_overrides.team_id, 99999) GROUP BY person_distinct_id_overrides.distinct_id HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id) - WHERE and(equals(e.team_id, 99999), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-23 23:59:59.999999', 6, 'UTC')), equals(e.event, 'signup')) + WHERE and(equals(e.team_id, 99999), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-27 23:59:59.999999', 6, 'UTC')), equals(e.event, 'signup')) GROUP BY if(not(empty(e__override.distinct_id)), e__override.person_id, e.person_id) HAVING ifNull(equals(min_timestamp, min_timestamp_with_condition), isNull(min_timestamp) and isNull(min_timestamp_with_condition))) @@ -474,7 +474,7 @@ WHERE equals(person_distinct_id_overrides.team_id, 99999) GROUP BY person_distinct_id_overrides.distinct_id HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id) - WHERE and(equals(e.team_id, 99999), greaterOrEquals(timestamp, toDateTime64('2023-01-23 00:00:00.000000', 6, 'UTC')), lessOrEquals(timestamp, toDateTime64('2025-01-23 23:59:59.999999', 6, 'UTC')), equals(e.event, '$pageview'))) + WHERE and(equals(e.team_id, 99999), greaterOrEquals(timestamp, toDateTime64('2023-01-27 00:00:00.000000', 6, 'UTC')), lessOrEquals(timestamp, toDateTime64('2025-01-27 23:59:59.999999', 6, 'UTC')), equals(e.event, '$pageview'))) GROUP BY actor_id) AS source ORDER BY source.id ASC LIMIT 100 SETTINGS optimize_aggregation_in_order=1, @@ -488,7 +488,7 @@ actor_id AS id FROM (SELECT min(toTimeZone(e.timestamp, 'UTC')) AS min_timestamp, - minIf(toTimeZone(e.timestamp, 'UTC'), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-08 00:00:00.000000', 6, 'UTC'))) AS min_timestamp_with_condition, + minIf(toTimeZone(e.timestamp, 'UTC'), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-12 00:00:00.000000', 6, 'UTC'))) AS min_timestamp_with_condition, if(not(empty(e__override.distinct_id)), e__override.person_id, e.person_id) AS actor_id, argMin(e.uuid, toTimeZone(e.timestamp, 'UTC')) AS uuid, argMin(e.distinct_id, toTimeZone(e.timestamp, 'UTC')) AS distinct_id @@ -500,7 +500,7 @@ WHERE equals(person_distinct_id_overrides.team_id, 99999) GROUP BY person_distinct_id_overrides.distinct_id HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id) - WHERE and(equals(e.team_id, 99999), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-23 23:59:59.999999', 6, 'UTC')), equals(e.event, 'signup')) + WHERE and(equals(e.team_id, 99999), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2025-01-27 23:59:59.999999', 6, 'UTC')), equals(e.event, 'signup')) GROUP BY if(not(empty(e__override.distinct_id)), e__override.person_id, e.person_id) HAVING ifNull(equals(min_timestamp, min_timestamp_with_condition), isNull(min_timestamp) and isNull(min_timestamp_with_condition))) From 9694f077aac475124e20763a51966e8cae248c57 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:44:54 +0000 Subject: [PATCH 18/46] Update UI snapshots for `chromium` (1) --- ...uccess--second-recording-in-list--dark.png | Bin 118489 -> 119098 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 e659453aae2dc6dc59adce6f94b5b795efb3effb..369a08aada28d06319c8499cc4dfd0e36d48115d 100644 GIT binary patch literal 119098 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 literal 118489 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 From e33dd64f977fa30cc7a4e0720e1d06b28e5206d5 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 10:47:20 +0100 Subject: [PATCH 19/46] Fix storage --- .../cdp-cyclotron-plugins-worker.test.ts.snap | 2 +- .../cdp-cyclotron-plugins-worker.consumer.ts | 23 +++++++++++++++---- .../cdp-cyclotron-plugins-worker.test.ts | 6 ++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap index d509f563624b2..e8924a331c548 100644 --- a/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap +++ b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap @@ -36,7 +36,7 @@ exports[`CdpCyclotronWorkerPlugins onEvent should handle and collect errors 3`] "level": "error", "log_source": "hog_function", "log_source_id": "", - "message": "Plugin intercom execution failed", + "message": "Plugin errored: Service is down, retry later", "team_id": 2, "timestamp": "2025-01-01 00:00:00.001", }, diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 7c13606539c7d..b57d9ba535864 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -1,4 +1,4 @@ -import { Meta, ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' +import { Meta, ProcessedPluginEvent, RetryError, StorageExtension } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' import { PLUGINS_BY_ID } from '../legacy-plugins' @@ -11,6 +11,21 @@ type PluginState = { meta: Meta } +const createStorage = (): StorageExtension => { + const storage: Record = {} + return { + get: (key: string) => Promise.resolve(storage[key]), + set: (key: string, value: any) => { + storage[key] = value + return Promise.resolve() + }, + del: (key: string) => { + delete storage[key] + return Promise.resolve() + }, + } +} + /** * NOTE: This is a consumer to take care of legacy plugins. */ @@ -70,7 +85,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { jobs: {}, metrics: {}, cache: {} as any, - storage: {} as any, // NOTE: Figuree out what to do about storage as that is used... + storage: createStorage(), geoip: {} as any, utils: {} as any, } @@ -122,7 +137,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { result.logs.push({ level: 'debug', timestamp: DateTime.now(), - message: `Plugin ${pluginId} execution successful`, + message: `Execution successful`, }) } catch (e) { if (e instanceof RetryError) { @@ -132,7 +147,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { result.logs.push({ level: 'error', timestamp: DateTime.now(), - message: `Plugin ${pluginId} execution failed`, + message: `Plugin errored: ${e.message}`, }) } diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index 1a2e040c7a6cd..43ff26e5882f7 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -136,7 +136,11 @@ describe('CdpCyclotronWorkerPlugins', () => { "global": {}, "jobs": {}, "metrics": {}, - "storage": {}, + "storage": { + "del": [Function], + "get": [Function], + "set": [Function], + }, "utils": {}, } `) From b7781cfdaac3b13016d9f8cff8ee56d30e1e39d0 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:52:33 +0000 Subject: [PATCH 20/46] Update query snapshots --- posthog/api/test/__snapshots__/test_cohort.ambr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posthog/api/test/__snapshots__/test_cohort.ambr b/posthog/api/test/__snapshots__/test_cohort.ambr index 26c2244e971da..8a6006ca4cbaa 100644 --- a/posthog/api/test/__snapshots__/test_cohort.ambr +++ b/posthog/api/test/__snapshots__/test_cohort.ambr @@ -174,7 +174,7 @@ WHERE equals(person_distinct_id_overrides.team_id, 99999) GROUP BY person_distinct_id_overrides.distinct_id HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id) - WHERE and(equals(e.team_id, 99999), greaterOrEquals(timestamp, toDateTime64('2025-01-22 00:00:00.000000', 6, 'UTC')), lessOrEquals(timestamp, toDateTime64('2025-01-23 23:59:59.999999', 6, 'UTC')), equals(e.event, '$pageview'))) + WHERE and(equals(e.team_id, 99999), greaterOrEquals(timestamp, toDateTime64('2025-01-26 00:00:00.000000', 6, 'UTC')), lessOrEquals(timestamp, toDateTime64('2025-01-27 23:59:59.999999', 6, 'UTC')), equals(e.event, '$pageview'))) GROUP BY actor_id) AS source ORDER BY source.id ASC LIMIT 100 SETTINGS optimize_aggregation_in_order=1, From 9001d928b755d9b4ef4d49bc2008fe1dc3f2ff40 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 11:53:31 +0100 Subject: [PATCH 21/46] Fixes --- .../cdp-cyclotron-plugins-worker.consumer.ts | 44 ++- .../cdp-cyclotron-plugins-worker.test.ts | 39 ++- .../cdp/legacy-plugins/customerio/index.ts | 278 ++++++++++++++++++ .../cdp/legacy-plugins/customerio/plugin.json | 60 ++++ .../src/cdp/legacy-plugins/intercom/index.ts | 197 +++++++++++++ .../cdp/legacy-plugins/intercom/plugin.json | 42 +++ plugin-server/src/cdp/legacy-plugins/types.ts | 22 +- 7 files changed, 659 insertions(+), 23 deletions(-) create mode 100644 plugin-server/src/cdp/legacy-plugins/customerio/index.ts create mode 100644 plugin-server/src/cdp/legacy-plugins/customerio/plugin.json create mode 100644 plugin-server/src/cdp/legacy-plugins/intercom/index.ts create mode 100644 plugin-server/src/cdp/legacy-plugins/intercom/plugin.json diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index b57d9ba535864..580212585f761 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -1,7 +1,11 @@ import { Meta, ProcessedPluginEvent, RetryError, StorageExtension } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' +import { Response, trackedFetch } from '~/src/utils/fetch' +import { status } from '~/src/utils/status' + import { PLUGINS_BY_ID } from '../legacy-plugins' +import { LegacyPluginLogger, LegacyPluginMeta } from '../legacy-plugins/types' import { HogFunctionInvocation, HogFunctionInvocationResult, HogFunctionTypeType } from '../types' import { CdpCyclotronWorker } from './cdp-cyclotron-worker.consumer' @@ -46,6 +50,10 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { return results } + public async fetch(...args: Parameters): Promise { + return trackedFetch(...args) + } + public async executePluginInvocation(invocation: HogFunctionInvocation): Promise { const result: HogFunctionInvocationResult = { invocation, @@ -75,10 +83,25 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { return result } + const addLog = (level: 'debug' | 'warn' | 'error' | 'info', ...args: any[]) => { + result.logs.push({ + level, + timestamp: DateTime.now(), + message: args.join(' '), + }) + } + + const logger: LegacyPluginLogger = { + debug: (...args: any[]) => addLog('debug', ...args), + warn: (...args: any[]) => addLog('warn', ...args), + log: (...args: any[]) => addLog('info', ...args), + error: (...args: any[]) => addLog('error', ...args), + } + let state = this.pluginState[pluginId] if (!state) { - const meta: Meta = { + const meta: LegacyPluginMeta = { config: invocation.globals.inputs, attachments: {}, global: {}, @@ -88,6 +111,8 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { storage: createStorage(), geoip: {} as any, utils: {} as any, + fetch: (...args) => this.fetch(...args), + logger: logger, } state = this.pluginState[pluginId] = { @@ -133,7 +158,15 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { } try { - await plugin.onEvent?.(event, state.meta) + status.info('⚡️', 'Executing plugin', { + pluginId, + invocationId: invocation.id, + }) + await plugin.onEvent?.(event, { + ...state.meta, + logger, + fetch: this.fetch, + }) result.logs.push({ level: 'debug', timestamp: DateTime.now(), @@ -143,6 +176,13 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { if (e instanceof RetryError) { // NOTE: Schedule as a retry to cyclotron? } + + status.error('💩', 'Plugin errored', { + error: e, + pluginId, + invocationId: invocation.id, + }) + result.error = e result.logs.push({ level: 'error', diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index 43ff26e5882f7..e1acefe03dfce 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -15,19 +15,19 @@ import { PLUGINS_BY_ID } from '../legacy-plugins' import { HogFunctionInvocationGlobalsWithInputs, HogFunctionType } from '../types' import { CdpCyclotronWorkerPlugins } from './cdp-cyclotron-plugins-worker.consumer' -jest.mock('../../../src/utils/fetch', () => { - return { - trackedFetch: jest.fn(() => - Promise.resolve({ - status: 200, - text: () => Promise.resolve(JSON.stringify({ success: true })), - json: () => Promise.resolve({ success: true }), - }) - ), - } -}) - -const mockFetch: jest.Mock = require('../../../src/utils/fetch').trackedFetch +// jest.mock('../../../src/utils/fetch', () => { +// return { +// trackedFetch: jest.fn(() => +// Promise.resolve({ +// status: 200, +// text: () => Promise.resolve(JSON.stringify({ success: true })), +// json: () => Promise.resolve({ success: true }), +// }) +// ), +// } +// }) + +// const mockFetch: jest.Mock = require('../../../src/utils/fetch').trackedFetch jest.setTimeout(1000) @@ -40,7 +40,7 @@ describe('CdpCyclotronWorkerPlugins', () => { let team: Team let fn: HogFunctionType let globals: HogFunctionInvocationGlobalsWithInputs - + let mockFetch: jest.Mock const insertHogFunction = async (hogFunction: Partial) => { const item = await _insertHogFunction(hub.postgres, team.id, { ...hogFunction, @@ -60,11 +60,11 @@ describe('CdpCyclotronWorkerPlugins', () => { await processor.start() + processor.fetch = mockFetch = jest.fn(() => Promise.resolve({} as any)) + jest.spyOn(processor['cyclotronWorker']!, 'updateJob').mockImplementation(() => {}) jest.spyOn(processor['cyclotronWorker']!, 'releaseJob').mockImplementation(() => Promise.resolve()) - mockFetch.mockClear() - const fixedTime = DateTime.fromObject({ year: 2025, month: 1, day: 1 }, { zone: 'UTC' }) jest.spyOn(Date, 'now').mockReturnValue(fixedTime.toMillis()) @@ -132,9 +132,16 @@ describe('CdpCyclotronWorkerPlugins', () => { "triggeringEvents": "$identify,mycustomevent", "useEuropeanDataStorage": "No", }, + "fetch": [Function], "geoip": {}, "global": {}, "jobs": {}, + "logger": { + "debug": [Function], + "error": [Function], + "log": [Function], + "warn": [Function], + }, "metrics": {}, "storage": { "del": [Function], diff --git a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts new file mode 100644 index 0000000000000..ed32ef0ea730c --- /dev/null +++ b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts @@ -0,0 +1,278 @@ +import { PluginInput, ProcessedPluginEvent } from '@posthog/plugin-scaffold' +import { RetryError } from '@posthog/plugin-scaffold' + +import { Response } from '~/src/utils/fetch' + +import { LegacyPlugin, LegacyPluginMeta } from '../types' + +const DEFAULT_HOST = 'track.customer.io' +const DEFAULT_SEND_EVENTS_FROM_ANONYMOUS_USERS = 'Send all events' + +interface CustomerIoPluginInput extends PluginInput { + config: { + customerioSiteId: string + customerioToken: string + host?: 'track.customer.io' | 'track-eu.customer.io' + identifyByEmail?: 'Yes' | 'No' + sendEventsFromAnonymousUsers?: + | 'Send all events' + | 'Only send events from users with emails' + | 'Only send events from users that have been identified' + eventsToSend?: string + } + global: { + authorizationHeader: string + eventNames: string[] + eventsConfig: EventsConfig + identifyByEmail: boolean + } +} + +type CustomerIoMeta = LegacyPluginMeta +enum EventsConfig { + SEND_ALL = '1', + SEND_EMAILS = '2', + SEND_IDENTIFIED = '3', +} + +const EVENTS_CONFIG_MAP = { + 'Send all events': EventsConfig.SEND_ALL, + 'Only send events from users with emails': EventsConfig.SEND_EMAILS, + 'Only send events from users that have been identified': EventsConfig.SEND_IDENTIFIED, +} + +interface Customer { + status: Set<'seen' | 'identified' | 'with_email'> + existsAlready: boolean + email: string | null +} + +async function callCustomerIoApi( + meta: CustomerIoMeta, + method: NonNullable, + host: string, + path: string, + authorization: string, + body?: any +) { + const headers: Record = { 'User-Agent': 'PostHog Customer.io App', Authorization: authorization } + let bodySerialized: string | undefined + if (body != null) { + headers['Content-Type'] = 'application/json' + bodySerialized = JSON.stringify(body) + } + let response: Response + try { + response = await meta.fetch(`https://${host}${path}`, { method, headers, body: bodySerialized }) + } catch (e) { + throw new RetryError(`Cannot reach the Customer.io API. ${e}`) + } + const responseStatusClass = Math.floor(response.status / 100) + if (response.status === 401 || response.status === 403) { + const responseData = await response.json() + throw new Error( + `Customer.io Site ID or API Key invalid! Response ${response.status}: ${JSON.stringify(responseData)}` + ) + } + if (response.status === 408 || response.status === 429 || responseStatusClass === 5) { + const responseData = await response.json() + throw new RetryError( + `Received a potentially intermittent error from the Customer.io API. Response ${ + response.status + }: ${JSON.stringify(responseData)}` + ) + } + if (responseStatusClass !== 2) { + const responseData = await response.json() + throw new Error( + `Received an unexpected error from the Customer.io API. Response ${response.status}: ${JSON.stringify( + responseData + )}` + ) + } + return response +} + +export const setupPlugin = async (meta: CustomerIoMeta) => { + const { config, global, storage, logger } = meta + const customerioBase64AuthToken = Buffer.from(`${config.customerioSiteId}:${config.customerioToken}`).toString( + 'base64' + ) + global.authorizationHeader = `Basic ${customerioBase64AuthToken}` + global.eventNames = config.eventsToSend + ? (config.eventsToSend as string) + .split(',') + .map((name) => name.trim()) + .filter(Boolean) + : [] + global.eventsConfig = + EVENTS_CONFIG_MAP[config.sendEventsFromAnonymousUsers || DEFAULT_SEND_EVENTS_FROM_ANONYMOUS_USERS] + global.identifyByEmail = config.identifyByEmail === 'Yes' + + const credentialsVerifiedPreviously = await storage.get(global.authorizationHeader, false) + + if (credentialsVerifiedPreviously) { + logger.log('Customer.io credentials verified previously. Completing setupPlugin.') + return + } + + // See https://www.customer.io/docs/api/#operation/getCioAllowlist + await callCustomerIoApi(meta, 'GET', 'api.customer.io', '/v1/api/info/ip_addresses', global.authorizationHeader) + await storage.set(global.authorizationHeader, true) + logger.log('Successfully authenticated with Customer.io. Completing setupPlugin.') +} + +export const onEvent = async (event: ProcessedPluginEvent, meta: CustomerIoMeta) => { + const { global, config, logger } = meta + // KLUDGE: This shouldn't even run if setupPlugin failed. Needs to be fixed at the plugin server level + if (!global.eventNames) { + throw new RetryError('Cannot run exportEvents because setupPlugin failed!') + } + + if (global.eventNames.length !== 0 && !global.eventNames.includes(event.event)) { + return + } + if (event.event === '$create_alias') { + return + } + + const customer: Customer = await syncCustomerMetadata(meta, event) + logger.debug(customer) + logger.debug(shouldCustomerBeTracked(customer, global.eventsConfig)) + if (!shouldCustomerBeTracked(customer, global.eventsConfig)) { + return + } + + await exportSingleEvent( + meta, + event, + customer, + global.authorizationHeader, + config.host || DEFAULT_HOST, + global.identifyByEmail + ) +} + +async function syncCustomerMetadata(meta: CustomerIoMeta, event: ProcessedPluginEvent): Promise { + const { storage, logger } = meta + const customerStatusKey = `customer-status/${event.distinct_id}` + const customerStatusArray = (await storage.get(customerStatusKey, [])) as string[] + const customerStatus = new Set(customerStatusArray) as Customer['status'] + const customerExistsAlready = customerStatus.has('seen') + const email = getEmailFromEvent(event) + + logger.debug(email) + + // Update customer status + customerStatus.add('seen') + if (event.event === '$identify') { + customerStatus.add('identified') + } + if (email) { + customerStatus.add('with_email') + } + + if (customerStatus.size > customerStatusArray.length) { + await storage.set(customerStatusKey, Array.from(customerStatus)) + } + + return { + status: customerStatus, + existsAlready: customerExistsAlready, + email, + } +} + +function shouldCustomerBeTracked(customer: Customer, eventsConfig: EventsConfig): boolean { + switch (eventsConfig) { + case EventsConfig.SEND_ALL: + return true + case EventsConfig.SEND_EMAILS: + return customer.status.has('with_email') + case EventsConfig.SEND_IDENTIFIED: + return customer.status.has('identified') + default: + throw new Error(`Unknown eventsConfig: ${eventsConfig}`) + } +} + +async function exportSingleEvent( + meta: CustomerIoMeta, + event: ProcessedPluginEvent, + customer: Customer, + authorizationHeader: string, + host: string, + identifyByEmail: boolean +) { + // Clean up properties + if (event.properties) { + delete event.properties['$set'] + delete event.properties['$set_once'] + } + + const customerPayload: Record = { + ...(event.$set || {}), + _update: customer.existsAlready, + identifier: event.distinct_id, + } + + if ('created_at' in customerPayload) { + // Timestamp must be in seconds since UNIX epoch. + // See: https://customer.io/docs/journeys/faq-timestamps/. + customerPayload.created_at = Date.parse(customerPayload.created_at) / 1000 + } + + let id = event.distinct_id + + if (customer.email) { + customerPayload.email = customer.email + if (identifyByEmail) { + id = customer.email + } + } + // Create or update customer + // See https://www.customer.io/docs/api/#operation/identify + await callCustomerIoApi(meta, 'PUT', host, `/api/v1/customers/${id}`, authorizationHeader, customerPayload) + + const eventType = event.event === '$pageview' ? 'page' : event.event === '$screen' ? 'screen' : 'event' + const eventTimestamp = (event.timestamp ? new Date(event.timestamp).valueOf() : Date.now()) / 1000 + // Track event + // See https://www.customer.io/docs/api/#operation/track + await callCustomerIoApi(meta, 'POST', host, `/api/v1/customers/${id}/events`, authorizationHeader, { + name: event.event, + type: eventType, + timestamp: eventTimestamp, + data: event.properties || {}, + }) +} + +function isEmail(email: string): boolean { + if (typeof email !== 'string') { + return false + } + const re = + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return re.test(email.toLowerCase()) +} + +function getEmailFromEvent(event: ProcessedPluginEvent): string | null { + const setAttribute = event.$set + if (typeof setAttribute !== 'object' || !setAttribute['email']) { + return null + } + const emailCandidate = setAttribute['email'] + if (isEmail(emailCandidate)) { + return emailCandidate + } + // Use distinct ID as a last resort + if (isEmail(event.distinct_id)) { + return event.distinct_id + } + return null +} + +export const customerioPlugin: LegacyPlugin = { + id: 'customer-io', + setupPlugin, + onEvent, +} diff --git a/plugin-server/src/cdp/legacy-plugins/customerio/plugin.json b/plugin-server/src/cdp/legacy-plugins/customerio/plugin.json new file mode 100644 index 0000000000000..d59671c3d3ab1 --- /dev/null +++ b/plugin-server/src/cdp/legacy-plugins/customerio/plugin.json @@ -0,0 +1,60 @@ +{ + "name": "Customer.io", + "description": "Send event data and emails into Customer.io.", + "posthogVersion": ">= 1.25.0", + "main": "index.ts", + "config": [ + { + "key": "customerioSiteId", + "hint": "Provided during Customer.io setup.", + "name": "Customer.io Site ID", + "type": "string", + "default": "", + "required": true, + "secret": true + }, + { + "key": "customerioToken", + "hint": "Provided during Customer.io setup.", + "name": "Customer.io API Key", + "type": "string", + "default": "", + "required": true, + "secret": true + }, + { + "key": "host", + "name": "Tracking Endpoint", + "hint": "Use the EU variant if your Customer.io account is based in the EU region.", + "type": "choice", + "default": "track.customer.io", + "choices": ["track.customer.io", "track-eu.customer.io"] + }, + { + "key": "identifyByEmail", + "name": "Identify by email", + "hint": "If enabled, the plugin will identify users by email instead of ID, whenever an email is available.", + "type": "choice", + "default": "No", + "choices": ["Yes", "No"] + }, + { + "key": "sendEventsFromAnonymousUsers", + "name": "Filtering of Anonymous Users", + "type": "choice", + "hint": "Customer.io pricing is based on the number of customers. This is an option to only send events from users that have been identified. Take into consideration that merging after identification won't work (as those previously anonymous events won't be there).", + "default": "Send all events", + "choices": [ + "Send all events", + "Only send events from users that have been identified", + "Only send events from users with emails" + ] + }, + { + "key": "eventsToSend", + "name": "PostHog Event Allowlist", + "type": "string", + "hint": "If this is set, only the specified events (comma-separated) will be sent to Customer.io." + } + ] +} diff --git a/plugin-server/src/cdp/legacy-plugins/intercom/index.ts b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts new file mode 100644 index 0000000000000..bd3568ce65e00 --- /dev/null +++ b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts @@ -0,0 +1,197 @@ +import { Plugin, ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' + +import { Response } from '~/src/utils/fetch' + +import { LegacyPlugin, LegacyPluginMeta } from '../types' + +type IntercomPlugin = Plugin<{ + global: { + intercomUrl: string + } + config: { + intercomApiKey: string + triggeringEvents: string + ignoredEmailDomains: string + useEuropeanDataStorage: string + } +}> + +type IntercomMeta = LegacyPluginMeta + +async function onEvent(event: ProcessedPluginEvent, meta: IntercomMeta): Promise { + if (!isTriggeringEvent(meta.config.triggeringEvents, event.event)) { + return + } + + const intercomUrl = + meta.config.useEuropeanDataStorage === 'Yes' ? 'https://api.eu.intercom.com' : 'https://api.intercom.io' + + const email = getEmailFromEvent(event) + if (!email) { + meta.logger.warn( + `'${event.event}' will not be sent to Intercom because distinct_id is not an email and no 'email' was found in the event properties.` + ) + meta.logger.debug(`Skipped event with UUID ${event.uuid}`) + return + } + + if (isIgnoredEmailDomain(meta.config.ignoredEmailDomains, email)) { + return + } + + const timestamp = getTimestamp(meta, event) + + const isContactInIntercom = await searchForContactInIntercom(meta, intercomUrl, meta.config.intercomApiKey, email) + if (!isContactInIntercom) { + return + } + await sendEventToIntercom( + meta, + intercomUrl, + meta.config.intercomApiKey, + email, + event.event, + event['distinct_id'], + timestamp + ) +} + +async function searchForContactInIntercom(meta: IntercomMeta, url: string, apiKey: string, email: string) { + const searchContactResponse = await fetchWithRetry( + meta, + `${url}/contacts/search`, + { + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: `Bearer ${apiKey}`, + }, + body: JSON.stringify({ + query: { + field: 'email', + operator: '=', + value: email, + }, + }), + }, + 'POST' + ) + const searchContactResponseJson = (await searchContactResponse.json()) as Record + + if (!statusOk(searchContactResponse) || searchContactResponseJson.errors) { + const errorMessage = searchContactResponseJson.errors ? searchContactResponseJson.errors[0].message : '' + meta.logger.error( + `Unable to search contact ${email} in Intercom. Status Code: ${searchContactResponseJson.status}. Error message: ${errorMessage}` + ) + return false + } else { + const found = searchContactResponseJson['total_count'] > 0 + meta.logger.log(`Contact ${email} in Intercom ${found ? 'found' : 'not found'}`) + return found + } +} + +async function sendEventToIntercom( + meta: IntercomMeta, + url: string, + apiKey: string, + email: string, + event: string, + distinct_id: string, + eventSendTime: number +) { + const sendEventResponse = await fetchWithRetry( + meta, + `${url}/events`, + { + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: `Bearer ${apiKey}`, + }, + body: JSON.stringify({ + event_name: event, + created_at: eventSendTime, + email, + id: distinct_id, + }), + }, + 'POST' + ) + + if (!statusOk(sendEventResponse)) { + let errorMessage = '' + try { + const sendEventResponseJson = await sendEventResponse.json() + errorMessage = sendEventResponseJson.errors ? sendEventResponseJson.errors[0].message : '' + } catch {} + meta.logger.error( + `Unable to send event ${event} for ${email} to Intercom. Status Code: ${sendEventResponse.status}. Error message: ${errorMessage}` + ) + } else { + meta.logger.log(`Sent event ${event} for ${email} to Intercom`) + } +} + +async function fetchWithRetry(meta: IntercomMeta, url: string, options = {}, method = 'GET'): Promise { + try { + const res = await meta.fetch(url, { method: method, ...options }) + return res + } catch { + throw new RetryError('Service is down, retry later') + } +} + +function statusOk(res: Response) { + return String(res.status)[0] === '2' +} + +function isEmail(email: string): boolean { + const re = + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return re.test(String(email).toLowerCase()) +} + +function getEmailFromEvent(event: ProcessedPluginEvent): string | null { + if (isEmail(event.distinct_id)) { + return event.distinct_id + } else if (event['$set'] && Object.keys(event['$set']).includes('email')) { + if (isEmail(event['$set']['email'])) { + return event['$set']['email'] + } + } else if (event['properties'] && Object.keys(event['properties']).includes('email')) { + if (isEmail(event['properties']['email'])) { + return event['properties']['email'] + } + } + + return null +} + +function isIgnoredEmailDomain(ignoredEmailDomains: string, email: string): boolean { + const emailDomainsToIgnore = (ignoredEmailDomains || '').split(',').map((e) => e.trim()) + return emailDomainsToIgnore.includes(email.split('@')[1]) +} + +function isTriggeringEvent(triggeringEvents: string, event: string): boolean { + const validEvents = (triggeringEvents || '').split(',').map((e) => e.trim()) + return validEvents.indexOf(event) >= 0 +} + +function getTimestamp(meta: IntercomMeta, event: ProcessedPluginEvent): number { + try { + if (event['timestamp']) { + return Number(event['timestamp']) + } + } catch { + meta.logger.error('Event timestamp cannot be parsed as a number') + } + const date = new Date() + return Math.floor(date.getTime() / 1000) +} + +export const intercomPlugin: LegacyPlugin = { + id: 'intercom', + onEvent, + setupPlugin: () => Promise.resolve(), +} diff --git a/plugin-server/src/cdp/legacy-plugins/intercom/plugin.json b/plugin-server/src/cdp/legacy-plugins/intercom/plugin.json new file mode 100644 index 0000000000000..6de2b2723ffcb --- /dev/null +++ b/plugin-server/src/cdp/legacy-plugins/intercom/plugin.json @@ -0,0 +1,42 @@ +{ + "name": "Intercom", + "url": "TODO", + "description": "Send event data to Intercom on PostHog events.", + "main": "index.ts", + "config": [ + { + "key": "intercomApiKey", + "hint": "Create an [Intercom app](https://developers.intercom.com/building-apps/), then go to Configure > Authentication to find your key.", + "name": "Intercom API Key", + "type": "string", + "default": "", + "required": true, + "secret": true + }, + { + "key": "triggeringEvents", + "hint": "A comma-separated list of PostHog events you want to send to Intercom (e.g.: '$identify,mycustomevent' ).", + "name": "Triggering events", + "type": "string", + "default": "$identify", + "required": true + }, + { + "key": "ignoredEmailDomains", + "hint": "A comma-separated list of email domains to ignore and not send events for in Intercom (e.g. 'posthog.com,dev.posthog.com' ).", + "name": "Email domains to skip", + "type": "string", + "default": "", + "required": false + }, + { + "key": "useEuropeanDataStorage", + "hint": "Send events to api.eu.intercom.com, if you are using Intercom's European Data Hosting.", + "name": "Send events to European Data Hosting", + "type": "choice", + "default": "No", + "choices": ["Yes", "No"], + "required": false + } + ] +} diff --git a/plugin-server/src/cdp/legacy-plugins/types.ts b/plugin-server/src/cdp/legacy-plugins/types.ts index cde9ed0529317..22acb222c50cc 100644 --- a/plugin-server/src/cdp/legacy-plugins/types.ts +++ b/plugin-server/src/cdp/legacy-plugins/types.ts @@ -1,9 +1,21 @@ -import { Plugin } from '@posthog/plugin-scaffold' +import { Meta, PluginInput, ProcessedPluginEvent } from '@posthog/plugin-scaffold' + +import { Response, trackedFetch } from '~/src/utils/fetch' + +export type LegacyPluginLogger = { + debug: (...args: any[]) => void + warn: (...args: any[]) => void + log: (...args: any[]) => void + error: (...args: any[]) => void +} + +export type LegacyPluginMeta = Meta & { + logger: LegacyPluginLogger + fetch: (...args: Parameters) => Promise +} export type LegacyPlugin = { id: string - name: string - description: string - onEvent: Plugin['onEvent'] - setupPlugin: Plugin['setupPlugin'] + onEvent(event: ProcessedPluginEvent, meta: LegacyPluginMeta): Promise + setupPlugin?: (meta: LegacyPluginMeta) => Promise } From d573b2047f66ac7efd3f55491d01eba08901dd5e Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 11:57:59 +0100 Subject: [PATCH 22/46] Fixes --- .../consumers/cdp-cyclotron-plugins-worker.test.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index e1acefe03dfce..52247ddf7216c 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -15,20 +15,6 @@ import { PLUGINS_BY_ID } from '../legacy-plugins' import { HogFunctionInvocationGlobalsWithInputs, HogFunctionType } from '../types' import { CdpCyclotronWorkerPlugins } from './cdp-cyclotron-plugins-worker.consumer' -// jest.mock('../../../src/utils/fetch', () => { -// return { -// trackedFetch: jest.fn(() => -// Promise.resolve({ -// status: 200, -// text: () => Promise.resolve(JSON.stringify({ success: true })), -// json: () => Promise.resolve({ success: true }), -// }) -// ), -// } -// }) - -// const mockFetch: jest.Mock = require('../../../src/utils/fetch').trackedFetch - jest.setTimeout(1000) /** From d0547391f5fb743475650f630c827b9b6bb2a949 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:12:06 +0000 Subject: [PATCH 23/46] Update UI snapshots for `chromium` (1) --- ...uccess--second-recording-in-list--dark.png | Bin 119098 -> 118722 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 369a08aada28d06319c8499cc4dfd0e36d48115d..397bb37bd08f74b083c4f147a14e88d2107cef81 100644 GIT binary patch delta 65556 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 delta 65935 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 z z=Mgr8nbwg;DrL9LlQ;RW6N?pAhs@p|ADuks`m4SE27PW94}iJmiZqD&Sg~bCg?(CZ zlhb|mzO)vy(2%04^=10P5L$L;PY?VPQ?(0M~5qtWaOLpluZks0_&t z1**`xueY%gFm7TJlG6-A4q%DZuXboTIPgg7FxAIbqtvNP004>=G)&j`CYDcC_{60r zYt~+qvA({zh%A2nieh-M{w=@H<-mShCyFb6)2&i3cV}b44se+w7l;>kw_%2pveoNL*l;$mbC z+{(StY-cW=NpbD^bslbR49H3Z1vO8GCM1L=BKpAO>dQeg!L{6dcx)eEX;p`9Ru>T+ zhOx!Z_BM$WXSa--gl;iB0Fe4K#Nv;7c@^u>x>r$^T+Cig8w(9?l9+o)2G2^#@Ig*Y3bTOt$BDPS+`d;9AHsQh{k zu0V+3%SzeDE^HYi7cD3nF0CR}N}A3>%tt zT3LL4v{uEvcQJ-%7VQDE_&z^Oy258y!YBnFE`IwU+^kLEipZ=N!-GdQZ(o;dM>hc_ z1u~OE+huNX{B3I}nx8Si4IG`%xF64@EA8xPi>MXr>gocIm0RHfpzU(sVKOU#f7h;& z1C|S4&|FLhf9w?Otp(Sh*V=Krfkd`YS7;q?;^8^R8=kFZ!!m;p}Ngl4;by$e85 zr2^%K;EEL3KQOtGN>z61(!Lzcz<0q-baZsY*^h^@6}Mv)xGVLlo%P>GM5HK%!6>xo zh^6u6-Yk>VFO$d(sQKMr9S7HBgy2nq8yK?-Z3g7z*~zxBBffusr)#ydlWS|K%VK|9 z7k2_zwKN1YP@>2c`*$X1A_9YgvaC&Zew1{CG13ZqUE3auHB?inGF{6Lh#7=}xhDq0?Xd@h7N=qo$Sz)>F^gI65K&`)frh z-?MLw?8TeR_hBZ@^6#R7f8y8?bZDwx0QX77O;7V|^3zb_#_MC=1|+PjSo|)jwaWIk z-5wCsSRY<>YyMU)E8hPvYt(CEfv>rp+eOXbV(O2l` zTp_R$`#a3R&Aq)zhPbwK8(>{x`l811_>4rkvj-_Y{q$m!DniQOb%fm+ao--%x(;XggsVCj>Sx}y&Djz5XLa9O zQc+T2Le9%2hBI77qoP840og%lPz!_CfX%)HWN9IOKN}lG0qOn-1z-X!v6c7Tq^!EDMw^Q0t!g9ESG!$H%iHE>cxEqhI=#u z=#1nT4s`|Rh{6Jw#`TG?iCA>rr=;HOv3@YO06#?#6(a9Tc0Kn|%_`|l!v|zEu!!%L zYDDSpT)R#V=w+$Nqqpm~!ImXn{Q*GK)YEhc%VuU#R>cFE7#ODfE-K0zt-G?0Wp9ci zi0wx64g-Qa=Nte;fMjid+t+HKtP&mDi#mD#aVW*t&Q2x4imFOo>{8Sa;VNam4A)0? zo@tKeJC?8>xnI7@PtuFTgst3Q~d8GeKS313mro2I;c z2*e#iyT#Q8`;@fUUr)q=28GHQjYe0-3N*KZTDqpxjW12T?JxKJJv}|SV+V)1);!QJ zEfNbKeRgZl?)Qg9RP&zB1iy`rrlh{qkt8XA#g1Q>49dU7$oQ!A*z|Wf?VRe(Vi=*& z+L6={ct&F6;BbCu;5UjLC~ouX`wBao5F6)GXVu}yN_SrkEiGnv_6l9Il#t2qoX`OD zs(`VIwE28hd)__rGb~+Cyu6NDmSik244?kn*!1sipntt&|EpIF`Cr;c|2xi(M7hUKdcPP9i~2jso%!)+}7Vm&ujU!34#UuZg@Fg30+IfNsdW5MlWkczIgdVKj zwq1OqqH^v1yBblyQb@gRFkwbg=ht&4J9h&+Ny(egB1Tm1p%K?xQv-6VouAl3^K9zP2~Cf->XJeYBisOCMcirl;%mP zNG#%ASueV7n|lpFw&&#u`491fd+w>rfBX%;b-(@}1*Tt4pmWvY-2oJ1uvA$R;VFo9 zpP2e_jvTxNUu+LEK@Ouj`4%?Xh0an#5a^AJj1+32`HIi{%Bd-^{zLe$=vV&`6A+b1 zaB;P^iS9c*2_bTJ7U-H(BRzeZ-+JKaklg;l`SV$wKR_Spbz3O)-m$clz!`4ss`ak6 z>ZYcqDl7va@Vkyn2gsC<&hv7=f3K9J07&{m zVC5jYU}ep~E>Dc{*(d{8dIxrXT48785PJhSQ%K&%O3Y;L8GHnp&oDTwbp;S{hI%ld z;^r3yKywy>iF9F`kF^HtKttjUM8U(ZiRS_taUB>Aw7{gndFE$V9kjj6xc^$j2HO0GzZx|TI6&Nz--GvNy|4KDn?UPC=_X0t4E^dO(yoM_2(2NfUp3>v=J(Eh zQ1NrbAw*U+BO~bXmt$uombEd{xzOl=%@=eNfo)=MPL340H>3jXs5bf)>>G?M<89+5U)TDzG5js{EWjW>=mLeKn1CkK!RO3TMTG z7Sy`p$PU}^r*wiEP;7&Cp7m6y2M-at3Z%Ubih&XFJUm$8Gu@i0l$Gd^r|ZdSi3Pd( zNK0nQN{h?TV40rkS}d z^GSbZ0{cF?PMLLyTeAw1UjR0X(H><^m0N*I6)_mjL)CA(JAW#PJx6GEfiv1(B3+uG z-|P{9ynIioG=G)gdKnlvu~TM!FnJ+OR3JsQ`4T1Va$nI#$*t>>!Cr;xWBal00yJO% zT5p_8qpucsZQ3{_J~IGTGfDbZj-7rOw4_sI$8>xBLq_tjSM$;*oiIk+Zeh&MkdBN@ zU?;SgF7w)~J%d!|#9MF0`nb#dUG#xyJK7UxH~EmPIa^s#aTR%R!5Cc(5R%8R@(@ z?8z!xDKjIF^7~_FYk#~!AB=--@xs-{OMBoBiam?_Rq3qGrT@%L(B>{arCCi!R;sbB z4G#v!9r6kVg4CXok8=s+84UGD?Rg-J(;WlTvg_Qp8FBo2Y^N`FTiXhu!k#s5KXy!f z@5%Q>(kNh*VouZWIUL&8T7y87v?(_HM9vOYeN0T$XmG*0YJcs9J|mO<=X5PSy`#?q z_RxFsVFXu-K*7w>%vZ?gFJO|bz1cVtsxPe?$Ocd7`B8KzOH`UM$k%$M>f^BkcE;P=A zP@cKs+QdyND`HMF#PF|)xNqxZd}U6(&!t})78+{iHjwNOpR8A8!@6bmy#|T)~?)yqY;qowpcMayMf|Lv3gVg6N;{->Xi(_P$WGhF8h_9$*@8+~yj zcr1_Ry8K%zn{kDi^GA9}`A7A!7tluHp!;3O%3#$OU>|Q&0w#F%>Q(4~|3P+2{Wje% z`F3cE%i1REv2v&Y5sl5~CbdyghYRV_@S^#?JK9lTH)*BP0%ogfb{}heRCY-Xhl!Ai7+O^;p zFaAJ^-$o^J>o<jIw8%c!0gp7dz?3>vf>PqkMsrvqiALWVoE(heBFT4*CL< zj?@q_bf<+_@WtxFe4w^`o7%W?{BgFN#~jG-kAN~WBHGQ|UfL0MocIx~Ea|zkZ(#AW zMHbM6(eJFTyb9j!rqnRmldL3eBh%hq+z$3X+tSpkS@G<|_Frv0CT-fes=CW~{+KtNZnZ7x|I^xAMn(08ZQqE3 zw19L9C`d~;DBazubVv?e8)N_l0g-O$?yf;WKtMveQ@Xq1x%}Vjy}!QChi4WahFF`~ zd(G_YJdf)rZJ!}1G5xCw*CsPSKcB8*cc+1W~0G^oN*$tR)x$yOmcx17< z3f^%yoW2_$@jAfAwIok;@|gC-)eRE^vn@v+Y4m9z;3A=;Wjf3?z1Lm$T3lQT5&f=( zz4NE;l-hP-=tK+>OwFy82;xjke3g7l+6L0PRF9qBUl=|dde)|tR%6yY(RiEywgXG) z^;C%06^NB}w6#y&sWpYT6Z&K$&V_tO2TkPiV@gZ=0Yow_&FAM&gmIg*g1&x86*4YP z==SEa>rH`)G8?SFN$Jxk9_mjotn4isyN(CzaL$CzFGL}qvzD@lD2oc0o{nB;ZR;SE zZ7c&!aYv!Hq1m^$x9PVm)^pWb&Bap$C;|0 z%!pQK*qn%HtuLO{-D4XJRjo`3y>>1(^RN%!r2S8*7@71-0_6-2 zKGCJyuTsZRR06syf9inGxi5hg;kr~3AHOzkFB(Bo#%2BX-bw|T`1kb+ctsCUZ(Xhj z#M~@__piZud!SPR^4OlfoK$OD$Ww;YTe8z6X$6Jc&gWLRJQo8(qtZREckn(fZsIPI zZ%)_34#I~%w2RAhpWzfy$KoVYeEu)hg{-8e2JYVwr+C3aB zROjPmub*I|3IdAJ9%WTVXM&(5fB(S!2W`a@4j_{@gqi~>B04qp18x>MnPM6zp1}%q zK@zSt3UB`2we*V-=T~9nrq#oLvC&9FB)*~xR_pVa#N~<^yly**(e{+n2c9h;6cD)F zh-u#OP*oa&M8k%+(A{h&<~qis_I`sFc9X{Ok4%+QsWTpTUWc@Dt=ne^cjj0|mf=&{96uHx`2f zf+PQTNoe3?S0zAEL0V*ZXWDMP$Ha~L`Cp>lfBN75-@(aX=d8aw|LG}UTj;!mLroNX z_dROkaT+aBfTel++YRy!I)L`TiAiFJlTT>|YP71!tN#Wwze#4yw-T`>(&2|&sFSv5 zR#hFzM5W(d@3gIz0SDG7g!vB%K6Jw(C(gi{j+JSR!>S@{ySIe|?^u$Kq)1PSqa-7G zC!4>$y7|4wiP4B#*VO{!UUReWrFkm@a)UW)O<%ouT4MQ4J*RZ zv7&H?zsnK7l6S1>xqC5Hr-^l+)kcZ`>6ax8mudO%B2G)|a39|#$qRw-r_cL*bQCsg zNFO1+J=YAaX9dHsu}-d=&Z$J-R{%bBa0&H_G!Kkxgf-XK*(=gbD#1Xaxy`oZR5on@caMzobtrJVQtk7rQtQz_SI ztbBxSXK7d?q5?UrE~&aKZu7Dl3s2nsB{Ez!EWo8;=;KET z-_YQMDk>=vvn9sF#liM&a;G=byj`2!jxp+fFFDa>8++Ry4)phH=<~{%{x`n-P(H($57?-CH0Ni+ttf-MoJ5vxVjDPmz;AX7; z>A3*U?%nOTw)q^G_ble7wbs`17Vb6>=|rbWAOPN-JN4u}GeoZ;oBY+b zmbKKRNEe}TeVny@gn!Z0|r!_9Wk$?i_j<3 zjxz|@N}j#{oy^qxfs&*)2&|`Rf_^xm9Rfmb`_s8xbD*5zt*xo89qV{p-`B@XW|To+ z=>DbvLFH*|*ASgA)dER>XK*)ljh-ur8o zdCWR2FQR29ANc`4hP|uWqTM%gl7_}cP^h`y{M_tID5pf{hYt6QZgS+>O!IfHGt0}x zd@pcm166%u1_%5M>i0kvdWq^wFsj$+%iHK~PZ`gqmzb6YI~W31QWb?4>R^@KKt(I@N6Y&4*GCl_a=u#%IQDLln^0VGM(&p$9NpE0%E7FqoH?7>i8S@f zV7PKmkZVy!UBBmQ;+DOdY^NWuMW$(Q&OlH0DO0v!4r;xE$AqOB`n38bG-J`Wndnlk zWa%*-+81{9=?!Gr5h} zS(y~N1%0{+d}+Ba67=!9#O(imcyGo-mQxz?O;NGnYVxZuVWc zt9=Um)@jr$iARnzp9@b0Kdg{Nl%E*(4QkR2Am@Pf{Jv2DU_1K-Bnw;GDJ#{?UC)(f~`kBLViG#Q(WxBy{Kv`uBiK~dUGUi{MRtT51J9GzgL#? zK0fL3%cq*F;L)vrJ$yaM7{kDSx)Gmxku06fdaO%uvp~m^ke+UA=`Fs1aBz!%f(SA3 zC%rmYiUHF$m&rS+vmZZN6R%Tkan;#c_)IQL6w1_#G`F_a`_wuv5E(4A`bxihB<}t56CPIO#%w&c>c-l}`r7f)Np5%TtAM-`O&9WR8zAb*DJWd_ z{Z;+_-+*XoP(On`W|;^ww!xP%J%*`if7$2euEFXD>B0Oxpk(@9kF7tf49uUTv&W3h zOxryVZ=C(AMl*^yQ+g9dOKq4BYNIq6DRB54_kexR3I#=Eey?@Lr+e>Ps0vuvx$M@s zd1^cF@SmFA3Hr6oq-9Y(XF=gX-eJ8Pyl zq>`f4Avb~o#rhC7g`o@ghc(+C5t-|cl4!j7o>>?|$XxYXn6n>svq~q0u((j&LuvlA zYoDZOXI~4NLG^e^!)w{(FQ$I^hUedu9@M#HXax#LakKW@sv!R0gp2F2DmMjG(a$`h z;TG(nFA$e8UhKf2Brhu9kqW@wD()})ic4E0)~aCl7xLE6oC{;Bp+(0N_jBbJW)%HA zmk1Gaw`e}Qb-lba$GbKElaJZ)9^E+MoA7(Bg_VeN=mKCh%P$XBp$tA&%!&3?5LC($ROz^i$?~>iS|?| z?6<7_Oi;4KjAdb&Z!Rc+Oo~4k;jF7JCjit*8o4E zl*nyAhx8Y*+ScW%ac{PzJLRTRu)+iz_rSR;QB?65n7!hiBgj|-ak^GDz>v6I-V zjfu)^kaqK3dwBEe@h$S+EYx^DGx`aPCk6+XU=o)-gS+n?MMQX&=83YKAY7cRgK#-t z4OzYVOe=OzA}!teegToTtiV@4KUq~)=CB?aNt3yBYS&2JrPCIF&*Qz}pKjb{DWJYF zk5Ws?p2hzA)w;aXnCVTbYk2hw)FSmG^NT_oZABWJD7QB`X4C$~zL3OnzO^N1>++NA zBNS31dFc5CF&X_qAs$7)8OxPyD-+MDfSRPrng%<;wt=c7K`H?aw@}B?;QJAAJdQLK zUiwdk{DmB9qcWk*K|P*>`KVf3H|e%d!9}MatNd5JV$tOr)wNA- z{3E}xHoL#_c&eP2IS5FQ0{*3$cik&DuY$4b2Q0@kvc`C|!13=2i#KP6cdq7ODsA3k zPM2h5Gg~*q0)M(pgt;9RdsY-*fh1b%lJ!B(#a^;7gOV|eOt!4zj^v7voiprF&aD2( zH3eHv{y`z1yc?tElpK+W((6XOB0EKO9fZ0%g>uLjf~7>{VM{2lCyNCW{)Izr7Mwyv zkL+JHYR!#D@!MEB{MWTAdb_Z>g0r$7u$2Ql1v54nbaWl5sfL|_|6rN9sxR$?b!g$g zo`bvu&)Y6mAo(}DUl*Z|+Z`NE3Az4y-6nC}-kxpTf~FNym6c_BUbgGn6j&MkC*5e? zVpYEDb|MDwZ?r5e<8N{m>FF3xXaEsuYNlR0nPb!My|VUjbG;f!b=0pk#TNhg?)_|i z`Ai750hmVJpYw4#&v@P0mxY#D*w(LKe-r_ngB+l(Rl^*WW?83{XZlgyy(ou|CCcxLP4Xs-v0w=Y?@3cQBb#? zjSUT)iCOHLs<5bJc<9^mA@yBC zV|_)ViKV%4+S&B2qLG8dB{@0TrL;y;Ya0fpXVG|BkqyR|L$qzi=Z$LN0k~g#af#gN z;Lka85Wcx%15dvS!xX#8G^GXej4J!w|14)ky_j`OIUVO%Ej8=q50Xb!Gukk`HsnLE zlvR9&%gn?C;)+ZVpVelc$H@=gx&0_}W45zn22~Z1LT+w8>_DlrsBsxFeK!lx51=`% z-oMrIx)c6;bJ+(-qcfY;r?Zy|gBhXRTLHM@vWMDI@S)lOBvbG?xAQ;kvZ52P8ce35y4qO^5>g=Q zmqF_>W6a%y9;0GY2?r?BH#VOlAh7~bV5@1Tze*xZh#lhQj&-1o`E}a(Fs^Uu865E9 z#XkmggBA@K{5m^xfm?nav>3JZ^)dOePcT5YX`Re1OjVwrAC5cS@Z)$fP~`EG9S{&T zJTfviGWG_IkPzBf1tA+utjxvtc$*v6$DY1Wp=PgTHJ*4=lVFDZ*w~LcQ+9CC<`Loh z+w&=}pPjhxUM@=|hN(ku7hEILvL8IQNv@HLv9h+c*_*4DK-_(7D@TpseK%YKk^(RH zP8nIuMQ+cb$vm*C>6Gg`SWPgovP#UCPbkq~l&A4sNNp@j9Ro5MXoOph?3fiWA=+r` zckdib+rP7AyqrrbYGSOauP5hnkau9y(4q;wJtrsGP)X$PA0NM}xW5BIl|vP1_Y&76 zSSvjmmbNx_R3a|2Eb%*Y9u@9^r-cF4uqZhV%aTLGMzibqc?WRQ3B5f7+KEy!r-XsR zHn=3ZoXiU09sY=UA@@+Y^bN$}bG4<_cb`~YkiK5veqMI6Qq|(aM@Ofjbv8ZM%%fkJ zwX8AtY`nGEvOmus%#Wf{xVSiXH+kIR?2-$cYqD{bcXTf>$S{m`CMgO3!m9T%ZYsEo8Sm-nqpK&(wK~c1pGV8r zOaIS2KT4eXVp@ z=xO2FRw;;ezlNug`AsSkn~e_m!7SrbZET;(xx)IF021#c>)lnXQ+aubGAZ>2 zIr{rs5^{2K&@9#Ctr{5U;cP6hv$6T_r6vL3`PNf_70}eup(73RAzqk#2aRHkh6RzEpA@OG86n#ou-qNy6_Z7rkIsrAGCn29EE| zKT6Hh(_`_b(8b9!7Z>4)1K&dY;No)v^vZ*vAFtZ+p_xft9UZL+u^|t4XL)($H)x=) zt=8=X!t37M)0Yd=Bb|&iG-@1vPENm$EW#gS@2Jp5XJwlt85B@B-UQk9+Fd%D$e4=# z(1=;NL#Q9?2PY*JR>PjKms0|f~EI+)`QT=qZe-)`&`H8z?vK zgsOC(3hr%}eMk!6sTpVQNWSe75d!>QslKnw?IUB(6; zfE^kdER)Xfg{nXw*8{GiCR1NOWKm{R-*`tO>bj4d`~H`>5B856ELdHvD(j2i{S_PE ze$+o>Zu{L4y$r-fog{+#%p;?k1_dQ~QvtH!sKYBCHaEAr!W3Sss=%+CGUG{vwfRRr zHZDZ3dhZw~3e#Q_?ocO*XicgG@hxnu5YlllW+m4Rv=pSFLU7};&T#>4$Q;~MSv%?A zhBXa54&&w+J?Mr-`8J0!81^=$)FeDEFAfSjO_%knmlthW-Sm@>&7e#| zOnyx-y5vWPvC!i6@6D6y6%L}=$I3IB{v0GWG+eMpnPiAwJ3=6nn?HCeR9$_z0+%|p zBZ8c33n1ies~(Gb#(w?U^MG@&LD=lI-DWtc_$}l_#ub>HfOhU5J zH=%1_5J3g;&~j9AsQHuoG`IS=pKSb5T6k?DAtAv+)W=SCcePD|iFwRxzY~f>NkDmv zacvALvHh6|C5@Q8!dwCS>DW3Pdyv7Xp+4LdMQ--)-F&G*0%2bQ3E3Y!apXWG8uNv& zvNL{KzlVN;bKl&ywX3a^>T4@;uzWw3wz+LPwE07O*)q4LmX@~m_B^1I2iY*+A3q^H z&dax2TPOZZA;7}4Wf7hvqM@c?+(&)BO+b|q$|@x2&cAa$#q~YnGmwOn^r&fnm6TAt ze={$~fQwdHh;Hi|XL{=m@Y|pn6Y-eG?^KdM2J}k+i!*LbE!4EN)`bIovfOy!?5q?5 z24O7=HLZHGzkDXltdCNHrHw%!VFy=TAE3k&2bkT-ULZP3NHqD{qId%xk$>f?`C}agPP)Pwl3JW7R%7hxV#gmtpB*Pw>Kjg4(BJPjJ*zJD;hf?>fkNv`MB+*V(%w@8gATBdB> zni|pENQo{`CfC$}DpR@1uCtoxQ292^Hm)yjIYZm}vELnex%3LN$b=FKraZ`H^4J$y zT;8ei{3DDJJev#4r;$MI&8Y%9Sv6#2Em`T{XLx-MBj@*oo`-7zH8`o%m>e}UqN_{5 zR}0`Bzy@}T*nSk)A!nW!2OHq){b^}mleO1h{|yR7MvkPIgbtjvwa@UQ;=rfgxWy@~ zV^!4q;$*({SvL;#o&~_0Pu0$NtcK+pQtc1t7K@1CoC5L-!gF)K;|?*?>e1I$`sy4x zh}Y2&@-d;=Dl+nq;YC%=0uJ+~?0nE=fQqrSsEj^F7JWZvZ?=^WtZCPQZ{#yjGNt8h zr-Am|9Z3qX4M~8PzI7sSnfLKy!R4`~owapKn3vzZ*|WQe#&8Y#D3caX#Or6Cz`CZm zLk=G@S!VI+pBx%H9;f~?v_>1KVs!9@;Gk@x6jjM@? zScwK`77}AAaGgvq4ruoF{GQ{>+1fVk`-_z*n5a29ZHyMi5bW1E$~nc4<6!r`HEl1r z{oXP?*!iV=a|pp&_pP}2DdC}S`_F}JlP*w`CyJPD$73Iz@(6BLP^o{;&4s*V4@P*l zdCLust)5u%6>2iE8*0r1brkHFq>JYQj&A4V|Ck((wp=YdHd(jA&5@_+_Ai_`d40 z>V>_Dnn`mXNy>M5x?PV3Wp0k-UwJzI7*;LR6wOe{{u9q`a5Li=Bk1NHeV?xFI3^!8 zQ~@l+D)qVbHf9X_^KNdtQ`tT`_Z{7uX}3V}M4=GiH{aL*jMv;!a|g??7kMM69pdSJ zTfkge)b(dfx9pZzRUfe|lwYTuMggtu8Rb&X3-Zyxr&UqTDWEFb5{fkQ7+O`TAl~+< z3;z6QZ!IAfOrOq~L&UcMAyy1raq>hS2Ag?1t!H1BdAXDj4awgC3wk*(!VU#_DJFjq z09gNSOd^_!yysBML%KxzaeSEKV>Idk^Sssnm?)~-V-uhs64huj-x0GL+3!sU?xS=} zl7x2mw4t3qCnsHzq|P98YHTbbiC$L?CL&vGla%;MUOuJaxFQp4^CU#H>T1R>lZb#o zTB>!n&P^jfGP2dX@t2idVRcNI`@g1J{uuRfD8FDGA0L;`Ej=5HaFvdVm4t-g*@}t{ zk(QeVjHMP6v?js9GTvUL`$L&?8)|K{4eo!Yd!evSCJY>$sX7ZYa9B{N^a&FgwYpc| zMPwT*vvKViwVc=WQ&I|n6b4q~i_Dl&K;04DTb%>}h5d?dt~FBPY9bQ8|MadUb550! z-(YSE^T^g!(7@wm}xy>!6-0$=OJ>nqlj zezh1WtvO9KwO<**C?zv|<(^)p3sqx}$%&RLXSqb^j;F_tWuhpWytW7K9^PTwQk)X8 z7;5Wjxoxkl?i%n>3LP$?vn(yCflW6)hXY>{*NIArYp>&k@oH`s2*|COL{4sZYNb8jO78S`@&3+-#)N%;o|4O3GUBUU8}^p(dH_2^$I_aG z{_kHEMTdOsBjV!(Dp|L9e?Bd1lqQPD+u;4h!J_AOvBm(5r>a+`T2RXR*s zsPL2|#yb>lHJUA^Ks^>~_OmtiV_T;>cL-76jkok%fY97-wh55c)3aK36^54cfkB}Y zrRVzf^V=Jh8b@l_NCoYduq`n)mJ3my{*RPHhG6h3@b!1mP`~RYBYuzJGNpWWif#0{ zW>&3inVo?0h>(~jTNukPT2gT@adq9=HDY(X0Q&XG%-eP-7}nlS`xs}Z4K^XlqY?1{ zNk5(1_2&Rzn%qI!}071G6B9arr}}4BQ_IFFmK_(Z=Q(FI+Eamt2OZDwKRw5P^9;8@{uwSBV1oxDRr3LRD$)Wmpayr- z@R%$!aq*g3jg5^>Pfwc`CJwIjyket7Y*f?*-*U=E`U;Cgdo(?-ia`|jq4gpdKmMHV6$zagM>53(FIqJn>k zcpPzoU!Hl$WrOkPgY*eV$U<2C&u{cmNkaY&x&SAk!v9R;fTyh3|HeH2J!-iBgF=F5 rL&L9Q|M4fl_QU@H8EBUL From 2ab4312e0a228b7a611fa266b5b86cb8e9626d78 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 15:09:13 +0100 Subject: [PATCH 24/46] USe own types --- .../cdp/legacy-plugins/customerio/index.ts | 22 ++++++------------- .../src/cdp/legacy-plugins/intercom/index.ts | 8 +++---- plugin-server/src/cdp/legacy-plugins/types.ts | 12 ++++++---- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts index ed32ef0ea730c..798ee94941c36 100644 --- a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts @@ -1,4 +1,4 @@ -import { PluginInput, ProcessedPluginEvent } from '@posthog/plugin-scaffold' +import { ProcessedPluginEvent } from '@posthog/plugin-scaffold' import { RetryError } from '@posthog/plugin-scaffold' import { Response } from '~/src/utils/fetch' @@ -8,7 +8,7 @@ import { LegacyPlugin, LegacyPluginMeta } from '../types' const DEFAULT_HOST = 'track.customer.io' const DEFAULT_SEND_EVENTS_FROM_ANONYMOUS_USERS = 'Send all events' -interface CustomerIoPluginInput extends PluginInput { +type CustomerIoMeta = LegacyPluginMeta & { config: { customerioSiteId: string customerioToken: string @@ -28,7 +28,6 @@ interface CustomerIoPluginInput extends PluginInput { } } -type CustomerIoMeta = LegacyPluginMeta enum EventsConfig { SEND_ALL = '1', SEND_EMAILS = '2', @@ -94,7 +93,7 @@ async function callCustomerIoApi( } export const setupPlugin = async (meta: CustomerIoMeta) => { - const { config, global, storage, logger } = meta + const { config, global, logger } = meta const customerioBase64AuthToken = Buffer.from(`${config.customerioSiteId}:${config.customerioToken}`).toString( 'base64' ) @@ -109,16 +108,8 @@ export const setupPlugin = async (meta: CustomerIoMeta) => { EVENTS_CONFIG_MAP[config.sendEventsFromAnonymousUsers || DEFAULT_SEND_EVENTS_FROM_ANONYMOUS_USERS] global.identifyByEmail = config.identifyByEmail === 'Yes' - const credentialsVerifiedPreviously = await storage.get(global.authorizationHeader, false) - - if (credentialsVerifiedPreviously) { - logger.log('Customer.io credentials verified previously. Completing setupPlugin.') - return - } - // See https://www.customer.io/docs/api/#operation/getCioAllowlist await callCustomerIoApi(meta, 'GET', 'api.customer.io', '/v1/api/info/ip_addresses', global.authorizationHeader) - await storage.set(global.authorizationHeader, true) logger.log('Successfully authenticated with Customer.io. Completing setupPlugin.') } @@ -154,9 +145,9 @@ export const onEvent = async (event: ProcessedPluginEvent, meta: CustomerIoMeta) } async function syncCustomerMetadata(meta: CustomerIoMeta, event: ProcessedPluginEvent): Promise { - const { storage, logger } = meta + const { logger } = meta const customerStatusKey = `customer-status/${event.distinct_id}` - const customerStatusArray = (await storage.get(customerStatusKey, [])) as string[] + const customerStatusArray = [] as string[] const customerStatus = new Set(customerStatusArray) as Customer['status'] const customerExistsAlready = customerStatus.has('seen') const email = getEmailFromEvent(event) @@ -173,7 +164,8 @@ async function syncCustomerMetadata(meta: CustomerIoMeta, event: ProcessedPlugin } if (customerStatus.size > customerStatusArray.length) { - await storage.set(customerStatusKey, Array.from(customerStatus)) + // TODO: Fix this + // await storage.set(customerStatusKey, Array.from(customerStatus)) } return { diff --git a/plugin-server/src/cdp/legacy-plugins/intercom/index.ts b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts index bd3568ce65e00..bc0fd544a5528 100644 --- a/plugin-server/src/cdp/legacy-plugins/intercom/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts @@ -1,10 +1,10 @@ -import { Plugin, ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' +import { ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' import { Response } from '~/src/utils/fetch' import { LegacyPlugin, LegacyPluginMeta } from '../types' -type IntercomPlugin = Plugin<{ +type IntercomMeta = LegacyPluginMeta & { global: { intercomUrl: string } @@ -14,9 +14,7 @@ type IntercomPlugin = Plugin<{ ignoredEmailDomains: string useEuropeanDataStorage: string } -}> - -type IntercomMeta = LegacyPluginMeta +} async function onEvent(event: ProcessedPluginEvent, meta: IntercomMeta): Promise { if (!isTriggeringEvent(meta.config.triggeringEvents, event.event)) { diff --git a/plugin-server/src/cdp/legacy-plugins/types.ts b/plugin-server/src/cdp/legacy-plugins/types.ts index 22acb222c50cc..02f7a54f5ba9e 100644 --- a/plugin-server/src/cdp/legacy-plugins/types.ts +++ b/plugin-server/src/cdp/legacy-plugins/types.ts @@ -1,4 +1,4 @@ -import { Meta, PluginInput, ProcessedPluginEvent } from '@posthog/plugin-scaffold' +import { ProcessedPluginEvent } from '@posthog/plugin-scaffold' import { Response, trackedFetch } from '~/src/utils/fetch' @@ -9,13 +9,17 @@ export type LegacyPluginLogger = { error: (...args: any[]) => void } -export type LegacyPluginMeta = Meta & { +export type LegacyPluginMeta = { + // storage: StorageExtension + config: Record + global: Record + logger: LegacyPluginLogger fetch: (...args: Parameters) => Promise } export type LegacyPlugin = { id: string - onEvent(event: ProcessedPluginEvent, meta: LegacyPluginMeta): Promise - setupPlugin?: (meta: LegacyPluginMeta) => Promise + onEvent(event: ProcessedPluginEvent, meta: LegacyPluginMeta): Promise + setupPlugin?: (meta: LegacyPluginMeta) => Promise } From 3231131d973450db88727636db9a625eaafe99cb Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 17:27:33 +0100 Subject: [PATCH 25/46] Fixes --- .../cdp/legacy-plugins/customerio/index.ts | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts index 798ee94941c36..1a596c11452e5 100644 --- a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts @@ -42,7 +42,6 @@ const EVENTS_CONFIG_MAP = { interface Customer { status: Set<'seen' | 'identified' | 'with_email'> - existsAlready: boolean email: string | null } @@ -127,7 +126,7 @@ export const onEvent = async (event: ProcessedPluginEvent, meta: CustomerIoMeta) return } - const customer: Customer = await syncCustomerMetadata(meta, event) + const customer: Customer = syncCustomerMetadata(meta, event) logger.debug(customer) logger.debug(shouldCustomerBeTracked(customer, global.eventsConfig)) if (!shouldCustomerBeTracked(customer, global.eventsConfig)) { @@ -144,14 +143,10 @@ export const onEvent = async (event: ProcessedPluginEvent, meta: CustomerIoMeta) ) } -async function syncCustomerMetadata(meta: CustomerIoMeta, event: ProcessedPluginEvent): Promise { +function syncCustomerMetadata(meta: CustomerIoMeta, event: ProcessedPluginEvent): Customer { const { logger } = meta - const customerStatusKey = `customer-status/${event.distinct_id}` - const customerStatusArray = [] as string[] - const customerStatus = new Set(customerStatusArray) as Customer['status'] - const customerExistsAlready = customerStatus.has('seen') const email = getEmailFromEvent(event) - + const customerStatus = new Set() as Customer['status'] logger.debug(email) // Update customer status @@ -163,14 +158,8 @@ async function syncCustomerMetadata(meta: CustomerIoMeta, event: ProcessedPlugin customerStatus.add('with_email') } - if (customerStatus.size > customerStatusArray.length) { - // TODO: Fix this - // await storage.set(customerStatusKey, Array.from(customerStatus)) - } - return { status: customerStatus, - existsAlready: customerExistsAlready, email, } } @@ -204,7 +193,6 @@ async function exportSingleEvent( const customerPayload: Record = { ...(event.$set || {}), - _update: customer.existsAlready, identifier: event.distinct_id, } @@ -248,6 +236,9 @@ function isEmail(email: string): boolean { } function getEmailFromEvent(event: ProcessedPluginEvent): string | null { + if (event.person?.properties?.email) { + return event.person.properties.email + } const setAttribute = event.$set if (typeof setAttribute !== 'object' || !setAttribute['email']) { return null From 343551ce2d38399d85835bbdae19236d6d3a1fe8 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 17:29:30 +0100 Subject: [PATCH 26/46] fix --- plugin-server/src/cdp/legacy-plugins/customerio/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts index 1a596c11452e5..4650a58471ec0 100644 --- a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts @@ -256,6 +256,6 @@ function getEmailFromEvent(event: ProcessedPluginEvent): string | null { export const customerioPlugin: LegacyPlugin = { id: 'customer-io', - setupPlugin, + setupPlugin: setupPlugin as any, onEvent, } From c574e3522385c5c948b690ddf2b66d6bbdf04d23 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 17:32:17 +0100 Subject: [PATCH 27/46] Fixes --- .../cdp-cyclotron-plugins-worker.consumer.ts | 29 +++---------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 580212585f761..ddbbd4c0462e4 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -1,4 +1,4 @@ -import { Meta, ProcessedPluginEvent, RetryError, StorageExtension } from '@posthog/plugin-scaffold' +import { ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' import { Response, trackedFetch } from '~/src/utils/fetch' @@ -12,22 +12,7 @@ import { CdpCyclotronWorker } from './cdp-cyclotron-worker.consumer' type PluginState = { setupPromise: Promise errored: boolean - meta: Meta -} - -const createStorage = (): StorageExtension => { - const storage: Record = {} - return { - get: (key: string) => Promise.resolve(storage[key]), - set: (key: string, value: any) => { - storage[key] = value - return Promise.resolve() - }, - del: (key: string) => { - delete storage[key] - return Promise.resolve() - }, - } + meta: LegacyPluginMeta } /** @@ -101,16 +86,9 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { let state = this.pluginState[pluginId] if (!state) { - const meta: LegacyPluginMeta = { + const meta: LegacyPluginMeta = { config: invocation.globals.inputs, - attachments: {}, global: {}, - jobs: {}, - metrics: {}, - cache: {} as any, - storage: createStorage(), - geoip: {} as any, - utils: {} as any, fetch: (...args) => this.fetch(...args), logger: logger, } @@ -164,6 +142,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { }) await plugin.onEvent?.(event, { ...state.meta, + // NOTE: We override logger and fetch here so we can track the calls logger, fetch: this.fetch, }) From e8665e55706a5bcec879db525b055b789b0246cd Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 18:20:25 +0100 Subject: [PATCH 28/46] Added migration commands --- posthog/cdp/migrations.py | 96 +++++++++++++++++++ .../migrate_plugins_to_hog_functions.py | 23 +++++ posthog/models/plugin.py | 10 ++ 3 files changed, 129 insertions(+) create mode 100644 posthog/cdp/migrations.py create mode 100644 posthog/management/commands/migrate_plugins_to_hog_functions.py diff --git a/posthog/cdp/migrations.py b/posthog/cdp/migrations.py new file mode 100644 index 0000000000000..f79effda7b42c --- /dev/null +++ b/posthog/cdp/migrations.py @@ -0,0 +1,96 @@ +# Migrate from legacy plugins to new hog function plugins + + +import json +from posthog.api.hog_function import HogFunctionSerializer +from posthog.models.hog_functions.hog_function import HogFunction +from posthog.models.plugin import PluginAttachment, PluginConfig + + +def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=False): + # Get all legacy plugin_configs that are active with their attachments and global values + legacy_plugins = PluginConfig.objects.select_related("plugin").filter(enabled=True) + + if team_ids: + legacy_plugins = legacy_plugins.filter(team_id__in=team_ids) + + hog_functions = [] + + for plugin_config in legacy_plugins: + print(plugin_config.plugin.name) + print(plugin_config.config) + print(plugin_config.plugin.config_schema) + + plugin_id = plugin_config.plugin.url.replace("inline://", "").replace("https://github.com/PostHog/", "") + + inputs = {} + inputs_schema = [] + + # Iterate over the plugin config to build the inputs + + for schema in plugin_config.plugin.config_schema: + if not schema.get("key"): + continue + + print("Converting schema", schema) + + # Some hacky stuff to convert the schemas correctly + input_schema = { + "key": schema["key"], + "type": schema["type"], + "label": schema.get("name", schema["key"]), + "description": schema.get("hint", ""), + "secret": schema.get("secret", False), + "required": schema.get("required", False), + "default": schema.get("default", None), + } + + if schema["type"] == "choice": + input_schema["choices"] = [ + { + "label": choice, + "value": choice, + } + for choice in schema["choices"] + ] + input_schema["type"] = "string" + elif schema["type"] == "attachment": + input_schema["type"] = "string" + + inputs_schema.append(input_schema) + + for key, value in plugin_config.config.items(): + inputs[key] = {"value": value} + + # Load all attachments for this plugin config + attachments = PluginAttachment.objects.filter(plugin_config=plugin_config) + + for attachment in attachments: + inputs[attachment.key] = {"value": attachment.parse_contents()} + + serializer_context = {"team": plugin_config.team, "get_team": lambda: plugin_config.team} + + data = { + "template_id": f"plugin-{plugin_id}", + "type": "destination", + "name": plugin_config.plugin.name, + "description": "This is a legacy destination migrated from our old plugin system.", + "filters": {}, + "inputs": inputs, + "inputs_schema": inputs_schema, + "enabled": True, + "icon_url": plugin_config.plugin.icon, + } + + print("Attempting to create hog function", data) + print(json.dumps(data, indent=2)) + + serializer = HogFunctionSerializer( + data=data, + context=serializer_context, + ) + serializer.is_valid(raise_exception=True) + hog_functions.append(HogFunction(**serializer.validated_data)) + + print(hog_functions) + return hog_functions diff --git a/posthog/management/commands/migrate_plugins_to_hog_functions.py b/posthog/management/commands/migrate_plugins_to_hog_functions.py new file mode 100644 index 0000000000000..8aa05aee700ac --- /dev/null +++ b/posthog/management/commands/migrate_plugins_to_hog_functions.py @@ -0,0 +1,23 @@ +from django.core.management.base import BaseCommand + +from posthog.cdp.migrations import migrate_legacy_plugins + + +class Command(BaseCommand): + help = "Migrate plugins to HogFunctions" + + def add_arguments(self, parser): + parser.add_argument( + "--dry-run", + type=bool, + help="If set, will not actually perform the migration, but will print out what would have been done", + ) + parser.add_argument("--team-ids", type=str, help="Comma separated list of team ids to sync") + parser.add_argument("--test-mode", type=str, help="Whether to just copy as a test function rather than migrate") + + def handle(self, *args, **options): + dry_run = options["dry_run"] + team_ids = options["team_ids"] + test_mode = options["test_mode"] + + migrate_legacy_plugins(dry_run=dry_run, team_ids=team_ids, test_mode=test_mode) diff --git a/posthog/models/plugin.py b/posthog/models/plugin.py index d2e204bdf3211..a11295e217bc7 100644 --- a/posthog/models/plugin.py +++ b/posthog/models/plugin.py @@ -1,4 +1,5 @@ import datetime +import json import os import subprocess from dataclasses import dataclass @@ -274,6 +275,15 @@ class PluginAttachment(models.Model): file_size = models.IntegerField() contents = models.BinaryField() + def parse_contents(self) -> str | None: + if self.content_type == "application/json": + return json.loads(self.contents) + + if self.content_type == "text/plain": + return self.contents.decode("utf-8") + + return None + class PluginStorage(models.Model): plugin_config = models.ForeignKey("PluginConfig", on_delete=models.CASCADE) From 04ba772fc45c6c9308d7350b36dc747c3b4be1ea Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 18:23:26 +0100 Subject: [PATCH 29/46] Fixes --- posthog/cdp/migrations.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/posthog/cdp/migrations.py b/posthog/cdp/migrations.py index f79effda7b42c..378e4acb0b8ca 100644 --- a/posthog/cdp/migrations.py +++ b/posthog/cdp/migrations.py @@ -7,7 +7,7 @@ from posthog.models.plugin import PluginAttachment, PluginConfig -def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=False): +def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=True): # Get all legacy plugin_configs that are active with their attachments and global values legacy_plugins = PluginConfig.objects.select_related("plugin").filter(enabled=True) @@ -17,11 +17,15 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=False): hog_functions = [] for plugin_config in legacy_plugins: - print(plugin_config.plugin.name) - print(plugin_config.config) - print(plugin_config.plugin.config_schema) + print(plugin_config.plugin.name) # noqa: T201 + print(plugin_config.config) # noqa: T201 + print(plugin_config.plugin.config_schema) # noqa: T201 plugin_id = plugin_config.plugin.url.replace("inline://", "").replace("https://github.com/PostHog/", "") + plugin_name = plugin_config.plugin.name + + if test_mode: + plugin_name = f"[CDP-TEST-HIDDEN] {plugin_name}" inputs = {} inputs_schema = [] @@ -32,7 +36,7 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=False): if not schema.get("key"): continue - print("Converting schema", schema) + print("Converting schema", schema) # noqa: T201 # Some hacky stuff to convert the schemas correctly input_schema = { @@ -73,7 +77,7 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=False): data = { "template_id": f"plugin-{plugin_id}", "type": "destination", - "name": plugin_config.plugin.name, + "name": plugin_name, "description": "This is a legacy destination migrated from our old plugin system.", "filters": {}, "inputs": inputs, @@ -82,8 +86,8 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=False): "icon_url": plugin_config.plugin.icon, } - print("Attempting to create hog function", data) - print(json.dumps(data, indent=2)) + print("Attempting to create hog function", data) # noqa: T201 + print(json.dumps(data, indent=2)) # noqa: T201 serializer = HogFunctionSerializer( data=data, @@ -92,5 +96,18 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=False): serializer.is_valid(raise_exception=True) hog_functions.append(HogFunction(**serializer.validated_data)) - print(hog_functions) + print(hog_functions) # noqa: T201 + + if dry_run: + print("Dry run, not creating hog functions") # noqa: T201 + return hog_functions + + print("Creating hog functions") # noqa: T201 + HogFunction.objects.bulk_create(hog_functions) + + # Disable the old plugins + PluginConfig.objects.filter(id__in=[plugin_config.id for plugin_config in legacy_plugins]).update(enabled=False) + + print("Done") # noqa: T201 + return hog_functions From 99987b2b3fd645a76a5ace480a9fba5dd4891ee7 Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 18:27:03 +0100 Subject: [PATCH 30/46] Fix --- .../templates/_internal/template_legacy_plugin.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/posthog/cdp/templates/_internal/template_legacy_plugin.py b/posthog/cdp/templates/_internal/template_legacy_plugin.py index cef66400e47a7..184251cc6b2c6 100644 --- a/posthog/cdp/templates/_internal/template_legacy_plugin.py +++ b/posthog/cdp/templates/_internal/template_legacy_plugin.py @@ -1,19 +1,5 @@ from posthog.cdp.templates.hog_function_template import HogFunctionTemplate -legacy_plugin_template: HogFunctionTemplate = HogFunctionTemplate( - status="alpha", - type="destination", - id="template-legacy-plugin", - name="Legacy plugin", - description="Legacy plugins", - icon_url="/static/hedgehog/builder-hog-01.png", - category=["Custom", "Analytics"], - hog=""" -print('not used') -""".strip(), - inputs_schema=[], -) - def create_legacy_plugin_template(template_id: str) -> HogFunctionTemplate: return HogFunctionTemplate( From 2ffb989f606d2e460376fa4004b81ae37fdd815f Mon Sep 17 00:00:00 2001 From: Ben White Date: Mon, 27 Jan 2025 18:28:49 +0100 Subject: [PATCH 31/46] Fix --- plugin-server/tests/cdp/cdp-e2e.test.ts | 113 ------------------------ 1 file changed, 113 deletions(-) diff --git a/plugin-server/tests/cdp/cdp-e2e.test.ts b/plugin-server/tests/cdp/cdp-e2e.test.ts index 50db3eb85f189..425eeeb37f6b7 100644 --- a/plugin-server/tests/cdp/cdp-e2e.test.ts +++ b/plugin-server/tests/cdp/cdp-e2e.test.ts @@ -3,7 +3,6 @@ import { getProducedKafkaMessages, getProducedKafkaMessagesForTopic } from '../h import { CdpCyclotronWorker, CdpCyclotronWorkerFetch } from '../../src/cdp/consumers/cdp-cyclotron-worker.consumer' import { CdpProcessedEventsConsumer } from '../../src/cdp/consumers/cdp-processed-events.consumer' -import { CdpCyclotronWorkerPlugins } from '../../src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer' import { HogFunctionInvocationGlobals, HogFunctionType } from '../../src/cdp/types' import { KAFKA_APP_METRICS_2, KAFKA_LOG_ENTRIES } from '../../src/config/kafka-topics' import { Hub, Team } from '../../src/types' @@ -35,7 +34,6 @@ describe('CDP Consumer loop', () => { let processedEventsConsumer: CdpProcessedEventsConsumer let cyclotronWorker: CdpCyclotronWorker | undefined let cyclotronFetchWorker: CdpCyclotronWorkerFetch | undefined - let cdpCyclotronWorkerPlugins: CdpCyclotronWorkerPlugins | undefined let hub: Hub let team: Team @@ -65,8 +63,6 @@ describe('CDP Consumer loop', () => { cyclotronWorker = new CdpCyclotronWorker(hub) await cyclotronWorker.start() - cdpCyclotronWorkerPlugins = new CdpCyclotronWorkerPlugins(hub) - await cdpCyclotronWorkerPlugins.start() cyclotronFetchWorker = new CdpCyclotronWorkerFetch(hub) await cyclotronFetchWorker.start() @@ -93,7 +89,6 @@ describe('CDP Consumer loop', () => { processedEventsConsumer?.stop().then(() => console.log('Stopped processedEventsConsumer')), cyclotronWorker?.stop().then(() => console.log('Stopped cyclotronWorker')), cyclotronFetchWorker?.stop().then(() => console.log('Stopped cyclotronFetchWorker')), - cdpCyclotronWorkerPlugins?.stop().then(() => console.log('Stopped cdpCyclotronWorkerPlugins')), ] await Promise.all(stoppers) @@ -216,113 +211,5 @@ describe('CDP Consumer loop', () => { }, ]) }) - - it('should invoke a legacy plugin in the worker loop until completed', async () => { - const invocations = await processedEventsConsumer.processBatch([globals]) - expect(invocations).toHaveLength(1) - - await waitForExpect(() => { - expect(getProducedKafkaMessages()).toHaveLength(7) - }, 5000) - - expect(mockFetch).toHaveBeenCalledTimes(1) - - expect(mockFetch.mock.calls[0]).toMatchInlineSnapshot(` - [ - "https://example.com/posthog-webhook", - { - "body": "{"event":{"uuid":"b3a1fe86-b10c-43cc-acaf-d208977608d0","event":"$pageview","elements_chain":"","distinct_id":"distinct_id","url":"http://localhost:8000/events/1","properties":{"$current_url":"https://posthog.com","$lib_version":"1.0.0"},"timestamp":"2024-09-03T09:00:00Z"},"groups":{},"nested":{"foo":"http://localhost:8000/events/1"},"person":{"id":"uuid","name":"test","url":"http://localhost:8000/persons/1","properties":{"email":"test@posthog.com","first_name":"Pumpkin"}},"event_url":"http://localhost:8000/events/1-test"}", - "headers": { - "version": "v=1.0.0", - }, - "method": "POST", - "timeout": 10000, - }, - ] - `) - - const logMessages = getProducedKafkaMessagesForTopic(KAFKA_LOG_ENTRIES) - const metricsMessages = getProducedKafkaMessagesForTopic(KAFKA_APP_METRICS_2) - - expect(metricsMessages).toMatchObject([ - { - topic: 'clickhouse_app_metrics2_test', - value: { - app_source: 'hog_function', - app_source_id: fnFetchNoFilters.id.toString(), - count: 1, - metric_kind: 'other', - metric_name: 'fetch', - team_id: 2, - }, - }, - { - topic: 'clickhouse_app_metrics2_test', - value: { - app_source: 'hog_function', - app_source_id: fnFetchNoFilters.id.toString(), - count: 1, - metric_kind: 'success', - metric_name: 'succeeded', - team_id: 2, - }, - }, - ]) - - expect(logMessages).toMatchObject([ - { - topic: 'log_entries_test', - value: { - level: 'debug', - log_source: 'hog_function', - log_source_id: fnFetchNoFilters.id.toString(), - message: 'Executing function', - team_id: 2, - }, - }, - { - topic: 'log_entries_test', - value: { - level: 'debug', - log_source: 'hog_function', - log_source_id: fnFetchNoFilters.id.toString(), - message: expect.stringContaining( - "Suspending function due to async function call 'fetch'. Payload:" - ), - team_id: 2, - }, - }, - { - topic: 'log_entries_test', - value: { - level: 'debug', - log_source: 'hog_function', - log_source_id: fnFetchNoFilters.id.toString(), - message: 'Resuming function', - team_id: 2, - }, - }, - { - topic: 'log_entries_test', - value: { - level: 'info', - log_source: 'hog_function', - log_source_id: fnFetchNoFilters.id.toString(), - message: `Fetch response:, {"status":200,"body":{"success":true}}`, - team_id: 2, - }, - }, - { - topic: 'log_entries_test', - value: { - level: 'debug', - log_source: 'hog_function', - log_source_id: fnFetchNoFilters.id.toString(), - message: expect.stringContaining('Function completed in'), - team_id: 2, - }, - }, - ]) - }) }) }) From 406d7de5bd019ecec4f90c4d4f0211c7f7ec6550 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 09:10:53 +0100 Subject: [PATCH 32/46] Fix migration --- posthog/cdp/migrations.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/posthog/cdp/migrations.py b/posthog/cdp/migrations.py index 378e4acb0b8ca..8b260cbea49cf 100644 --- a/posthog/cdp/migrations.py +++ b/posthog/cdp/migrations.py @@ -72,7 +72,7 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=True): for attachment in attachments: inputs[attachment.key] = {"value": attachment.parse_contents()} - serializer_context = {"team": plugin_config.team, "get_team": lambda: plugin_config.team} + serializer_context = {"team": plugin_config.team, "get_team": (lambda config=plugin_config: config.team)} data = { "template_id": f"plugin-{plugin_id}", @@ -105,8 +105,10 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=True): print("Creating hog functions") # noqa: T201 HogFunction.objects.bulk_create(hog_functions) - # Disable the old plugins - PluginConfig.objects.filter(id__in=[plugin_config.id for plugin_config in legacy_plugins]).update(enabled=False) + if not test_mode: + print("Disabling old plugins") # noqa: T201 + # Disable the old plugins + PluginConfig.objects.filter(id__in=[plugin_config.id for plugin_config in legacy_plugins]).update(enabled=False) print("Done") # noqa: T201 From 0460d3a08f1b02510327c7a23ebb5a0617ba7ac6 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 09:15:17 +0100 Subject: [PATCH 33/46] Fixes --- posthog/cdp/migrations.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/posthog/cdp/migrations.py b/posthog/cdp/migrations.py index 8b260cbea49cf..86aa29e7108a7 100644 --- a/posthog/cdp/migrations.py +++ b/posthog/cdp/migrations.py @@ -17,9 +17,13 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=True): hog_functions = [] for plugin_config in legacy_plugins: - print(plugin_config.plugin.name) # noqa: T201 - print(plugin_config.config) # noqa: T201 - print(plugin_config.plugin.config_schema) # noqa: T201 + methods = plugin_config.plugin.capabilities.get("methods", []) + + if "onEvent" not in methods or "composeWebhook" not in methods: + print("Skipping plugin", plugin_config.plugin.name, "as it doesn't have onEvent or composeWebhook") # noqa: T201 + continue + + print("Attempting to migrate plugin", plugin_config) # noqa: T201 plugin_id = plugin_config.plugin.url.replace("inline://", "").replace("https://github.com/PostHog/", "") plugin_name = plugin_config.plugin.name @@ -86,8 +90,7 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=True): "icon_url": plugin_config.plugin.icon, } - print("Attempting to create hog function", data) # noqa: T201 - print(json.dumps(data, indent=2)) # noqa: T201 + print("Attempting to create hog function...") # noqa: T201 serializer = HogFunctionSerializer( data=data, @@ -98,6 +101,10 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=True): print(hog_functions) # noqa: T201 + if not hog_functions: + print("No hog functions to create") # noqa: T201 + return [] + if dry_run: print("Dry run, not creating hog functions") # noqa: T201 return hog_functions From e2450472199a8b656b5b64f1218490a5cf41ff47 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 09:17:18 +0100 Subject: [PATCH 34/46] Fixes --- .../cdp-cyclotron-plugins-worker.consumer.ts | 1 + .../cdp-cyclotron-plugins-worker.test.ts | 11 ---------- .../hog-function-manager.service.test.ts | 20 ++----------------- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index ddbbd4c0462e4..66094bcbc70dc 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -86,6 +86,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { let state = this.pluginState[pluginId] if (!state) { + // TODO: Modify fetch to be a silent log if it is a test function... const meta: LegacyPluginMeta = { config: invocation.globals.inputs, global: {}, diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index 52247ddf7216c..c5b1faf1558d5 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -110,8 +110,6 @@ describe('CdpCyclotronWorkerPlugins', () => { expect(PLUGINS_BY_ID['intercom'].setupPlugin).toHaveBeenCalledTimes(1) expect(jest.mocked(PLUGINS_BY_ID['intercom'].setupPlugin!).mock.calls[0][0]).toMatchInlineSnapshot(` { - "attachments": {}, - "cache": {}, "config": { "ignoredEmailDomains": "dev.posthog.com", "intercomApiKey": "1234567890", @@ -119,22 +117,13 @@ describe('CdpCyclotronWorkerPlugins', () => { "useEuropeanDataStorage": "No", }, "fetch": [Function], - "geoip": {}, "global": {}, - "jobs": {}, "logger": { "debug": [Function], "error": [Function], "log": [Function], "warn": [Function], }, - "metrics": {}, - "storage": { - "del": [Function], - "get": [Function], - "set": [Function], - }, - "utils": {}, } `) }) diff --git a/plugin-server/src/cdp/services/hog-function-manager.service.test.ts b/plugin-server/src/cdp/services/hog-function-manager.service.test.ts index c4530200b8b5c..41c15d8f1c85a 100644 --- a/plugin-server/src/cdp/services/hog-function-manager.service.test.ts +++ b/plugin-server/src/cdp/services/hog-function-manager.service.test.ts @@ -3,6 +3,7 @@ import { Hub } from '~/src/types' import { closeHub, createHub } from '~/src/utils/db/hub' import { PostgresUse } from '~/src/utils/db/postgres' import { insertHogFunction, insertIntegration } from '~/tests/cdp/fixtures' +import { forSnapshot } from '~/tests/helpers/snapshots' import { createTeam, resetTestDatabase } from '~/tests/helpers/sql' import { HogFunctionManagerService } from './hog-function-manager.service' @@ -70,24 +71,6 @@ describe('HogFunctionManager', () => { }) ) - // hogFunctions.push( - // await insertHogFunction(hub.postgres, teamId1, { - // name: 'Email Provider team 1', - // type: 'email', - // inputs_schema: [ - // { - // type: 'email', - // key: 'message', - // }, - // ], - // inputs: { - // email: { - // value: { from: 'me@a.com', to: 'you@b.com', subject: 'subject', html: 'text' }, - // }, - // }, - // }) - // ) - hogFunctions.push( await insertHogFunction(hub.postgres, teamId2, { name: 'Test Hog Function team 2', @@ -149,6 +132,7 @@ describe('HogFunctionManager', () => { encrypted_inputs: null, masking: null, mappings: null, + template_id: null, depends_on_integration_ids: new Set([integrations[0].id]), }, ]) From 4e7ffe0450f4888b8280cb3aefac679ec4a8ceb0 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 09:19:57 +0100 Subject: [PATCH 35/46] Fix --- plugin-server/src/cdp/legacy-plugins/types.ts | 1 - posthog/cdp/migrations.py | 4 ---- 2 files changed, 5 deletions(-) diff --git a/plugin-server/src/cdp/legacy-plugins/types.ts b/plugin-server/src/cdp/legacy-plugins/types.ts index 02f7a54f5ba9e..b65484dfe43a8 100644 --- a/plugin-server/src/cdp/legacy-plugins/types.ts +++ b/plugin-server/src/cdp/legacy-plugins/types.ts @@ -10,7 +10,6 @@ export type LegacyPluginLogger = { } export type LegacyPluginMeta = { - // storage: StorageExtension config: Record global: Record diff --git a/posthog/cdp/migrations.py b/posthog/cdp/migrations.py index 86aa29e7108a7..eee11f0e08011 100644 --- a/posthog/cdp/migrations.py +++ b/posthog/cdp/migrations.py @@ -1,7 +1,3 @@ -# Migrate from legacy plugins to new hog function plugins - - -import json from posthog.api.hog_function import HogFunctionSerializer from posthog.models.hog_functions.hog_function import HogFunction from posthog.models.plugin import PluginAttachment, PluginConfig From 3af5796fc46cd23fe911a25f60f21e76e25a09fd Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 09:22:15 +0100 Subject: [PATCH 36/46] Fixes --- .../commands/migrate_plugins_to_hog_functions.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/posthog/management/commands/migrate_plugins_to_hog_functions.py b/posthog/management/commands/migrate_plugins_to_hog_functions.py index 8aa05aee700ac..ccc58b88604ab 100644 --- a/posthog/management/commands/migrate_plugins_to_hog_functions.py +++ b/posthog/management/commands/migrate_plugins_to_hog_functions.py @@ -9,15 +9,19 @@ class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument( "--dry-run", - type=bool, + action="store_true", help="If set, will not actually perform the migration, but will print out what would have been done", ) parser.add_argument("--team-ids", type=str, help="Comma separated list of team ids to sync") - parser.add_argument("--test-mode", type=str, help="Whether to just copy as a test function rather than migrate") + parser.add_argument( + "--test-mode", action="store_true", help="Whether to just copy as a test function rather than migrate" + ) def handle(self, *args, **options): dry_run = options["dry_run"] team_ids = options["team_ids"] test_mode = options["test_mode"] + print("Migrating plugins to hog functions", options) # noqa: T201 + migrate_legacy_plugins(dry_run=dry_run, team_ids=team_ids, test_mode=test_mode) From 91b8ea5877e6b100224cfcf1b7019866b5efd639 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 09:36:24 +0100 Subject: [PATCH 37/46] Fixes --- .../cdp-cyclotron-plugins-worker.consumer.ts | 20 +++++++++++-- .../cdp-cyclotron-plugins-worker.test.ts | 29 ++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 66094bcbc70dc..37d0492022330 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -51,6 +51,8 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { ? invocation.hogFunction.template_id.replace('plugin-', '') : null + const isTestFunction = invocation.hogFunction.name.includes('[CDP-TEST-HIDDEN]') + result.logs.push({ level: 'debug', timestamp: DateTime.now(), @@ -85,12 +87,26 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { let state = this.pluginState[pluginId] + const fetch = (...args: Parameters): Promise => { + if (isTestFunction) { + addLog('info', 'Fetch called but mocked due to test function') + return Promise.resolve({ + status: 500, + json: () => + Promise.resolve({ + message: 'Test function', + }), + } as Response) + } + return this.fetch(...args) + } + if (!state) { // TODO: Modify fetch to be a silent log if it is a test function... const meta: LegacyPluginMeta = { config: invocation.globals.inputs, global: {}, - fetch: (...args) => this.fetch(...args), + fetch, logger: logger, } @@ -145,7 +161,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { ...state.meta, // NOTE: We override logger and fetch here so we can track the calls logger, - fetch: this.fetch, + fetch, }) result.logs.push({ level: 'debug', diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index c5b1faf1558d5..3acd044f8ace8 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -5,7 +5,7 @@ import { createInvocation, insertHogFunction as _insertHogFunction, } from '~/tests/cdp/fixtures' -import { getProducedKafkaMessages } from '~/tests/helpers/mocks/producer.mock' +import { getProducedKafkaMessages, getProducedKafkaMessagesForTopic } from '~/tests/helpers/mocks/producer.mock' import { forSnapshot } from '~/tests/helpers/snapshots' import { getFirstTeam, resetTestDatabase } from '~/tests/helpers/sql' @@ -210,6 +210,33 @@ describe('CdpCyclotronWorkerPlugins', () => { `) }) + it('should mock out fetch if it is a test function', async () => { + jest.spyOn(PLUGINS_BY_ID['intercom'] as any, 'onEvent') + + const invocation = createInvocation(fn, globals) + invocation.hogFunction.name = 'My function [CDP-TEST-HIDDEN]' + invocation.globals.event.event = 'mycustomevent' + invocation.globals.event.properties = { + email: 'test@posthog.com', + } + + await processor.processInvocations([invocation]) + + expect(mockFetch).toHaveBeenCalledTimes(0) + + expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) + + expect(forSnapshot(getProducedKafkaMessagesForTopic('log_entries_test').map((m) => m.value.message))) + .toMatchInlineSnapshot(` + [ + "Executing plugin intercom", + "Fetch called but mocked due to test function", + "Unable to search contact test@posthog.com in Intercom. Status Code: undefined. Error message: ", + "Execution successful", + ] + `) + }) + it('should handle and collect errors', async () => { jest.spyOn(PLUGINS_BY_ID['intercom'] as any, 'onEvent') From be04729619e663f909cef8fa6f3114ceb6305212 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 09:44:30 +0100 Subject: [PATCH 38/46] fix --- .../src/cdp/services/hog-function-manager.service.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-server/src/cdp/services/hog-function-manager.service.test.ts b/plugin-server/src/cdp/services/hog-function-manager.service.test.ts index 41c15d8f1c85a..b31892365e316 100644 --- a/plugin-server/src/cdp/services/hog-function-manager.service.test.ts +++ b/plugin-server/src/cdp/services/hog-function-manager.service.test.ts @@ -3,7 +3,6 @@ import { Hub } from '~/src/types' import { closeHub, createHub } from '~/src/utils/db/hub' import { PostgresUse } from '~/src/utils/db/postgres' import { insertHogFunction, insertIntegration } from '~/tests/cdp/fixtures' -import { forSnapshot } from '~/tests/helpers/snapshots' import { createTeam, resetTestDatabase } from '~/tests/helpers/sql' import { HogFunctionManagerService } from './hog-function-manager.service' From a2d445045ec85313ac824118afba3704d5a011c7 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 10:04:17 +0100 Subject: [PATCH 39/46] Fixes --- .../cdp-cyclotron-plugins-worker.test.ts.snap | 46 ++++++++++++++++ .../cdp-cyclotron-plugins-worker.consumer.ts | 3 +- .../cdp-cyclotron-plugins-worker.test.ts | 55 ++++++++++++++++++- .../cdp/legacy-plugins/customerio/index.ts | 5 +- .../src/cdp/legacy-plugins/intercom/index.ts | 1 + plugin-server/src/cdp/legacy-plugins/types.ts | 6 +- .../src/cdp/services/hog-executor.service.ts | 2 +- 7 files changed, 112 insertions(+), 6 deletions(-) diff --git a/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap index e8924a331c548..4a2036225a8b3 100644 --- a/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap +++ b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap @@ -43,3 +43,49 @@ exports[`CdpCyclotronWorkerPlugins onEvent should handle and collect errors 3`] }, ] `; + +exports[`CdpCyclotronWorkerPlugins smoke tests should run the plugin: { name: 'customer-io', plugin: [Object] } 1`] = ` +[ + { + "level": "debug", + "message": "Executing plugin customer-io", + }, + { + "level": "info", + "message": "Successfully authenticated with Customer.io. Completing setupPlugin.", + }, + { + "level": "debug", + "message": "test@posthog.com", + }, + { + "level": "debug", + "message": "{"status":{},"email":"test@posthog.com"}", + }, + { + "level": "debug", + "message": "true", + }, + { + "level": "debug", + "message": "Execution successful", + }, +] +`; + +exports[`CdpCyclotronWorkerPlugins smoke tests should run the plugin: { name: 'intercom', plugin: [Object] } 1`] = ` +[ + { + "level": "debug", + "message": "Executing plugin intercom", + }, + { + "level": "info", + "message": "Contact test@posthog.com in Intercom not found", + }, + { + "level": "debug", + "message": "Execution successful", + }, +] +`; diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index 37d0492022330..ba4e333d23d6c 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -6,6 +6,7 @@ import { status } from '~/src/utils/status' import { PLUGINS_BY_ID } from '../legacy-plugins' import { LegacyPluginLogger, LegacyPluginMeta } from '../legacy-plugins/types' +import { sanitizeLogMessage } from '../services/hog-executor.service' import { HogFunctionInvocation, HogFunctionInvocationResult, HogFunctionTypeType } from '../types' import { CdpCyclotronWorker } from './cdp-cyclotron-worker.consumer' @@ -74,7 +75,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { result.logs.push({ level, timestamp: DateTime.now(), - message: args.join(' '), + message: sanitizeLogMessage(args), }) } diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index 3acd044f8ace8..fedbe3ebe84db 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -46,7 +46,15 @@ describe('CdpCyclotronWorkerPlugins', () => { await processor.start() - processor.fetch = mockFetch = jest.fn(() => Promise.resolve({} as any)) + processor.fetch = mockFetch = jest.fn(() => + Promise.resolve({ + status: 200, + json: () => + Promise.resolve({ + status: 200, + }), + } as any) + ) jest.spyOn(processor['cyclotronWorker']!, 'updateJob').mockImplementation(() => {}) jest.spyOn(processor['cyclotronWorker']!, 'releaseJob').mockImplementation(() => Promise.resolve()) @@ -267,4 +275,49 @@ describe('CdpCyclotronWorkerPlugins', () => { expect(forSnapshot(getProducedKafkaMessages())).toMatchSnapshot() }) }) + + describe('smoke tests', () => { + const testCases = Object.entries(PLUGINS_BY_ID).map(([pluginId, plugin]) => ({ + name: pluginId, + plugin, + })) + + it.each(testCases)('should run the plugin: %s', async ({ name, plugin }) => { + globals.event.event = '$identify' // Many plugins filter for this + const invocation = createInvocation(fn, globals) + + invocation.hogFunction.template_id = `plugin-${plugin.id}` + + const inputs: Record = {} + + for (const input of plugin.metadata.config) { + if (!input.key) { + continue + } + + if (input.default) { + inputs[input.key] = input.default + continue + } + + if (input.type === 'choice') { + inputs[input.key] = input.choices[0] + } else if (input.type === 'string') { + inputs[input.key] = 'test' + } + } + + invocation.hogFunction.name = name + await processor.processInvocations([invocation]) + + expect( + forSnapshot( + getProducedKafkaMessagesForTopic('log_entries_test').map((m) => ({ + message: m.value.message, + level: m.value.level, + })) + ) + ).toMatchSnapshot() + }) + }) }) diff --git a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts index 4650a58471ec0..7ec1e99ec92f5 100644 --- a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts @@ -128,7 +128,7 @@ export const onEvent = async (event: ProcessedPluginEvent, meta: CustomerIoMeta) const customer: Customer = syncCustomerMetadata(meta, event) logger.debug(customer) - logger.debug(shouldCustomerBeTracked(customer, global.eventsConfig)) + logger.debug('Should customer be tracked:', shouldCustomerBeTracked(customer, global.eventsConfig)) if (!shouldCustomerBeTracked(customer, global.eventsConfig)) { return } @@ -147,7 +147,7 @@ function syncCustomerMetadata(meta: CustomerIoMeta, event: ProcessedPluginEvent) const { logger } = meta const email = getEmailFromEvent(event) const customerStatus = new Set() as Customer['status'] - logger.debug(email) + logger.debug('Detected email:', email) // Update customer status customerStatus.add('seen') @@ -256,6 +256,7 @@ function getEmailFromEvent(event: ProcessedPluginEvent): string | null { export const customerioPlugin: LegacyPlugin = { id: 'customer-io', + metadata: require('./plugin.json'), setupPlugin: setupPlugin as any, onEvent, } diff --git a/plugin-server/src/cdp/legacy-plugins/intercom/index.ts b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts index bc0fd544a5528..c01adbb7e46fa 100644 --- a/plugin-server/src/cdp/legacy-plugins/intercom/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts @@ -190,6 +190,7 @@ function getTimestamp(meta: IntercomMeta, event: ProcessedPluginEvent): number { export const intercomPlugin: LegacyPlugin = { id: 'intercom', + metadata: require('./plugin.json'), onEvent, setupPlugin: () => Promise.resolve(), } diff --git a/plugin-server/src/cdp/legacy-plugins/types.ts b/plugin-server/src/cdp/legacy-plugins/types.ts index b65484dfe43a8..f9df0a48e7ad1 100644 --- a/plugin-server/src/cdp/legacy-plugins/types.ts +++ b/plugin-server/src/cdp/legacy-plugins/types.ts @@ -1,4 +1,4 @@ -import { ProcessedPluginEvent } from '@posthog/plugin-scaffold' +import { PluginConfigSchema, ProcessedPluginEvent } from '@posthog/plugin-scaffold' import { Response, trackedFetch } from '~/src/utils/fetch' @@ -19,6 +19,10 @@ export type LegacyPluginMeta = { export type LegacyPlugin = { id: string + metadata: { + name: string + config: PluginConfigSchema[] + } onEvent(event: ProcessedPluginEvent, meta: LegacyPluginMeta): Promise setupPlugin?: (meta: LegacyPluginMeta) => Promise } diff --git a/plugin-server/src/cdp/services/hog-executor.service.ts b/plugin-server/src/cdp/services/hog-executor.service.ts index 9962d51e03b24..5514d03206d28 100644 --- a/plugin-server/src/cdp/services/hog-executor.service.ts +++ b/plugin-server/src/cdp/services/hog-executor.service.ts @@ -93,7 +93,7 @@ export const formatInput = (bytecode: any, globals: HogFunctionInvocation['globa } } -const sanitizeLogMessage = (args: any[], sensitiveValues?: string[]): string => { +export const sanitizeLogMessage = (args: any[], sensitiveValues?: string[]): string => { let message = args.map((arg) => (typeof arg !== 'string' ? JSON.stringify(arg) : arg)).join(', ') // Find and replace any sensitive values From b0ba1888e9fb4d8815b538a4c86409aa2d183e04 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 10:05:13 +0100 Subject: [PATCH 40/46] Fixes --- .../__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap index 4a2036225a8b3..1211a43ef7591 100644 --- a/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap +++ b/plugin-server/src/cdp/consumers/__snapshots__/cdp-cyclotron-plugins-worker.test.ts.snap @@ -56,7 +56,7 @@ exports[`CdpCyclotronWorkerPlugins smoke tests should run the plugin: { name: 'c }, { "level": "debug", - "message": "test@posthog.com", + "message": "Detected email:, test@posthog.com", }, { "level": "debug", @@ -64,7 +64,7 @@ exports[`CdpCyclotronWorkerPlugins smoke tests should run the plugin: { name: 'c }, { "level": "debug", - "message": "true", + "message": "Should customer be tracked:, true", }, { "level": "debug", From 2de9d40339b8aaf6e54d03448c5eaaf00166db09 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 10:09:01 +0100 Subject: [PATCH 41/46] Fixes --- posthog/cdp/migrations.py | 7 ++++++- posthog/models/plugin.py | 18 ++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/posthog/cdp/migrations.py b/posthog/cdp/migrations.py index eee11f0e08011..5156c5e496aac 100644 --- a/posthog/cdp/migrations.py +++ b/posthog/cdp/migrations.py @@ -20,8 +20,13 @@ def migrate_legacy_plugins(dry_run=True, team_ids=None, test_mode=True): continue print("Attempting to migrate plugin", plugin_config) # noqa: T201 + url: str = plugin_config.plugin.url or "" - plugin_id = plugin_config.plugin.url.replace("inline://", "").replace("https://github.com/PostHog/", "") + if not url: + print("Skipping plugin", plugin_config.plugin.name, "as it doesn't have a url") # noqa: T201 + continue + + plugin_id = url.replace("inline://", "").replace("https://github.com/PostHog/", "") plugin_name = plugin_config.plugin.name if test_mode: diff --git a/posthog/models/plugin.py b/posthog/models/plugin.py index a11295e217bc7..a01a7347efb17 100644 --- a/posthog/models/plugin.py +++ b/posthog/models/plugin.py @@ -276,13 +276,19 @@ class PluginAttachment(models.Model): contents = models.BinaryField() def parse_contents(self) -> str | None: - if self.content_type == "application/json": - return json.loads(self.contents) + contents: bytes | None = self.contents + if not contents: + return None - if self.content_type == "text/plain": - return self.contents.decode("utf-8") - - return None + try: + if self.content_type == "application/json": + return json.loads(contents) + + if self.content_type == "text/plain": + return contents.decode("utf-8") + return None + except Exception: + return None class PluginStorage(models.Model): From cde1d59bb96f754d2d0caf3fe0ecdb0e04b8ffe3 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 10:17:38 +0100 Subject: [PATCH 42/46] Fixes --- .../src/cdp/consumers/cdp-function-callback.consumer.ts | 0 .../src/cdp/consumers/cdp-processed-events.consumer.ts | 6 +++--- plugin-server/src/cdp/legacy-plugins/customerio/index.ts | 3 ++- plugin-server/src/cdp/legacy-plugins/intercom/index.ts | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 plugin-server/src/cdp/consumers/cdp-function-callback.consumer.ts diff --git a/plugin-server/src/cdp/consumers/cdp-function-callback.consumer.ts b/plugin-server/src/cdp/consumers/cdp-function-callback.consumer.ts deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts b/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts index 67b434c9979b2..5716e1bea0407 100644 --- a/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts @@ -1,13 +1,13 @@ import { CyclotronManager } from '@posthog/cyclotron' import { Message } from 'node-rdkafka' -import { Hub, RawClickHouseEvent } from '~/src/types' - import { convertToHogFunctionInvocationGlobals, fixLogDeduplication, serializeHogFunctionInvocation, -} from '../../cdp/utils' +} from '~/src/cdp/utils' +import { Hub, RawClickHouseEvent } from '~/src/types' + import { KAFKA_EVENTS_JSON, KAFKA_LOG_ENTRIES } from '../../config/kafka-topics' import { runInstrumentedFunction } from '../../main/utils' import { status } from '../../utils/status' diff --git a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts index 7ec1e99ec92f5..684deb0c22d5e 100644 --- a/plugin-server/src/cdp/legacy-plugins/customerio/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/customerio/index.ts @@ -4,6 +4,7 @@ import { RetryError } from '@posthog/plugin-scaffold' import { Response } from '~/src/utils/fetch' import { LegacyPlugin, LegacyPluginMeta } from '../types' +import metadata from './plugin.json' const DEFAULT_HOST = 'track.customer.io' const DEFAULT_SEND_EVENTS_FROM_ANONYMOUS_USERS = 'Send all events' @@ -256,7 +257,7 @@ function getEmailFromEvent(event: ProcessedPluginEvent): string | null { export const customerioPlugin: LegacyPlugin = { id: 'customer-io', - metadata: require('./plugin.json'), + metadata: metadata as any, setupPlugin: setupPlugin as any, onEvent, } diff --git a/plugin-server/src/cdp/legacy-plugins/intercom/index.ts b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts index c01adbb7e46fa..c2eb3b5319841 100644 --- a/plugin-server/src/cdp/legacy-plugins/intercom/index.ts +++ b/plugin-server/src/cdp/legacy-plugins/intercom/index.ts @@ -3,6 +3,7 @@ import { ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' import { Response } from '~/src/utils/fetch' import { LegacyPlugin, LegacyPluginMeta } from '../types' +import metadata from './plugin.json' type IntercomMeta = LegacyPluginMeta & { global: { @@ -190,7 +191,7 @@ function getTimestamp(meta: IntercomMeta, event: ProcessedPluginEvent): number { export const intercomPlugin: LegacyPlugin = { id: 'intercom', - metadata: require('./plugin.json'), + metadata: metadata as any, onEvent, setupPlugin: () => Promise.resolve(), } From 1e954b235715db86fd917a81ff366c84da7dd73c Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 10:34:13 +0100 Subject: [PATCH 43/46] Fixes --- .../cdp-cyclotron-plugins-worker.consumer.ts | 13 +++---------- .../consumers/cdp-cyclotron-plugins-worker.test.ts | 10 +++++----- .../cdp/consumers/cdp-cyclotron-worker.consumer.ts | 6 ++++-- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts index ba4e333d23d6c..877451bc4417a 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.consumer.ts @@ -1,9 +1,8 @@ import { ProcessedPluginEvent, RetryError } from '@posthog/plugin-scaffold' import { DateTime } from 'luxon' -import { Response, trackedFetch } from '~/src/utils/fetch' -import { status } from '~/src/utils/status' - +import { Response, trackedFetch } from '../../utils/fetch' +import { status } from '../../utils/status' import { PLUGINS_BY_ID } from '../legacy-plugins' import { LegacyPluginLogger, LegacyPluginMeta } from '../legacy-plugins/types' import { sanitizeLogMessage } from '../services/hog-executor.service' @@ -27,13 +26,7 @@ export class CdpCyclotronWorkerPlugins extends CdpCyclotronWorker { private pluginState: Record = {} public async processInvocations(invocations: HogFunctionInvocation[]): Promise { - const results = await this.runManyWithHeartbeat(invocations, (item) => this.executePluginInvocation(item)) - - await this.processInvocationResults(results) - await this.updateJobs(results) - await this.produceQueuedMessages() - - return results + return await this.runManyWithHeartbeat(invocations, (item) => this.executePluginInvocation(item)) } public async fetch(...args: Parameters): Promise { diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts index fedbe3ebe84db..8d501a550c182 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-plugins-worker.test.ts @@ -107,7 +107,7 @@ describe('CdpCyclotronWorkerPlugins', () => { it('should setup a plugin on first call', async () => { jest.spyOn(PLUGINS_BY_ID['intercom'] as any, 'setupPlugin') - const results = processor.processInvocations([ + const results = processor.processBatch([ createInvocation(fn, globals), createInvocation(fn, globals), createInvocation(fn, globals), @@ -152,7 +152,7 @@ describe('CdpCyclotronWorkerPlugins', () => { json: () => Promise.resolve({ total_count: 1 }), }) - await processor.processInvocations([invocation]) + await processor.processBatch([invocation]) expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) expect(forSnapshot(jest.mocked(PLUGINS_BY_ID['intercom'].onEvent!).mock.calls[0][0])) @@ -228,7 +228,7 @@ describe('CdpCyclotronWorkerPlugins', () => { email: 'test@posthog.com', } - await processor.processInvocations([invocation]) + await processor.processBatch([invocation]) expect(mockFetch).toHaveBeenCalledTimes(0) @@ -256,7 +256,7 @@ describe('CdpCyclotronWorkerPlugins', () => { mockFetch.mockRejectedValue(new Error('Test error')) - const res = await processor.processInvocations([invocation]) + const res = await processor.processBatch([invocation]) expect(PLUGINS_BY_ID['intercom'].onEvent).toHaveBeenCalledTimes(1) @@ -308,7 +308,7 @@ describe('CdpCyclotronWorkerPlugins', () => { } invocation.hogFunction.name = name - await processor.processInvocations([invocation]) + await processor.processBatch([invocation]) expect( forSnapshot( diff --git a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts index 185d186a9f2b8..a43930ec547f8 100644 --- a/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-cyclotron-worker.consumer.ts @@ -20,9 +20,9 @@ export class CdpCyclotronWorker extends CdpConsumerBase { return await this.runManyWithHeartbeat(invocations, (item) => this.hogExecutor.execute(item)) } - public async processBatch(invocations: HogFunctionInvocation[]): Promise { + public async processBatch(invocations: HogFunctionInvocation[]): Promise { if (!invocations.length) { - return + return [] } const invocationResults = await runInstrumentedFunction({ @@ -33,6 +33,8 @@ export class CdpCyclotronWorker extends CdpConsumerBase { await this.processInvocationResults(invocationResults) await this.updateJobs(invocationResults) await this.produceQueuedMessages() + + return invocationResults } protected async updateJobs(invocations: HogFunctionInvocationResult[]) { From da407fd592dedd304e7cd8b7c1ed212d4fc0ac53 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 11:27:47 +0100 Subject: [PATCH 44/46] Revert --- .../src/cdp/consumers/cdp-processed-events.consumer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts b/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts index 5716e1bea0407..67b434c9979b2 100644 --- a/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts +++ b/plugin-server/src/cdp/consumers/cdp-processed-events.consumer.ts @@ -1,13 +1,13 @@ import { CyclotronManager } from '@posthog/cyclotron' import { Message } from 'node-rdkafka' +import { Hub, RawClickHouseEvent } from '~/src/types' + import { convertToHogFunctionInvocationGlobals, fixLogDeduplication, serializeHogFunctionInvocation, -} from '~/src/cdp/utils' -import { Hub, RawClickHouseEvent } from '~/src/types' - +} from '../../cdp/utils' import { KAFKA_EVENTS_JSON, KAFKA_LOG_ENTRIES } from '../../config/kafka-topics' import { runInstrumentedFunction } from '../../main/utils' import { status } from '../../utils/status' From ab8757bf83b62c25e2ad6240900ec5378253295e Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 11:53:44 +0100 Subject: [PATCH 45/46] Fixes --- plugin-server/src/main/pluginsServer.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugin-server/src/main/pluginsServer.ts b/plugin-server/src/main/pluginsServer.ts index 274e3231e35f3..6807430d9e931 100644 --- a/plugin-server/src/main/pluginsServer.ts +++ b/plugin-server/src/main/pluginsServer.ts @@ -550,9 +550,13 @@ export async function startPluginsServer( if (capabilities.cdpCyclotronWorkerPlugins) { const hub = await setupHub() - const worker = new CdpCyclotronWorkerPlugins(hub) - await worker.start() - services.push(worker.service) + if (!hub.CYCLOTRON_DATABASE_URL) { + status.error('💥', 'Cyclotron database URL not set.') + } else { + const worker = new CdpCyclotronWorkerPlugins(hub) + await worker.start() + services.push(worker.service) + } } if (capabilities.http) { From 8ebb8a983b1e066a36870e2d439d399b2abfea87 Mon Sep 17 00:00:00 2001 From: Ben White Date: Tue, 28 Jan 2025 12:04:21 +0100 Subject: [PATCH 46/46] Remove old secrets --- .vscode/launch.json | 2 -- plugin-server/src/config/config.ts | 1 - plugin-server/src/types.ts | 1 - 3 files changed, 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index dd756e6acc43d..d8b8160204498 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -143,8 +143,6 @@ "WORKER_CONCURRENCY": "2", "OBJECT_STORAGE_ENABLED": "True", "HOG_HOOK_URL": "http://localhost:3300/hoghook", - "CDP_ASYNC_FUNCTIONS_RUSTY_HOOK_TEAMS": "", - "CDP_CYCLOTRON_ENABLED_TEAMS": "*", "PLUGIN_SERVER_MODE": "all-v2" }, "presentation": { diff --git a/plugin-server/src/config/config.ts b/plugin-server/src/config/config.ts index 5de8a99a0c74c..447c921c645ae 100644 --- a/plugin-server/src/config/config.ts +++ b/plugin-server/src/config/config.ts @@ -187,7 +187,6 @@ export function getDefaultConfig(): PluginsServerConfig { CDP_WATCHER_TTL: 60 * 60 * 24, // This is really long as it is essentially only important to make sure the key is eventually deleted CDP_WATCHER_REFILL_RATE: 10, CDP_WATCHER_DISABLED_TEMPORARY_MAX_COUNT: 3, - CDP_ASYNC_FUNCTIONS_RUSTY_HOOK_TEAMS: '', CDP_HOG_FILTERS_TELEMETRY_TEAMS: '', CDP_REDIS_PASSWORD: '', CDP_EVENT_PROCESSOR_EXECUTE_FIRST_STEP: true, diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 5682796f0817c..ec42460600740 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -119,7 +119,6 @@ export type CdpConfig = { CDP_WATCHER_REFILL_RATE: number // The number of tokens to be refilled per second CDP_WATCHER_DISABLED_TEMPORARY_TTL: number // How long a function should be temporarily disabled for CDP_WATCHER_DISABLED_TEMPORARY_MAX_COUNT: number // How many times a function can be disabled before it is disabled permanently - CDP_ASYNC_FUNCTIONS_RUSTY_HOOK_TEAMS: string CDP_HOG_FILTERS_TELEMETRY_TEAMS: string CDP_CYCLOTRON_BATCH_SIZE: number CDP_CYCLOTRON_BATCH_DELAY_MS: number