feat(n8n Evaluation Trigger Node): Add telemetry events (#15465)

This commit is contained in:
Dana
2025-05-16 17:22:17 +02:00
committed by GitHub
parent b53bd173d0
commit 9834a49bd3
5 changed files with 48 additions and 3 deletions

View File

@@ -729,6 +729,7 @@ export class TelemetryEventRelay extends EventRelay {
sharing_role: userRole, sharing_role: userRole,
credential_type: null, credential_type: null,
is_managed: false, is_managed: false,
eval_rows_left: null,
...TelemetryHelpers.resolveAIMetrics(workflow.nodes, this.nodeTypes), ...TelemetryHelpers.resolveAIMetrics(workflow.nodes, this.nodeTypes),
}; };
@@ -739,6 +740,15 @@ export class TelemetryEventRelay extends EventRelay {
manualExecEventProperties.node_graph_string = JSON.stringify(nodeGraphResult.nodeGraph); manualExecEventProperties.node_graph_string = JSON.stringify(nodeGraphResult.nodeGraph);
} }
nodeGraphResult?.evaluationTriggerNodeNames?.forEach((name: string) => {
const rowsLeft =
runData.data.resultData.runData[name]?.[0]?.data?.main?.[0]?.[0]?.json?._rowsLeft;
if (typeof rowsLeft === 'number') {
manualExecEventProperties.eval_rows_left = rowsLeft;
}
});
if (runData.data.startData?.destinationNode) { if (runData.data.startData?.destinationNode) {
const credentialsData = TelemetryHelpers.extractLastExecutedNodeCredentialData(runData); const credentialsData = TelemetryHelpers.extractLastExecutedNodeCredentialData(runData);
if (credentialsData) { if (credentialsData) {

View File

@@ -28,6 +28,7 @@ export const HTTP_REQUEST_NODE_TYPE = 'n8n-nodes-base.httpRequest';
export const WEBHOOK_NODE_TYPE = 'n8n-nodes-base.webhook'; export const WEBHOOK_NODE_TYPE = 'n8n-nodes-base.webhook';
export const MANUAL_TRIGGER_NODE_TYPE = 'n8n-nodes-base.manualTrigger'; export const MANUAL_TRIGGER_NODE_TYPE = 'n8n-nodes-base.manualTrigger';
export const EVALUATION_TRIGGER_NODE_TYPE = 'n8n-nodes-base.evaluationTrigger'; export const EVALUATION_TRIGGER_NODE_TYPE = 'n8n-nodes-base.evaluationTrigger';
export const EVALUATION_NODE_TYPE = 'n8n-nodes-base.evaluation';
export const ERROR_TRIGGER_NODE_TYPE = 'n8n-nodes-base.errorTrigger'; export const ERROR_TRIGGER_NODE_TYPE = 'n8n-nodes-base.errorTrigger';
export const START_NODE_TYPE = 'n8n-nodes-base.start'; export const START_NODE_TYPE = 'n8n-nodes-base.start';
export const EXECUTE_WORKFLOW_NODE_TYPE = 'n8n-nodes-base.executeWorkflow'; export const EXECUTE_WORKFLOW_NODE_TYPE = 'n8n-nodes-base.executeWorkflow';

View File

@@ -2587,6 +2587,7 @@ export interface INodeGraphItem {
workflow_id?: string; //@n8n/n8n-nodes-langchain.toolWorkflow and n8n-nodes-base.executeWorkflow workflow_id?: string; //@n8n/n8n-nodes-langchain.toolWorkflow and n8n-nodes-base.executeWorkflow
runs?: number; runs?: number;
items_total?: number; items_total?: number;
metric_names?: string[];
} }
export interface INodeNameIndex { export interface INodeNameIndex {
@@ -2597,6 +2598,7 @@ export interface INodesGraphResult {
nodeGraph: INodesGraph; nodeGraph: INodesGraph;
nameIndices: INodeNameIndex; nameIndices: INodeNameIndex;
webhookNodeNames: string[]; webhookNodeNames: string[];
evaluationTriggerNodeNames: string[];
} }
export interface FeatureFlags { export interface FeatureFlags {

View File

@@ -3,6 +3,8 @@ import {
AI_TRANSFORM_NODE_TYPE, AI_TRANSFORM_NODE_TYPE,
CHAIN_LLM_LANGCHAIN_NODE_TYPE, CHAIN_LLM_LANGCHAIN_NODE_TYPE,
CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE, CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE,
EVALUATION_NODE_TYPE,
EVALUATION_TRIGGER_NODE_TYPE,
EXECUTE_WORKFLOW_NODE_TYPE, EXECUTE_WORKFLOW_NODE_TYPE,
FREE_AI_CREDITS_ERROR_TYPE, FREE_AI_CREDITS_ERROR_TYPE,
FREE_AI_CREDITS_USED_ALL_CREDITS_ERROR_CODE, FREE_AI_CREDITS_USED_ALL_CREDITS_ERROR_CODE,
@@ -178,11 +180,12 @@ export function generateNodesGraph(
}; };
const nameIndices: INodeNameIndex = {}; const nameIndices: INodeNameIndex = {};
const webhookNodeNames: string[] = []; const webhookNodeNames: string[] = [];
const evaluationTriggerNodeNames: string[] = [];
const notes = (workflow.nodes ?? []).filter((node) => node.type === STICKY_NODE_TYPE); const nodes = (workflow.nodes ?? []).filter((node) => node.type === STICKY_NODE_TYPE);
const otherNodes = (workflow.nodes ?? []).filter((node) => node.type !== STICKY_NODE_TYPE); const otherNodes = (workflow.nodes ?? []).filter((node) => node.type !== STICKY_NODE_TYPE);
notes.forEach((stickyNote: INode, index: number) => { nodes.forEach((stickyNote: INode, index: number) => {
const stickyType = nodeTypes.getByNameAndVersion(STICKY_NODE_TYPE, stickyNote.typeVersion); const stickyType = nodeTypes.getByNameAndVersion(STICKY_NODE_TYPE, stickyNote.typeVersion);
if (!stickyType) { if (!stickyType) {
return; return;
@@ -367,6 +370,18 @@ export function generateNodesGraph(
if (node.parameters?.workflowId) { if (node.parameters?.workflowId) {
nodeItem.workflow_id = node.parameters?.workflowId as string; nodeItem.workflow_id = node.parameters?.workflowId as string;
} }
} else if (node.type === EVALUATION_TRIGGER_NODE_TYPE) {
evaluationTriggerNodeNames.push(node.name);
} else if (
node.type === EVALUATION_NODE_TYPE &&
options?.isCloudDeployment &&
node.parameters?.operation === 'setMetrics'
) {
const metrics = node.parameters?.metrics as IDataObject;
nodeItem.metric_names = (metrics.assignments as Array<{ name: string }> | undefined)?.map(
(metric: { name: string }) => metric.name,
);
} else { } else {
try { try {
const nodeType = nodeTypes.getByNameAndVersion(node.type, node.typeVersion); const nodeType = nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
@@ -484,7 +499,7 @@ export function generateNodesGraph(
}); });
}); });
return { nodeGraph, nameIndices, webhookNodeNames }; return { nodeGraph, nameIndices, webhookNodeNames, evaluationTriggerNodeNames };
} }
export function extractLastExecutedNodeCredentialData( export function extractLastExecutedNodeCredentialData(

View File

@@ -148,6 +148,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'When clicking "Execute Workflow"': '0', 'Google Sheets': '1' }, nameIndices: { 'When clicking "Execute Workflow"': '0', 'Google Sheets': '1' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -175,6 +176,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: {}, nameIndices: {},
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -190,6 +192,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: {}, nameIndices: {},
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -256,6 +259,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'When clicking "Execute Workflow"': '0', 'Google Sheets': '1' }, nameIndices: { 'When clicking "Execute Workflow"': '0', 'Google Sheets': '1' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -333,6 +337,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'When clicking "Execute Workflow"': '0', 'Google Sheets': '1' }, nameIndices: { 'When clicking "Execute Workflow"': '0', 'Google Sheets': '1' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -388,6 +393,7 @@ describe('generateNodesGraph', () => {
versionId: '70b92d94-0e9a-4b41-9976-a654df420af5', versionId: '70b92d94-0e9a-4b41-9976-a654df420af5',
}; };
expect(generateNodesGraph(workflow, nodeTypes)).toEqual({ expect(generateNodesGraph(workflow, nodeTypes)).toEqual({
evaluationTriggerNodeNames: [],
nodeGraph: { nodeGraph: {
node_types: ['n8n-nodes-base.manualTrigger', 'test.googleSheets'], node_types: ['n8n-nodes-base.manualTrigger', 'test.googleSheets'],
node_connections: [{ start: '0', end: '1' }], node_connections: [{ start: '0', end: '1' }],
@@ -451,6 +457,7 @@ describe('generateNodesGraph', () => {
notes: {}, notes: {},
}, },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -474,6 +481,7 @@ describe('generateNodesGraph', () => {
pinData: {}, pinData: {},
}; };
expect(generateNodesGraph(workflow, nodeTypes)).toEqual({ expect(generateNodesGraph(workflow, nodeTypes)).toEqual({
evaluationTriggerNodeNames: [],
nodeGraph: { nodeGraph: {
node_types: ['n8n-nodes-base.webhook'], node_types: ['n8n-nodes-base.webhook'],
node_connections: [], node_connections: [],
@@ -520,6 +528,7 @@ describe('generateNodesGraph', () => {
pinData: {}, pinData: {},
}; };
expect(generateNodesGraph(workflow, nodeTypes)).toEqual({ expect(generateNodesGraph(workflow, nodeTypes)).toEqual({
evaluationTriggerNodeNames: [],
nodeGraph: { nodeGraph: {
node_types: ['n8n-nodes-base.httpRequest'], node_types: ['n8n-nodes-base.httpRequest'],
node_connections: [], node_connections: [],
@@ -574,6 +583,7 @@ describe('generateNodesGraph', () => {
pinData: {}, pinData: {},
}; };
expect(generateNodesGraph(workflow, nodeTypes)).toEqual({ expect(generateNodesGraph(workflow, nodeTypes)).toEqual({
evaluationTriggerNodeNames: [],
nodeGraph: { nodeGraph: {
node_types: ['n8n-nodes-base.httpRequest'], node_types: ['n8n-nodes-base.httpRequest'],
node_connections: [], node_connections: [],
@@ -635,6 +645,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'Merge Node V3': '0' }, nameIndices: { 'Merge Node V3': '0' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}, },
}, },
{ {
@@ -673,6 +684,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'Merge Node V3': '0' }, nameIndices: { 'Merge Node V3': '0' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}, },
}, },
{ {
@@ -713,6 +725,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'Merge Node V3': '0' }, nameIndices: { 'Merge Node V3': '0' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}, },
}, },
])('should return graph with merge v3 node', ({ workflow, expected, isCloudDeployment }) => { ])('should return graph with merge v3 node', ({ workflow, expected, isCloudDeployment }) => {
@@ -755,6 +768,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'HTTP Request V1': '0' }, nameIndices: { 'HTTP Request V1': '0' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -795,6 +809,7 @@ describe('generateNodesGraph', () => {
}, },
nameIndices: { 'HTTP Request v4 with defaults': '0' }, nameIndices: { 'HTTP Request v4 with defaults': '0' },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -900,6 +915,7 @@ describe('generateNodesGraph', () => {
Model: '2', Model: '2',
}, },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
@@ -1012,6 +1028,7 @@ describe('generateNodesGraph', () => {
notes: {}, notes: {},
}, },
webhookNodeNames: [], webhookNodeNames: [],
evaluationTriggerNodeNames: [],
}); });
}); });
}); });