refactor(core): Add node ID to log streaming events (#16313)

This commit is contained in:
Iván Ovejero
2025-06-13 13:08:16 +02:00
committed by GitHub
parent 43c52a8b4f
commit ce3c92abe2
8 changed files with 67 additions and 7 deletions

View File

@@ -13,6 +13,7 @@ export interface EventPayloadNode extends AbstractEventPayload {
msg?: string; msg?: string;
executionId: string; executionId: string;
nodeName: string; nodeName: string;
nodeId?: string;
workflowId?: string; workflowId?: string;
workflowName: string; workflowName: string;
nodeType?: string; nodeType?: string;

View File

@@ -561,6 +561,8 @@ describe('LogStreamingEventRelay', () => {
executionId: 'exec456', executionId: 'exec456',
nodeName: 'HTTP Request', nodeName: 'HTTP Request',
workflow, workflow,
nodeId: 'node2',
nodeType: 'n8n-nodes-base.httpRequest',
}; };
eventService.emit('node-pre-execute', event); eventService.emit('node-pre-execute', event);
@@ -573,6 +575,7 @@ describe('LogStreamingEventRelay', () => {
workflowId: 'wf303', workflowId: 'wf303',
workflowName: 'Test Workflow with Nodes', workflowName: 'Test Workflow with Nodes',
nodeType: 'n8n-nodes-base.httpRequest', nodeType: 'n8n-nodes-base.httpRequest',
nodeId: 'node2',
}, },
}); });
}); });
@@ -606,6 +609,8 @@ describe('LogStreamingEventRelay', () => {
executionId: 'exec789', executionId: 'exec789',
nodeName: 'HTTP Response', nodeName: 'HTTP Response',
workflow, workflow,
nodeId: 'node2',
nodeType: 'n8n-nodes-base.httpResponse',
}; };
eventService.emit('node-post-execute', event); eventService.emit('node-post-execute', event);
@@ -618,6 +623,7 @@ describe('LogStreamingEventRelay', () => {
workflowId: 'wf404', workflowId: 'wf404',
workflowName: 'Test Workflow with Completed Node', workflowName: 'Test Workflow with Completed Node',
nodeType: 'n8n-nodes-base.httpResponse', nodeType: 'n8n-nodes-base.httpResponse',
nodeId: 'node2',
}, },
}); });
}); });

View File

@@ -111,13 +111,17 @@ export type RelayEventMap = {
'node-pre-execute': { 'node-pre-execute': {
executionId: string; executionId: string;
workflow: IWorkflowBase; workflow: IWorkflowBase;
nodeId?: string;
nodeName: string; nodeName: string;
nodeType?: string;
}; };
'node-post-execute': { 'node-post-execute': {
executionId: string; executionId: string;
workflow: IWorkflowBase; workflow: IWorkflowBase;
nodeId?: string;
nodeName: string; nodeName: string;
nodeType?: string;
}; };
// #endregion // #endregion

View File

@@ -180,28 +180,42 @@ export class LogStreamingEventRelay extends EventRelay {
// #region Node // #region Node
private nodePreExecute({ workflow, executionId, nodeName }: RelayEventMap['node-pre-execute']) { private nodePreExecute({
workflow,
executionId,
nodeId,
nodeName,
nodeType,
}: RelayEventMap['node-pre-execute']) {
void this.eventBus.sendNodeEvent({ void this.eventBus.sendNodeEvent({
eventName: 'n8n.node.started', eventName: 'n8n.node.started',
payload: { payload: {
workflowId: workflow.id, workflowId: workflow.id,
workflowName: workflow.name, workflowName: workflow.name,
executionId, executionId,
nodeType: workflow.nodes.find((n) => n.name === nodeName)?.type, nodeType,
nodeName, nodeName,
nodeId,
}, },
}); });
} }
private nodePostExecute({ workflow, executionId, nodeName }: RelayEventMap['node-post-execute']) { private nodePostExecute({
workflow,
executionId,
nodeType,
nodeName,
nodeId,
}: RelayEventMap['node-post-execute']) {
void this.eventBus.sendNodeEvent({ void this.eventBus.sendNodeEvent({
eventName: 'n8n.node.finished', eventName: 'n8n.node.finished',
payload: { payload: {
workflowId: workflow.id, workflowId: workflow.id,
workflowName: workflow.name, workflowName: workflow.name,
executionId, executionId,
nodeType: workflow.nodes.find((n) => n.name === nodeName)?.type, nodeType,
nodeName, nodeName,
nodeId,
}, },
}); });
} }

View File

@@ -54,6 +54,8 @@ describe('Execution Lifecycle Hooks', () => {
const workflowExecutionService = mockInstance(WorkflowExecutionService); const workflowExecutionService = mockInstance(WorkflowExecutionService);
const nodeName = 'Test Node'; const nodeName = 'Test Node';
const nodeType = 'n8n-nodes-base.testNode';
const nodeId = 'test-node-id';
const node = mock<INode>(); const node = mock<INode>();
const workflowId = 'test-workflow-id'; const workflowId = 'test-workflow-id';
const executionId = 'test-execution-id'; const executionId = 'test-execution-id';
@@ -63,7 +65,16 @@ describe('Execution Lifecycle Hooks', () => {
active: true, active: true,
isArchived: false, isArchived: false,
connections: {}, connections: {},
nodes: [], nodes: [
{
id: nodeId,
name: nodeName,
type: nodeType,
typeVersion: 1,
position: [100, 200],
parameters: {},
},
],
settings: {}, settings: {},
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
@@ -155,6 +166,8 @@ describe('Execution Lifecycle Hooks', () => {
executionId, executionId,
workflow: workflowData, workflow: workflowData,
nodeName, nodeName,
nodeType,
nodeId,
}); });
}); });
}); });
@@ -167,6 +180,8 @@ describe('Execution Lifecycle Hooks', () => {
executionId, executionId,
workflow: workflowData, workflow: workflowData,
nodeName, nodeName,
nodeType,
nodeId,
}); });
}); });
}); });

View File

@@ -52,11 +52,27 @@ function hookFunctionsNodeEvents(hooks: ExecutionLifecycleHooks) {
const eventService = Container.get(EventService); const eventService = Container.get(EventService);
hooks.addHandler('nodeExecuteBefore', function (nodeName) { hooks.addHandler('nodeExecuteBefore', function (nodeName) {
const { executionId, workflowData: workflow } = this; const { executionId, workflowData: workflow } = this;
eventService.emit('node-pre-execute', { executionId, workflow, nodeName }); const node = workflow.nodes.find((n) => n.name === nodeName);
eventService.emit('node-pre-execute', {
executionId,
workflow,
nodeId: node?.id,
nodeName,
nodeType: node?.type,
});
}); });
hooks.addHandler('nodeExecuteAfter', function (nodeName) { hooks.addHandler('nodeExecuteAfter', function (nodeName) {
const { executionId, workflowData: workflow } = this; const { executionId, workflowData: workflow } = this;
eventService.emit('node-post-execute', { executionId, workflow, nodeName }); const node = workflow.nodes.find((n) => n.name === nodeName);
eventService.emit('node-post-execute', {
executionId,
workflow,
nodeId: node?.id,
nodeName,
nodeType: node?.type,
});
}); });
} }

View File

@@ -323,6 +323,7 @@ describe('ExecutionRecoveryService', () => {
workflowName: workflow.name, workflowName: workflow.name,
nodeName: 'DebugHelper', nodeName: 'DebugHelper',
nodeType: 'n8n-nodes-base.debugHelper', nodeType: 'n8n-nodes-base.debugHelper',
nodeId: '123',
}, },
}), }),
); );

View File

@@ -15,6 +15,7 @@ export const setupMessages = (executionId: string, workflowName: string): EventM
workflowName, workflowName,
nodeName: 'When clicking "Execute workflow"', nodeName: 'When clicking "Execute workflow"',
nodeType: 'n8n-nodes-base.manualTrigger', nodeType: 'n8n-nodes-base.manualTrigger',
nodeId: '123',
}, },
}), }),
new EventMessageNode({ new EventMessageNode({
@@ -24,6 +25,7 @@ export const setupMessages = (executionId: string, workflowName: string): EventM
workflowName, workflowName,
nodeName: 'When clicking "Execute workflow"', nodeName: 'When clicking "Execute workflow"',
nodeType: 'n8n-nodes-base.manualTrigger', nodeType: 'n8n-nodes-base.manualTrigger',
nodeId: '123',
}, },
}), }),
new EventMessageNode({ new EventMessageNode({
@@ -33,6 +35,7 @@ export const setupMessages = (executionId: string, workflowName: string): EventM
workflowName, workflowName,
nodeName: 'DebugHelper', nodeName: 'DebugHelper',
nodeType: 'n8n-nodes-base.debugHelper', nodeType: 'n8n-nodes-base.debugHelper',
nodeId: '123',
}, },
}), }),
]; ];