fix: Stop telemetry events to Posthog (#16788)

This commit is contained in:
Ricardo Espinoza
2025-06-30 09:08:47 -04:00
committed by GitHub
parent 913334005f
commit d76f05ba3d
30 changed files with 247 additions and 461 deletions

View File

@@ -195,11 +195,7 @@ export class Telemetry {
}); });
} }
track( track(eventName: string, properties: ITelemetryTrackProperties = {}) {
eventName: string,
properties: ITelemetryTrackProperties = {},
{ withPostHog } = { withPostHog: false }, // whether to additionally track with PostHog
) {
if (!this.rudderStack) { if (!this.rudderStack) {
return; return;
} }
@@ -219,10 +215,6 @@ export class Telemetry {
context: {}, context: {},
}; };
if (withPostHog) {
this.postHog?.track(payload);
}
return this.rudderStack.track({ return this.rudderStack.track({
...payload, ...payload,
// provide a fake IP address to instruct RudderStack to not use the user's IP address // provide a fake IP address to instruct RudderStack to not use the user's IP address

View File

@@ -257,14 +257,10 @@ const isSingleLineInput: ComputedRef<boolean> = computed(
function applyOverride() { function applyOverride() {
if (!fromAIOverride.value) return; if (!fromAIOverride.value) return;
telemetry.track( telemetry.track('User turned on fromAI override', {
'User turned on fromAI override', nodeType: activeNode.value?.type,
{ parameter: props.path,
nodeType: activeNode.value?.type, });
parameter: props.path,
},
{ withPostHog: true },
);
updateFromAIOverrideValues(fromAIOverride.value, String(props.value)); updateFromAIOverrideValues(fromAIOverride.value, String(props.value));
const value = buildValueFromOverride(fromAIOverride.value, props, true); const value = buildValueFromOverride(fromAIOverride.value, props, true);
valueChanged({ valueChanged({
@@ -277,14 +273,10 @@ function applyOverride() {
function removeOverride(clearField = false) { function removeOverride(clearField = false) {
if (!fromAIOverride.value) return; if (!fromAIOverride.value) return;
telemetry.track( telemetry.track('User turned off fromAI override', {
'User turned off fromAI override', nodeType: activeNode.value?.type,
{ parameter: props.path,
nodeType: activeNode.value?.type, });
parameter: props.path,
},
{ withPostHog: true },
);
valueChanged({ valueChanged({
node: activeNode.value?.name, node: activeNode.value?.name,
name: props.path, name: props.path,

View File

@@ -847,14 +847,10 @@ function onInputBlur(event: FocusEvent) {
function applyOverride() { function applyOverride() {
if (!props.node || !fromAIOverride.value) return; if (!props.node || !fromAIOverride.value) return;
telemetry.track( telemetry.track('User turned on fromAI override', {
'User turned on fromAI override', nodeType: props.node.type,
{ parameter: props.path,
nodeType: props.node.type, });
parameter: props.path,
},
{ withPostHog: true },
);
updateFromAIOverrideValues(fromAIOverride.value, props.modelValue.value?.toString() ?? ''); updateFromAIOverrideValues(fromAIOverride.value, props.modelValue.value?.toString() ?? '');
emit('update:modelValue', { emit('update:modelValue', {
@@ -866,14 +862,10 @@ function applyOverride() {
function removeOverride() { function removeOverride() {
if (!props.node || !fromAIOverride.value) return; if (!props.node || !fromAIOverride.value) return;
telemetry.track( telemetry.track('User turned off fromAI override', {
'User turned off fromAI override', nodeType: props.node.type,
{ parameter: props.path,
nodeType: props.node.type, });
parameter: props.path,
},
{ withPostHog: true },
);
emit('update:modelValue', { emit('update:modelValue', {
...props.modelValue, ...props.modelValue,
value: buildValueFromOverride(fromAIOverride.value, props, false), value: buildValueFromOverride(fromAIOverride.value, props, false),

View File

@@ -715,18 +715,12 @@ onMounted(() => {
const errorsToTrack = ['unknown error']; const errorsToTrack = ['unknown error'];
if (error && errorsToTrack.some((e) => error.message?.toLowerCase().includes(e))) { if (error && errorsToTrack.some((e) => error.message?.toLowerCase().includes(e))) {
telemetry.track( telemetry.track('User encountered an error', {
'User encountered an error', node: node.value.type,
{ errorMessage: error.message,
node: node.value.type, nodeVersion: node.value.typeVersion,
errorMessage: error.message, n8nVersion: rootStore.versionCli,
nodeVersion: node.value.typeVersion, });
n8nVersion: rootStore.versionCli,
},
{
withPostHog: true,
},
);
} }
} }
}); });

View File

@@ -108,9 +108,7 @@ const onDragEnd = (el: HTMLElement) => {
setTimeout(() => { setTimeout(() => {
void externalHooks.run('runDataJson.onDragEnd', telemetryPayload); void externalHooks.run('runDataJson.onDragEnd', telemetryPayload);
telemetry.track('User dragged data for mapping', telemetryPayload, { telemetry.track('User dragged data for mapping', telemetryPayload);
withPostHog: true,
});
}, 1000); // ensure dest data gets set if drop }, 1000); // ensure dest data gets set if drop
}; };

View File

@@ -308,9 +308,7 @@ function onDragEnd(column: string, src: string, depth = '0') {
void externalHooks.run('runDataTable.onDragEnd', telemetryPayload); void externalHooks.run('runDataTable.onDragEnd', telemetryPayload);
telemetry.track('User dragged data for mapping', telemetryPayload, { telemetry.track('User dragged data for mapping', telemetryPayload);
withPostHog: true,
});
}, 1000); // ensure dest data gets set if drop }, 1000); // ensure dest data gets set if drop
} }

View File

@@ -33,7 +33,7 @@ const {
onMounted(() => { onMounted(() => {
setInitialCredentialSelection(); setInitialCredentialSelection();
telemetry.track('User opened cred setup', { source: 'canvas' }, { withPostHog: true }); telemetry.track('User opened cred setup', { source: 'canvas' });
}); });
onUnmounted(() => { onUnmounted(() => {

View File

@@ -569,7 +569,6 @@ describe('VirtualSchema.vue', () => {
src_nodes_back: '1', src_nodes_back: '1',
src_has_credential: false, src_has_credential: false,
}), }),
{ withPostHog: true },
), ),
); );
}); });
@@ -616,7 +615,6 @@ describe('VirtualSchema.vue', () => {
src_view: 'schema_preview', src_view: 'schema_preview',
src_has_credential: true, src_has_credential: true,
}), }),
{ withPostHog: true },
), ),
); );
}); });

View File

@@ -407,7 +407,7 @@ const onDragEnd = (el: HTMLElement) => {
void useExternalHooks().run('runDataJson.onDragEnd', telemetryPayload); void useExternalHooks().run('runDataJson.onDragEnd', telemetryPayload);
telemetry.track('User dragged data for mapping', telemetryPayload, { withPostHog: true }); telemetry.track('User dragged data for mapping', telemetryPayload);
}, 250); // ensure dest data gets set if drop }, 250); // ensure dest data gets set if drop
}; };
</script> </script>

View File

@@ -171,7 +171,7 @@ function onInputChange(workflowId: NodeParameterValue): void {
} }
function onListItemSelected(value: NodeParameterValue) { function onListItemSelected(value: NodeParameterValue) {
telemetry.track('User chose sub-workflow', {}, { withPostHog: true }); telemetry.track('User chose sub-workflow', {});
onInputChange(value); onInputChange(value);
hideDropdown(); hideDropdown();
} }
@@ -258,7 +258,7 @@ const onAddResourceClicked = async () => {
if (projectId) { if (projectId) {
workflow.projectId = projectId; workflow.projectId = projectId;
} }
telemetry.track('User clicked create new sub-workflow button', {}, { withPostHog: true }); telemetry.track('User clicked create new sub-workflow button', {});
const newWorkflow = await workflowsStore.createNewWorkflow(workflow); const newWorkflow = await workflowsStore.createNewWorkflow(workflow);
const { href } = router.resolve({ const { href } = router.resolve({

View File

@@ -526,15 +526,11 @@ describe('useCanvasOperations', () => {
const { tidyUp } = useCanvasOperations(); const { tidyUp } = useCanvasOperations();
tidyUp(event); tidyUp(event);
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User tidied up canvas', {
'User tidied up canvas', nodes_count: 2,
{ source: 'canvas-button',
nodes_count: 2, target: 'all',
source: 'canvas-button', });
target: 'all',
},
{ withPostHog: true },
);
}); });
}); });

View File

@@ -188,15 +188,11 @@ export function useCanvasOperations() {
} }
function trackTidyUp({ result, source, target }: CanvasLayoutEvent) { function trackTidyUp({ result, source, target }: CanvasLayoutEvent) {
telemetry.track( telemetry.track('User tidied up canvas', {
'User tidied up canvas', source,
{ target,
source, nodes_count: result.nodes.length,
target, });
nodes_count: result.nodes.length,
},
{ withPostHog: true },
);
} }
function updateNodesPosition( function updateNodesPosition(

View File

@@ -59,13 +59,9 @@ export async function executionFinished(
const easyAiWorkflowJson = getEasyAiWorkflowJson(); const easyAiWorkflowJson = getEasyAiWorkflowJson();
const isEasyAIWorkflow = workflow.meta.templateId === easyAiWorkflowJson.meta.templateId; const isEasyAIWorkflow = workflow.meta.templateId === easyAiWorkflowJson.meta.templateId;
if (isEasyAIWorkflow) { if (isEasyAIWorkflow) {
telemetry.track( telemetry.track('User executed test AI workflow', {
'User executed test AI workflow', status: data.status,
{ });
status: data.status,
},
{ withPostHog: true },
);
} }
} }
@@ -313,9 +309,7 @@ export function handleExecutionFinishedWithErrorOrCanceled(
} }
} }
telemetry.track('Instance FE emitted paired item error', eventData, { telemetry.track('Instance FE emitted paired item error', eventData);
withPostHog: true,
});
}); });
} }

View File

@@ -190,9 +190,8 @@ describe('telemetry', () => {
const event = 'testEvent'; const event = 'testEvent';
const properties = { test: '1' }; const properties = { test: '1' };
const options = { withPostHog: false };
telemetry.track(event, properties, options); telemetry.track(event, properties);
expect(trackFunction).toHaveBeenCalledTimes(1); expect(trackFunction).toHaveBeenCalledTimes(1);
expect(trackFunction).toHaveBeenCalledWith( expect(trackFunction).toHaveBeenCalledWith(

View File

@@ -13,7 +13,6 @@ import {
} from '@/constants'; } from '@/constants';
import { useRootStore } from '@n8n/stores/useRootStore'; import { useRootStore } from '@n8n/stores/useRootStore';
import { useNDVStore } from '@/stores/ndv.store'; import { useNDVStore } from '@/stores/ndv.store';
import { usePostHog } from '@/stores/posthog.store';
import { useSettingsStore } from '@/stores/settings.store'; import { useSettingsStore } from '@/stores/settings.store';
import { useUIStore } from '@/stores/ui.store'; import { useUIStore } from '@/stores/ui.store';
@@ -97,11 +96,7 @@ export class Telemetry {
} }
} }
track( track(event: string, properties?: ITelemetryTrackProperties) {
event: string,
properties?: ITelemetryTrackProperties,
options: { withPostHog?: boolean } = {},
) {
if (!this.rudderStack) return; if (!this.rudderStack) return;
const updatedProperties = { const updatedProperties = {
@@ -115,10 +110,6 @@ export class Telemetry {
ip: '0.0.0.0', ip: '0.0.0.0',
}, },
}); });
if (options.withPostHog) {
usePostHog().capture(event, updatedProperties);
}
} }
page(route: RouteLocation) { page(route: RouteLocation) {
@@ -170,7 +161,7 @@ export class Telemetry {
switch (event) { switch (event) {
case 'askAi.generationFinished': case 'askAi.generationFinished':
this.track('Ai code generation finished', properties, { withPostHog: true }); this.track('Ai code generation finished', properties);
default: default:
break; break;
} }
@@ -184,7 +175,7 @@ export class Telemetry {
switch (event) { switch (event) {
case 'generationFinished': case 'generationFinished':
this.track('Ai Transform code generation finished', properties, { withPostHog: true }); this.track('Ai Transform code generation finished', properties);
default: default:
break; break;
} }
@@ -202,14 +193,10 @@ export class Telemetry {
}; };
const changeName = changeNameMap[nodeType] || APPEND_ATTRIBUTION_DEFAULT_PATH; const changeName = changeNameMap[nodeType] || APPEND_ATTRIBUTION_DEFAULT_PATH;
if (change.name === changeName) { if (change.name === changeName) {
this.track( this.track('User toggled n8n reference option', {
'User toggled n8n reference option', node: nodeType,
{ toValue: change.value,
node: nodeType, });
toValue: change.value,
},
{ withPostHog: true },
);
} }
} }
} }

View File

@@ -371,18 +371,12 @@ describe('AI Assistant store', () => {
source: 'error', source: 'error',
has_existing_session: true, has_existing_session: true,
}); });
expect(track).toHaveBeenCalledWith( expect(track).toHaveBeenCalledWith('Assistant session started', {
'Assistant session started', chat_session_id: 'test',
{ node_type: 'n8n-nodes-base.stopAndError',
chat_session_id: 'test', task: 'error',
node_type: 'n8n-nodes-base.stopAndError', credential_type: undefined,
task: 'error', });
credential_type: undefined,
},
{
withPostHog: true,
},
);
expect(track).toHaveBeenCalledWith('User opened assistant', { expect(track).toHaveBeenCalledWith('User opened assistant', {
chat_session_id: 'test', chat_session_id: 'test',

View File

@@ -291,16 +291,12 @@ export const useAssistantStore = defineStore(STORES.ASSISTANT, () => {
function onEachStreamingMessage(response: ChatRequest.ResponsePayload, id: string) { function onEachStreamingMessage(response: ChatRequest.ResponsePayload, id: string) {
if (response.sessionId && !currentSessionId.value) { if (response.sessionId && !currentSessionId.value) {
currentSessionId.value = response.sessionId; currentSessionId.value = response.sessionId;
telemetry.track( telemetry.track('Assistant session started', {
'Assistant session started', chat_session_id: currentSessionId.value,
{ task: chatSessionTask.value,
chat_session_id: currentSessionId.value, node_type: chatSessionError.value?.node.type,
task: chatSessionTask.value, credential_type: chatSessionCredType.value?.name,
node_type: chatSessionError.value?.node.type, });
credential_type: chatSessionCredType.value?.name,
},
{ withPostHog: true },
);
// Track first user message in support chat now that we have a session id // Track first user message in support chat now that we have a session id
if (usersMessages.value.length === 1 && chatSessionTask.value === 'support') { if (usersMessages.value.length === 1 && chatSessionTask.value === 'support') {
const firstUserMessage = usersMessages.value[0] as ChatUI.TextMessage; const firstUserMessage = usersMessages.value[0] as ChatUI.TextMessage;

View File

@@ -242,14 +242,10 @@ export const useBuilderStore = defineStore(STORES.BUILDER, () => {
function onEachStreamingMessage(response: ChatRequest.ResponsePayload, id: string) { function onEachStreamingMessage(response: ChatRequest.ResponsePayload, id: string) {
if (response.sessionId && !currentSessionId.value) { if (response.sessionId && !currentSessionId.value) {
currentSessionId.value = response.sessionId; currentSessionId.value = response.sessionId;
telemetry.track( telemetry.track('Assistant session started', {
'Assistant session started', chat_session_id: currentSessionId.value,
{ task: 'workflow-generation',
chat_session_id: currentSessionId.value, });
task: 'workflow-generation',
},
{ withPostHog: true },
);
} else if (currentSessionId.value !== response.sessionId) { } else if (currentSessionId.value !== response.sessionId) {
// Ignore messages from other sessions // Ignore messages from other sessions
return; return;
@@ -263,14 +259,10 @@ export const useBuilderStore = defineStore(STORES.BUILDER, () => {
// Core API functions // Core API functions
async function initBuilderChat(userMessage: string, source: 'chat' | 'canvas') { async function initBuilderChat(userMessage: string, source: 'chat' | 'canvas') {
telemetry.track( telemetry.track('User submitted workflow prompt', {
'User submitted workflow prompt', source,
{ prompt: userMessage,
source, });
prompt: userMessage,
},
{ withPostHog: true },
);
resetBuilderChat(); resetBuilderChat();
const id = getRandomId(); const id = getRandomId();

View File

@@ -80,18 +80,12 @@ describe('useNodeCreatorStore', () => {
workflow_id, workflow_id,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User opened nodes panel', {
'User opened nodes panel', mode,
{ source,
mode, nodes_panel_session_id: getSessionId(now),
source, workflow_id,
nodes_panel_session_id: getSessionId(now), });
workflow_id,
},
{
withPostHog: false,
},
);
}); });
it('resets session id every time node creator is opened', () => { it('resets session id every time node creator is opened', () => {
@@ -101,18 +95,12 @@ describe('useNodeCreatorStore', () => {
workflow_id, workflow_id,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User opened nodes panel', {
'User opened nodes panel', mode,
{ source,
mode, nodes_panel_session_id: getSessionId(now),
source, workflow_id,
nodes_panel_session_id: getSessionId(now), });
workflow_id,
},
{
withPostHog: false,
},
);
vi.setSystemTime(now1); vi.setSystemTime(now1);
@@ -122,18 +110,12 @@ describe('useNodeCreatorStore', () => {
workflow_id, workflow_id,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User opened nodes panel', {
'User opened nodes panel', mode,
{ source,
mode, nodes_panel_session_id: getSessionId(now1),
source, workflow_id,
nodes_panel_session_id: getSessionId(now1), });
workflow_id,
},
{
withPostHog: false,
},
);
}); });
it('tracks event on category expanded', () => { it('tracks event on category expanded', () => {
@@ -144,18 +126,12 @@ describe('useNodeCreatorStore', () => {
}); });
nodeCreatorStore.onCategoryExpanded({ workflow_id, category_name }); nodeCreatorStore.onCategoryExpanded({ workflow_id, category_name });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed node category', {
'User viewed node category', category_name,
{ is_subcategory: false,
category_name, nodes_panel_session_id: getSessionId(now),
is_subcategory: false, workflow_id,
nodes_panel_session_id: getSessionId(now), });
workflow_id,
},
{
withPostHog: false,
},
);
}); });
it('tracks event when node is added to canvas', () => { it('tracks event when node is added to canvas', () => {
@@ -174,22 +150,16 @@ describe('useNodeCreatorStore', () => {
input_node_type, input_node_type,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User added node to workflow canvas', {
'User added node to workflow canvas', node_id,
{ node_type,
node_id, node_version,
node_type, is_auto_add: true,
node_version, drag_and_drop: true,
is_auto_add: true, input_node_type,
drag_and_drop: true, nodes_panel_session_id: getSessionId(now),
input_node_type, workflow_id,
nodes_panel_session_id: getSessionId(now), });
workflow_id,
},
{
withPostHog: true,
},
);
}); });
it('tracks event when action is added', () => { it('tracks event when action is added', () => {
@@ -205,19 +175,13 @@ describe('useNodeCreatorStore', () => {
resource, resource,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User added action', {
'User added action', node_type,
{ action,
node_type, source_mode,
action, resource,
source_mode, nodes_panel_session_id: getSessionId(now),
resource, });
nodes_panel_session_id: getSessionId(now),
},
{
withPostHog: false,
},
);
}); });
it('tracks when custom api action is clicked', () => { it('tracks when custom api action is clicked', () => {
@@ -230,16 +194,10 @@ describe('useNodeCreatorStore', () => {
app_identifier: node_type, app_identifier: node_type,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User clicked custom API from node actions', {
'User clicked custom API from node actions', app_identifier: node_type,
{ nodes_panel_session_id: getSessionId(now),
app_identifier: node_type, });
nodes_panel_session_id: getSessionId(now),
},
{
withPostHog: false,
},
);
}); });
it('tracks when action is viewed', () => { it('tracks when action is viewed', () => {
@@ -255,19 +213,13 @@ describe('useNodeCreatorStore', () => {
trigger_action_count: 2, trigger_action_count: 2,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed node actions', {
'User viewed node actions', app_identifier: node_type,
{ actions,
app_identifier: node_type, regular_action_count: 1,
actions, trigger_action_count: 2,
regular_action_count: 1, nodes_panel_session_id: getSessionId(now),
trigger_action_count: 2, });
nodes_panel_session_id: getSessionId(now),
},
{
withPostHog: false,
},
);
}); });
it('tracks when search filter is updated, ignoring custom actions in count', () => { it('tracks when search filter is updated, ignoring custom actions in count', () => {
@@ -308,22 +260,16 @@ describe('useNodeCreatorStore', () => {
title, title,
}); });
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User entered nodes panel search term', {
'User entered nodes panel search term', search_string: newValue,
{ filter_mode: 'regular',
search_string: newValue, category_name: subcategory,
filter_mode: 'regular', results_count: 2,
category_name: subcategory, trigger_count: 1,
results_count: 2, regular_count: 1,
trigger_count: 1, nodes_panel_session_id: getSessionId(now),
regular_count: 1, title,
nodes_panel_session_id: getSessionId(now), });
title,
},
{
withPostHog: false,
},
);
}); });
describe('selective connection view', () => { describe('selective connection view', () => {
const mockedParseCanvasConnectionHandleString = vi.mocked( const mockedParseCanvasConnectionHandleString = vi.mocked(

View File

@@ -292,17 +292,11 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
nodePanelSessionId.value = `nodes_panel_session_${new Date().valueOf()}`; nodePanelSessionId.value = `nodes_panel_session_${new Date().valueOf()}`;
} }
function trackNodeCreatorEvent(event: string, properties: IDataObject = {}, withPostHog = false) { function trackNodeCreatorEvent(event: string, properties: IDataObject = {}) {
telemetry.track( telemetry.track(event, {
event, ...properties,
{ nodes_panel_session_id: nodePanelSessionId.value,
...properties, });
nodes_panel_session_id: nodePanelSessionId.value,
},
{
withPostHog,
},
);
} }
function onCreatorOpened({ function onCreatorOpened({
@@ -419,7 +413,7 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
drag_and_drop?: boolean; drag_and_drop?: boolean;
input_node_type?: string; input_node_type?: string;
}) { }) {
trackNodeCreatorEvent('User added node to workflow canvas', properties, true); trackNodeCreatorEvent('User added node to workflow canvas', properties);
} }
function getMode(mode: NodeFilterType): string { function getMode(mode: NodeFilterType): string {

View File

@@ -164,12 +164,6 @@ export const usePostHog = defineStore('posthog', () => {
} }
}; };
const capture = (event: string, properties: IDataObject) => {
if (typeof window.posthog?.capture === 'function') {
window.posthog.capture(event, properties);
}
};
const setMetadata = (metadata: IDataObject, target: 'user' | 'events') => { const setMetadata = (metadata: IDataObject, target: 'user' | 'events') => {
if (typeof window.posthog?.people?.set !== 'function') return; if (typeof window.posthog?.people?.set !== 'function') return;
if (typeof window.posthog?.register !== 'function') return; if (typeof window.posthog?.register !== 'function') return;
@@ -188,7 +182,6 @@ export const usePostHog = defineStore('posthog', () => {
getVariant, getVariant,
reset, reset,
identify, identify,
capture,
setMetadata, setMetadata,
overrides, overrides,
}; };

View File

@@ -647,20 +647,14 @@ describe('useWorkflowsStore', () => {
}, },
}, },
}); });
expect(track).toHaveBeenCalledWith( expect(track).toHaveBeenCalledWith('Manual exec errored', {
'Manual exec errored', error_title: 'invalid syntax',
{ node_type: 'n8n-nodes-base.set',
error_title: 'invalid syntax', node_type_version: 3.4,
node_type: 'n8n-nodes-base.set', node_id: '554c7ff4-7ee2-407c-8931-e34234c5056a',
node_type_version: 3.4, node_graph_string:
node_id: '554c7ff4-7ee2-407c-8931-e34234c5056a', '{"node_types":["n8n-nodes-base.set"],"node_connections":[],"nodes":{"0":{"id":"554c7ff4-7ee2-407c-8931-e34234c5056a","type":"n8n-nodes-base.set","version":3.4,"position":[680,180]}},"notes":{},"is_pinned":false}',
node_graph_string: });
'{"node_types":["n8n-nodes-base.set"],"node_connections":[],"nodes":{"0":{"id":"554c7ff4-7ee2-407c-8931-e34234c5056a","type":"n8n-nodes-base.set","version":3.4,"position":[680,180]}},"notes":{},"is_pinned":false}',
},
{
withPostHog: true,
},
);
}); });
it('sets workflow pin data', () => { it('sets workflow pin data', () => {

View File

@@ -1511,25 +1511,21 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
if (pushData.data.error) { if (pushData.data.error) {
const node = getNodeByName(nodeName); const node = getNodeByName(nodeName);
telemetry.track( telemetry.track('Manual exec errored', {
'Manual exec errored', error_title: pushData.data.error.message,
{ node_type: node?.type,
error_title: pushData.data.error.message, node_type_version: node?.typeVersion,
node_type: node?.type, node_id: node?.id,
node_type_version: node?.typeVersion, node_graph_string: JSON.stringify(
node_id: node?.id, TelemetryHelpers.generateNodesGraph(
node_graph_string: JSON.stringify( await workflowHelpers.getWorkflowDataToSave(),
TelemetryHelpers.generateNodesGraph( workflowHelpers.getNodeTypes(),
await workflowHelpers.getWorkflowDataToSave(), {
workflowHelpers.getNodeTypes(), isCloudDeployment: settingsStore.isCloudDeployment,
{ },
isCloudDeployment: settingsStore.isCloudDeployment, ).nodeGraph,
}, ),
).nodeGraph, });
),
},
{ withPostHog: true },
);
} }
} }

View File

@@ -70,7 +70,7 @@ async function openTemplateCredentialSetup(opts: {
}) { }) {
const { router, templateId, inNewBrowserTab = false, telemetry, source } = opts; const { router, templateId, inNewBrowserTab = false, telemetry, source } = opts;
telemetry.track('User opened cred setup', { source }, { withPostHog: true }); telemetry.track('User opened cred setup', { source });
const routeLocation: RouteLocationRaw = { const routeLocation: RouteLocationRaw = {
name: VIEWS.TEMPLATE_SETUP, name: VIEWS.TEMPLATE_SETUP,

View File

@@ -103,30 +103,22 @@ watch(
(ready) => { (ready) => {
if (ready) { if (ready) {
if (showWizard.value) { if (showWizard.value) {
telemetry.track( telemetry.track('User viewed tests tab', {
'User viewed tests tab', workflow_id: props.name,
{ test_type: 'evaluation',
workflow_id: props.name, view: 'setup',
test_type: 'evaluation', trigger_set_up: evaluationStore.evaluationTriggerExists,
view: 'setup', output_set_up: evaluationStore.evaluationSetOutputsNodeExist,
trigger_set_up: evaluationStore.evaluationTriggerExists, metrics_set_up: evaluationStore.evaluationSetMetricsNodeExist,
output_set_up: evaluationStore.evaluationSetOutputsNodeExist, quota_reached: evaluationsQuotaExceeded.value,
metrics_set_up: evaluationStore.evaluationSetMetricsNodeExist, });
quota_reached: evaluationsQuotaExceeded.value,
},
{ withPostHog: true },
);
} else { } else {
telemetry.track( telemetry.track('User viewed tests tab', {
'User viewed tests tab', workflow_id: props.name,
{ test_type: 'evaluation',
workflow_id: props.name, view: 'overview',
test_type: 'evaluation', run_count: runs.value.length,
view: 'overview', });
run_count: runs.value.length,
},
{ withPostHog: true },
);
} }
} }
}, },

View File

@@ -144,19 +144,15 @@ describe('EvaluationsRootView', () => {
renderComponent({ props: { name: mockWorkflow.id } }); renderComponent({ props: { name: mockWorkflow.id } });
await waitFor(() => { await waitFor(() => {
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed tests tab', {
'User viewed tests tab', workflow_id: mockWorkflow.id,
{ test_type: 'evaluation',
workflow_id: mockWorkflow.id, view: 'setup',
test_type: 'evaluation', trigger_set_up: false,
view: 'setup', output_set_up: false,
trigger_set_up: false, metrics_set_up: false,
output_set_up: false, quota_reached: false,
metrics_set_up: false, });
quota_reached: false,
},
{ withPostHog: true },
);
}); });
}); });
@@ -176,16 +172,12 @@ describe('EvaluationsRootView', () => {
renderComponent({ props: { name: mockWorkflow.id } }); renderComponent({ props: { name: mockWorkflow.id } });
await waitFor(() => { await waitFor(() => {
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed tests tab', {
'User viewed tests tab', workflow_id: mockWorkflow.id,
{ test_type: 'evaluation',
workflow_id: mockWorkflow.id, view: 'overview',
test_type: 'evaluation', run_count: 2,
view: 'overview', });
run_count: 2,
},
{ withPostHog: true },
);
}); });
}); });
@@ -223,19 +215,15 @@ describe('EvaluationsRootView', () => {
renderComponent({ props: { name: mockWorkflow.id } }); renderComponent({ props: { name: mockWorkflow.id } });
await waitFor(() => { await waitFor(() => {
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed tests tab', {
'User viewed tests tab', workflow_id: mockWorkflow.id,
{ test_type: 'evaluation',
workflow_id: mockWorkflow.id, view: 'setup',
test_type: 'evaluation', trigger_set_up: true,
view: 'setup', output_set_up: false,
trigger_set_up: true, metrics_set_up: false,
output_set_up: false, quota_reached: false,
metrics_set_up: false, });
quota_reached: false,
},
{ withPostHog: true },
);
}); });
}); });
@@ -279,19 +267,15 @@ describe('EvaluationsRootView', () => {
renderComponent({ props: { name: mockWorkflow.id } }); renderComponent({ props: { name: mockWorkflow.id } });
await waitFor(() => { await waitFor(() => {
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed tests tab', {
'User viewed tests tab', workflow_id: mockWorkflow.id,
{ test_type: 'evaluation',
workflow_id: mockWorkflow.id, view: 'setup',
test_type: 'evaluation', trigger_set_up: false,
view: 'setup', output_set_up: true,
trigger_set_up: false, metrics_set_up: false,
output_set_up: true, quota_reached: false,
metrics_set_up: false, });
quota_reached: false,
},
{ withPostHog: true },
);
}); });
}); });
@@ -335,19 +319,15 @@ describe('EvaluationsRootView', () => {
renderComponent({ props: { name: mockWorkflow.id } }); renderComponent({ props: { name: mockWorkflow.id } });
await waitFor(() => { await waitFor(() => {
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed tests tab', {
'User viewed tests tab', workflow_id: mockWorkflow.id,
{ test_type: 'evaluation',
workflow_id: mockWorkflow.id, view: 'setup',
test_type: 'evaluation', trigger_set_up: false,
view: 'setup', output_set_up: false,
trigger_set_up: false, metrics_set_up: true,
output_set_up: false, quota_reached: false,
metrics_set_up: true, });
quota_reached: false,
},
{ withPostHog: true },
);
}); });
}); });
@@ -367,19 +347,15 @@ describe('EvaluationsRootView', () => {
renderComponent({ props: { name: mockWorkflow.id } }); renderComponent({ props: { name: mockWorkflow.id } });
await waitFor(() => { await waitFor(() => {
expect(useTelemetry().track).toHaveBeenCalledWith( expect(useTelemetry().track).toHaveBeenCalledWith('User viewed tests tab', {
'User viewed tests tab', workflow_id: mockWorkflow.id,
{ test_type: 'evaluation',
workflow_id: mockWorkflow.id, view: 'setup',
test_type: 'evaluation', trigger_set_up: false,
view: 'setup', output_set_up: false,
trigger_set_up: false, metrics_set_up: false,
output_set_up: false, quota_reached: true,
metrics_set_up: false, });
quota_reached: true,
},
{ withPostHog: true },
);
}); });
}); });
}); });

View File

@@ -554,9 +554,6 @@ function trackOpenWorkflowFromOnboardingTemplate() {
{ {
workflow_id: workflowId.value, workflow_id: workflowId.value,
}, },
{
withPostHog: true,
},
); );
} }
@@ -646,17 +643,11 @@ async function openWorkflowTemplate(templateId: string) {
} }
function trackOpenWorkflowTemplate(templateId: string) { function trackOpenWorkflowTemplate(templateId: string) {
telemetry.track( telemetry.track('User inserted workflow template', {
'User inserted workflow template', source: 'workflow',
{ template_id: tryToParseNumber(templateId),
source: 'workflow', wf_template_repo_session_id: templatesStore.previousSessionId,
template_id: tryToParseNumber(templateId), });
wf_template_repo_session_id: templatesStore.previousSessionId,
},
{
withPostHog: true,
},
);
} }
/** /**

View File

@@ -62,17 +62,11 @@ const nodeNames = computed(() => {
//#region Methods //#region Methods
const onCredentialModalOpened = () => { const onCredentialModalOpened = () => {
telemetry.track( telemetry.track('User opened Credential modal', {
'User opened Credential modal', source: 'cred_setup',
{ credentialType: props.credentials.credentialType,
source: 'cred_setup', new_credential: !props.selectedCredentialId,
credentialType: props.credentials.credentialType, });
new_credential: !props.selectedCredentialId,
},
{
withPostHog: true,
},
);
}; };
//#endregion Methods //#endregion Methods

View File

@@ -197,15 +197,11 @@ export const useSetupTemplateStore = defineStore('setupTemplate', () => {
workflow_id: createdWorkflow.id, workflow_id: createdWorkflow.id,
}); });
telemetry.track( telemetry.track('User inserted workflow template', {
'User inserted workflow template', source: 'workflow',
{ template_id: tryToParseNumber(templateId.value),
source: 'workflow', wf_template_repo_session_id: templatesStore.currentSessionId,
template_id: tryToParseNumber(templateId.value), });
wf_template_repo_session_id: templatesStore.currentSessionId,
},
{ withPostHog: true },
);
telemetry.track('User saved new workflow from template', { telemetry.track('User saved new workflow from template', {
template_id: tryToParseNumber(templateId.value), template_id: tryToParseNumber(templateId.value),

View File

@@ -765,13 +765,9 @@ function isValidProjectId(projectId: string) {
const openAIWorkflow = async (source: string) => { const openAIWorkflow = async (source: string) => {
dismissEasyAICallout(); dismissEasyAICallout();
telemetry.track( telemetry.track('User clicked test AI workflow', {
'User clicked test AI workflow', source,
{ });
source,
},
{ withPostHog: true },
);
const easyAiWorkflowJson = getEasyAiWorkflowJson(); const easyAiWorkflowJson = getEasyAiWorkflowJson();