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