From 0667831f413c08503a9099e4cdd05818937ab5f6 Mon Sep 17 00:00:00 2001 From: Tomi Turtiainen <10324676+tomi@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:49:41 +0300 Subject: [PATCH] fix(core): Flush instance stopped event immediately (#10238) --- packages/cli/src/InternalHooks.ts | 171 +++++++----------- .../handlers/executions/executions.handler.ts | 4 +- .../v1/handlers/users/users.handler.ee.ts | 4 +- .../handlers/workflows/workflows.handler.ts | 6 +- .../email/UserManagementMailer.ts | 8 +- packages/cli/src/auth/methods/ldap.ts | 2 +- .../concurrency-control.service.ts | 2 +- .../cli/src/controllers/auth.controller.ts | 2 +- .../communityPackages.controller.ts | 2 - .../src/controllers/invitation.controller.ts | 2 +- packages/cli/src/controllers/me.controller.ts | 6 +- .../cli/src/controllers/owner.controller.ts | 2 +- .../controllers/passwordReset.controller.ts | 12 +- .../cli/src/controllers/users.controller.ts | 4 +- packages/cli/src/services/frontend.service.ts | 2 +- packages/cli/src/services/user.service.ts | 6 +- packages/cli/src/telemetry/index.ts | 118 ++++++------ .../telemetry-event-relay.service.ts | 64 ++++--- .../cli/src/workflows/workflow.service.ts | 2 +- .../cli/src/workflows/workflows.controller.ts | 4 +- packages/cli/test/unit/Telemetry.test.ts | 76 ++++---- 21 files changed, 224 insertions(+), 275 deletions(-) diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index e6418743d7b1a..dedfb46b0cb3f 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -43,13 +43,11 @@ export class InternalHooks { private readonly projectRelationRepository: ProjectRelationRepository, private readonly _eventBus: MessageEventBus, // needed until we decouple telemetry ) { - workflowStatisticsService.on( - 'telemetry.onFirstProductionWorkflowSuccess', - async (metrics) => await this.onFirstProductionWorkflowSuccess(metrics), + workflowStatisticsService.on('telemetry.onFirstProductionWorkflowSuccess', (metrics) => + this.onFirstProductionWorkflowSuccess(metrics), ); - workflowStatisticsService.on( - 'telemetry.onFirstWorkflowDataLoad', - async (metrics) => await this.onFirstWorkflowDataLoad(metrics), + workflowStatisticsService.on('telemetry.onFirstWorkflowDataLoad', (metrics) => + this.onFirstWorkflowDataLoad(metrics), ); } @@ -57,35 +55,29 @@ export class InternalHooks { await this.telemetry.init(); } - async onFrontendSettingsAPI(pushRef?: string): Promise { - return await this.telemetry.track('Session started', { session_id: pushRef }); + onFrontendSettingsAPI(pushRef?: string): void { + this.telemetry.track('Session started', { session_id: pushRef }); } - async onPersonalizationSurveySubmitted( - userId: string, - answers: Record, - ): Promise { + onPersonalizationSurveySubmitted(userId: string, answers: Record): void { const camelCaseKeys = Object.keys(answers); const personalizationSurveyData = { user_id: userId } as Record; camelCaseKeys.forEach((camelCaseKey) => { personalizationSurveyData[snakeCase(camelCaseKey)] = answers[camelCaseKey]; }); - return await this.telemetry.track( - 'User responded to personalization questions', - personalizationSurveyData, - ); + this.telemetry.track('User responded to personalization questions', personalizationSurveyData); } - async onWorkflowCreated( + onWorkflowCreated( user: User, workflow: IWorkflowBase, project: Project, publicApi: boolean, - ): Promise { + ): void { const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes); - void this.telemetry.track('User created workflow', { + this.telemetry.track('User created workflow', { user_id: user.id, workflow_id: workflow.id, node_graph_string: JSON.stringify(nodeGraph), @@ -95,8 +87,8 @@ export class InternalHooks { }); } - async onWorkflowDeleted(user: User, workflowId: string, publicApi: boolean): Promise { - void this.telemetry.track('User deleted workflow', { + onWorkflowDeleted(user: User, workflowId: string, publicApi: boolean): void { + this.telemetry.track('User deleted workflow', { user_id: user.id, workflow_id: workflowId, public_api: publicApi, @@ -136,7 +128,7 @@ export class InternalHooks { (note) => note.overlapping, ).length; - void this.telemetry.track('User saved workflow', { + this.telemetry.track('User saved workflow', { user_id: user.id, workflow_id: workflow.id, node_graph_string: JSON.stringify(nodeGraph), @@ -155,7 +147,7 @@ export class InternalHooks { workflow: IWorkflowBase, runData?: IRun, userId?: string, - ): Promise { + ) { if (!workflow.id) { return; } @@ -165,8 +157,6 @@ export class InternalHooks { return; } - const promises = []; - const telemetryProperties: IExecutionTrackProperties = { workflow_id: workflow.id, is_manual: false, @@ -270,7 +260,7 @@ export class InternalHooks { node_id: nodeGraphResult.nameIndices[runData.data.startData?.destinationNode], }; - promises.push(this.telemetry.track('Manual node exec finished', telemetryPayload)); + this.telemetry.track('Manual node exec finished', telemetryPayload); } else { nodeGraphResult.webhookNodeNames.forEach((name: string) => { const execJson = runData.data.resultData.runData[name]?.[0]?.data?.main?.[0]?.[0] @@ -282,56 +272,52 @@ export class InternalHooks { } }); - promises.push( - this.telemetry.track('Manual workflow exec finished', manualExecEventProperties), - ); + this.telemetry.track('Manual workflow exec finished', manualExecEventProperties); } } } - void Promise.all([...promises, this.telemetry.trackWorkflowExecution(telemetryProperties)]); + this.telemetry.trackWorkflowExecution(telemetryProperties); } - async onWorkflowSharingUpdate(workflowId: string, userId: string, userList: string[]) { + onWorkflowSharingUpdate(workflowId: string, userId: string, userList: string[]) { const properties: ITelemetryTrackProperties = { workflow_id: workflowId, user_id_sharer: userId, user_id_list: userList, }; - return await this.telemetry.track('User updated workflow sharing', properties); + this.telemetry.track('User updated workflow sharing', properties); } async onN8nStop(): Promise { const timeoutPromise = new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, 3000); + setTimeout(resolve, 3000); }); return await Promise.race([timeoutPromise, this.telemetry.trackN8nStop()]); } - async onUserDeletion(userDeletionData: { + onUserDeletion(userDeletionData: { user: User; telemetryData: ITelemetryUserDeletionData; publicApi: boolean; - }): Promise { - void this.telemetry.track('User deleted user', { + }) { + this.telemetry.track('User deleted user', { ...userDeletionData.telemetryData, user_id: userDeletionData.user.id, public_api: userDeletionData.publicApi, }); } - async onUserInvite(userInviteData: { + onUserInvite(userInviteData: { user: User; target_user_id: string[]; public_api: boolean; email_sent: boolean; invitee_role: string; - }): Promise { - void this.telemetry.track('User invited new user', { + }) { + this.telemetry.track('User invited new user', { user_id: userInviteData.user.id, target_user_id: userInviteData.target_user_id, public_api: userInviteData.public_api, @@ -340,7 +326,7 @@ export class InternalHooks { }); } - async onUserRoleChange(userRoleChangeData: { + onUserRoleChange(userRoleChangeData: { user: User; target_user_id: string; public_api: boolean; @@ -348,74 +334,53 @@ export class InternalHooks { }) { const { user, ...rest } = userRoleChangeData; - void this.telemetry.track('User changed role', { user_id: user.id, ...rest }); + this.telemetry.track('User changed role', { user_id: user.id, ...rest }); } - async onUserRetrievedUser(userRetrievedData: { - user_id: string; - public_api: boolean; - }): Promise { - return await this.telemetry.track('User retrieved user', userRetrievedData); + onUserRetrievedUser(userRetrievedData: { user_id: string; public_api: boolean }) { + this.telemetry.track('User retrieved user', userRetrievedData); } - async onUserRetrievedAllUsers(userRetrievedData: { - user_id: string; - public_api: boolean; - }): Promise { - return await this.telemetry.track('User retrieved all users', userRetrievedData); + onUserRetrievedAllUsers(userRetrievedData: { user_id: string; public_api: boolean }) { + this.telemetry.track('User retrieved all users', userRetrievedData); } - async onUserRetrievedExecution(userRetrievedData: { - user_id: string; - public_api: boolean; - }): Promise { - return await this.telemetry.track('User retrieved execution', userRetrievedData); + onUserRetrievedExecution(userRetrievedData: { user_id: string; public_api: boolean }) { + this.telemetry.track('User retrieved execution', userRetrievedData); } - async onUserRetrievedAllExecutions(userRetrievedData: { - user_id: string; - public_api: boolean; - }): Promise { - return await this.telemetry.track('User retrieved all executions', userRetrievedData); + onUserRetrievedAllExecutions(userRetrievedData: { user_id: string; public_api: boolean }) { + this.telemetry.track('User retrieved all executions', userRetrievedData); } - async onUserRetrievedWorkflow(userRetrievedData: { - user_id: string; - public_api: boolean; - }): Promise { - return await this.telemetry.track('User retrieved workflow', userRetrievedData); + onUserRetrievedWorkflow(userRetrievedData: { user_id: string; public_api: boolean }) { + this.telemetry.track('User retrieved workflow', userRetrievedData); } - async onUserRetrievedAllWorkflows(userRetrievedData: { - user_id: string; - public_api: boolean; - }): Promise { - return await this.telemetry.track('User retrieved all workflows', userRetrievedData); + onUserRetrievedAllWorkflows(userRetrievedData: { user_id: string; public_api: boolean }) { + this.telemetry.track('User retrieved all workflows', userRetrievedData); } - async onUserUpdate(userUpdateData: { user: User; fields_changed: string[] }): Promise { - void this.telemetry.track('User changed personal settings', { + onUserUpdate(userUpdateData: { user: User; fields_changed: string[] }) { + this.telemetry.track('User changed personal settings', { user_id: userUpdateData.user.id, fields_changed: userUpdateData.fields_changed, }); } - async onUserInviteEmailClick(userInviteClickData: { - inviter: User; - invitee: User; - }): Promise { - void this.telemetry.track('User clicked invite link from email', { + onUserInviteEmailClick(userInviteClickData: { inviter: User; invitee: User }) { + this.telemetry.track('User clicked invite link from email', { user_id: userInviteClickData.invitee.id, }); } - async onUserPasswordResetEmailClick(userPasswordResetData: { user: User }): Promise { - void this.telemetry.track('User clicked password reset link from email', { + onUserPasswordResetEmailClick(userPasswordResetData: { user: User }) { + this.telemetry.track('User clicked password reset link from email', { user_id: userPasswordResetData.user.id, }); } - async onUserTransactionalEmail(userTransactionalEmailData: { + onUserTransactionalEmail(userTransactionalEmailData: { user_id: string; message_type: | 'Reset password' @@ -424,37 +389,34 @@ export class InternalHooks { | 'Workflow shared' | 'Credentials shared'; public_api: boolean; - }): Promise { - return await this.telemetry.track( - 'Instance sent transactional email to user', - userTransactionalEmailData, - ); + }) { + this.telemetry.track('Instance sent transactional email to user', userTransactionalEmailData); } - async onUserPasswordResetRequestClick(userPasswordResetData: { user: User }): Promise { - void this.telemetry.track('User requested password reset while logged out', { + onUserPasswordResetRequestClick(userPasswordResetData: { user: User }) { + this.telemetry.track('User requested password reset while logged out', { user_id: userPasswordResetData.user.id, }); } - async onInstanceOwnerSetup(instanceOwnerSetupData: { user_id: string }): Promise { - return await this.telemetry.track('Owner finished instance setup', instanceOwnerSetupData); + onInstanceOwnerSetup(instanceOwnerSetupData: { user_id: string }) { + this.telemetry.track('Owner finished instance setup', instanceOwnerSetupData); } - async onUserSignup( + onUserSignup( user: User, userSignupData: { user_type: AuthProviderType; was_disabled_ldap_user: boolean; }, - ): Promise { - void this.telemetry.track('User signed up', { + ) { + this.telemetry.track('User signed up', { user_id: user.id, ...userSignupData, }); } - async onEmailFailed(failedEmailData: { + onEmailFailed(failedEmailData: { user: User; message_type: | 'Reset password' @@ -463,8 +425,8 @@ export class InternalHooks { | 'Workflow shared' | 'Credentials shared'; public_api: boolean; - }): Promise { - void this.telemetry.track('Instance failed to send transactional email to user', { + }) { + this.telemetry.track('Instance failed to send transactional email to user', { user_id: failedEmailData.user.id, }); } @@ -472,21 +434,18 @@ export class InternalHooks { /* * Execution Statistics */ - async onFirstProductionWorkflowSuccess(data: { - user_id: string; - workflow_id: string; - }): Promise { - return await this.telemetry.track('Workflow first prod success', data); + onFirstProductionWorkflowSuccess(data: { user_id: string; workflow_id: string }) { + this.telemetry.track('Workflow first prod success', data); } - async onFirstWorkflowDataLoad(data: { + onFirstWorkflowDataLoad(data: { user_id: string; workflow_id: string; node_type: string; node_id: string; credential_type?: string; credential_id?: string; - }): Promise { - return await this.telemetry.track('Workflow first data fetched', data); + }) { + this.telemetry.track('Workflow first data fetched', data); } } diff --git a/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts b/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts index cd936d1d1cec1..16ca8093cb325 100644 --- a/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts +++ b/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts @@ -78,7 +78,7 @@ export = { return res.status(404).json({ message: 'Not Found' }); } - void Container.get(InternalHooks).onUserRetrievedExecution({ + Container.get(InternalHooks).onUserRetrievedExecution({ user_id: req.user.id, public_api: true, }); @@ -129,7 +129,7 @@ export = { const count = await Container.get(ExecutionRepository).getExecutionsCountForPublicApi(filters); - void Container.get(InternalHooks).onUserRetrievedAllExecutions({ + Container.get(InternalHooks).onUserRetrievedAllExecutions({ user_id: req.user.id, public_api: true, }); diff --git a/packages/cli/src/PublicApi/v1/handlers/users/users.handler.ee.ts b/packages/cli/src/PublicApi/v1/handlers/users/users.handler.ee.ts index 96b2d57239c57..0df22ec4aa9ef 100644 --- a/packages/cli/src/PublicApi/v1/handlers/users/users.handler.ee.ts +++ b/packages/cli/src/PublicApi/v1/handlers/users/users.handler.ee.ts @@ -33,7 +33,7 @@ export = { public_api: true, }; - void Container.get(InternalHooks).onUserRetrievedUser(telemetryData); + Container.get(InternalHooks).onUserRetrievedUser(telemetryData); return res.json(clean(user, { includeRole })); }, @@ -56,7 +56,7 @@ export = { public_api: true, }; - void Container.get(InternalHooks).onUserRetrievedAllUsers(telemetryData); + Container.get(InternalHooks).onUserRetrievedAllUsers(telemetryData); return res.json({ data: clean(users, { includeRole }), diff --git a/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts b/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts index 943d53764daf3..5139cb686fd60 100644 --- a/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts +++ b/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts @@ -58,7 +58,7 @@ export = { ); await Container.get(ExternalHooks).run('workflow.afterCreate', [createdWorkflow]); - void Container.get(InternalHooks).onWorkflowCreated(req.user, createdWorkflow, project, true); + Container.get(InternalHooks).onWorkflowCreated(req.user, createdWorkflow, project, true); Container.get(EventService).emit('workflow-created', { workflow: createdWorkflow, user: req.user, @@ -101,7 +101,7 @@ export = { return res.status(404).json({ message: 'Not Found' }); } - void Container.get(InternalHooks).onUserRetrievedWorkflow({ + Container.get(InternalHooks).onUserRetrievedWorkflow({ user_id: req.user.id, public_api: true, }); @@ -163,7 +163,7 @@ export = { ...(!config.getEnv('workflowTagsDisabled') && { relations: ['tags'] }), }); - void Container.get(InternalHooks).onUserRetrievedAllWorkflows({ + Container.get(InternalHooks).onUserRetrievedAllWorkflows({ user_id: req.user.id, public_api: true, }); diff --git a/packages/cli/src/UserManagement/email/UserManagementMailer.ts b/packages/cli/src/UserManagement/email/UserManagementMailer.ts index 531ce24cd67c4..6d60c3b4907e1 100644 --- a/packages/cli/src/UserManagement/email/UserManagementMailer.ts +++ b/packages/cli/src/UserManagement/email/UserManagementMailer.ts @@ -112,7 +112,7 @@ export class UserManagementMailer { this.logger.info('Sent workflow shared email successfully', { sharerId: sharer.id }); - void Container.get(InternalHooks).onUserTransactionalEmail({ + Container.get(InternalHooks).onUserTransactionalEmail({ user_id: sharer.id, message_type: 'Workflow shared', public_api: false, @@ -120,7 +120,7 @@ export class UserManagementMailer { return result; } catch (e) { - void Container.get(InternalHooks).onEmailFailed({ + Container.get(InternalHooks).onEmailFailed({ user: sharer, message_type: 'Workflow shared', public_api: false, @@ -171,7 +171,7 @@ export class UserManagementMailer { this.logger.info('Sent credentials shared email successfully', { sharerId: sharer.id }); - void Container.get(InternalHooks).onUserTransactionalEmail({ + Container.get(InternalHooks).onUserTransactionalEmail({ user_id: sharer.id, message_type: 'Credentials shared', public_api: false, @@ -179,7 +179,7 @@ export class UserManagementMailer { return result; } catch (e) { - void Container.get(InternalHooks).onEmailFailed({ + Container.get(InternalHooks).onEmailFailed({ user: sharer, message_type: 'Credentials shared', public_api: false, diff --git a/packages/cli/src/auth/methods/ldap.ts b/packages/cli/src/auth/methods/ldap.ts index 09e8f38c87a03..c8946aec9321e 100644 --- a/packages/cli/src/auth/methods/ldap.ts +++ b/packages/cli/src/auth/methods/ldap.ts @@ -51,7 +51,7 @@ export const handleLdapLogin = async ( await updateLdapUserOnLocalDb(identity, ldapAttributesValues); } else { const user = await createLdapUserOnLocalDb(ldapAttributesValues, ldapId); - void Container.get(InternalHooks).onUserSignup(user, { + Container.get(InternalHooks).onUserSignup(user, { user_type: 'ldap', was_disabled_ldap_user: false, }); diff --git a/packages/cli/src/concurrency/concurrency-control.service.ts b/packages/cli/src/concurrency/concurrency-control.service.ts index c562448379fef..50c73fa668b4e 100644 --- a/packages/cli/src/concurrency/concurrency-control.service.ts +++ b/packages/cli/src/concurrency/concurrency-control.service.ts @@ -55,7 +55,7 @@ export class ConcurrencyControlService { this.productionQueue.on('concurrency-check', ({ capacity }) => { if (this.shouldReport(capacity)) { - void this.telemetry.track('User hit concurrency limit', { + this.telemetry.track('User hit concurrency limit', { threshold: CLOUD_TEMP_PRODUCTION_LIMIT - capacity, }); } diff --git a/packages/cli/src/controllers/auth.controller.ts b/packages/cli/src/controllers/auth.controller.ts index 7994221d9db6c..7711d95177e0f 100644 --- a/packages/cli/src/controllers/auth.controller.ts +++ b/packages/cli/src/controllers/auth.controller.ts @@ -179,7 +179,7 @@ export class AuthController { throw new BadRequestError('Invalid request'); } - void this.internalHooks.onUserInviteEmailClick({ inviter, invitee }); + this.internalHooks.onUserInviteEmailClick({ inviter, invitee }); this.eventService.emit('user-invite-email-click', { inviter, invitee }); const { firstName, lastName } = inviter; diff --git a/packages/cli/src/controllers/communityPackages.controller.ts b/packages/cli/src/controllers/communityPackages.controller.ts index b37d3df249ce4..1860e1df86652 100644 --- a/packages/cli/src/controllers/communityPackages.controller.ts +++ b/packages/cli/src/controllers/communityPackages.controller.ts @@ -9,7 +9,6 @@ import { Delete, Get, Middleware, Patch, Post, RestController, GlobalScope } fro import { NodeRequest } from '@/requests'; import type { InstalledPackages } from '@db/entities/InstalledPackages'; import type { CommunityPackages } from '@/Interfaces'; -import { InternalHooks } from '@/InternalHooks'; import { Push } from '@/push'; import { CommunityPackagesService } from '@/services/communityPackages.service'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; @@ -37,7 +36,6 @@ export function isNpmError(error: unknown): error is { code: number; stdout: str export class CommunityPackagesController { constructor( private readonly push: Push, - private readonly internalHooks: InternalHooks, private readonly communityPackagesService: CommunityPackagesService, private readonly eventService: EventService, ) {} diff --git a/packages/cli/src/controllers/invitation.controller.ts b/packages/cli/src/controllers/invitation.controller.ts index d89d077ae61b0..c32bf543002fd 100644 --- a/packages/cli/src/controllers/invitation.controller.ts +++ b/packages/cli/src/controllers/invitation.controller.ts @@ -168,7 +168,7 @@ export class InvitationController { this.authService.issueCookie(res, updatedUser, req.browserId); - void this.internalHooks.onUserSignup(updatedUser, { + this.internalHooks.onUserSignup(updatedUser, { user_type: 'email', was_disabled_ldap_user: false, }); diff --git a/packages/cli/src/controllers/me.controller.ts b/packages/cli/src/controllers/me.controller.ts index 62a2e101ff27d..3f9366b441260 100644 --- a/packages/cli/src/controllers/me.controller.ts +++ b/packages/cli/src/controllers/me.controller.ts @@ -101,7 +101,7 @@ export class MeController { this.authService.issueCookie(res, user, req.browserId); const fieldsChanged = Object.keys(payload); - void this.internalHooks.onUserUpdate({ user, fields_changed: fieldsChanged }); + this.internalHooks.onUserUpdate({ user, fields_changed: fieldsChanged }); this.eventService.emit('user-updated', { user, fieldsChanged }); const publicUser = await this.userService.toPublic(user); @@ -151,7 +151,7 @@ export class MeController { this.authService.issueCookie(res, updatedUser, req.browserId); - void this.internalHooks.onUserUpdate({ user: updatedUser, fields_changed: ['password'] }); + this.internalHooks.onUserUpdate({ user: updatedUser, fields_changed: ['password'] }); this.eventService.emit('user-updated', { user: updatedUser, fieldsChanged: ['password'] }); await this.externalHooks.run('user.password.update', [updatedUser.email, updatedUser.password]); @@ -186,7 +186,7 @@ export class MeController { this.logger.info('User survey updated successfully', { userId: req.user.id }); - void this.internalHooks.onPersonalizationSurveySubmitted(req.user.id, personalizationAnswers); + this.internalHooks.onPersonalizationSurveySubmitted(req.user.id, personalizationAnswers); return { success: true }; } diff --git a/packages/cli/src/controllers/owner.controller.ts b/packages/cli/src/controllers/owner.controller.ts index 6077026c90202..9b86ac41ab313 100644 --- a/packages/cli/src/controllers/owner.controller.ts +++ b/packages/cli/src/controllers/owner.controller.ts @@ -85,7 +85,7 @@ export class OwnerController { this.authService.issueCookie(res, owner, req.browserId); - void this.internalHooks.onInstanceOwnerSetup({ user_id: owner.id }); + this.internalHooks.onInstanceOwnerSetup({ user_id: owner.id }); return await this.userService.toPublic(owner, { posthog: this.postHog, withScopes: true }); } diff --git a/packages/cli/src/controllers/passwordReset.controller.ts b/packages/cli/src/controllers/passwordReset.controller.ts index c548e607fd9d4..e17a0f15efe63 100644 --- a/packages/cli/src/controllers/passwordReset.controller.ts +++ b/packages/cli/src/controllers/passwordReset.controller.ts @@ -120,7 +120,7 @@ export class PasswordResetController { domain: this.urlService.getInstanceBaseUrl(), }); } catch (error) { - void this.internalHooks.onEmailFailed({ + this.internalHooks.onEmailFailed({ user, message_type: 'Reset password', public_api: false, @@ -132,13 +132,13 @@ export class PasswordResetController { } this.logger.info('Sent password reset email successfully', { userId: user.id, email }); - void this.internalHooks.onUserTransactionalEmail({ + this.internalHooks.onUserTransactionalEmail({ user_id: id, message_type: 'Reset password', public_api: false, }); - void this.internalHooks.onUserPasswordResetRequestClick({ user }); + this.internalHooks.onUserPasswordResetRequestClick({ user }); this.eventService.emit('user-password-reset-request-click', { user }); } @@ -171,7 +171,7 @@ export class PasswordResetController { } this.logger.info('Reset-password token resolved successfully', { userId: user.id }); - void this.internalHooks.onUserPasswordResetEmailClick({ user }); + this.internalHooks.onUserPasswordResetEmailClick({ user }); this.eventService.emit('user-password-reset-email-click', { user }); } @@ -215,13 +215,13 @@ export class PasswordResetController { this.authService.issueCookie(res, user, req.browserId); - void this.internalHooks.onUserUpdate({ user, fields_changed: ['password'] }); + this.internalHooks.onUserUpdate({ user, fields_changed: ['password'] }); this.eventService.emit('user-updated', { user, fieldsChanged: ['password'] }); // if this user used to be an LDAP users const ldapIdentity = user?.authIdentities?.find((i) => i.providerType === 'ldap'); if (ldapIdentity) { - void this.internalHooks.onUserSignup(user, { + this.internalHooks.onUserSignup(user, { user_type: 'email', was_disabled_ldap_user: true, }); diff --git a/packages/cli/src/controllers/users.controller.ts b/packages/cli/src/controllers/users.controller.ts index 0fd8481ed8813..f0815aa54d405 100644 --- a/packages/cli/src/controllers/users.controller.ts +++ b/packages/cli/src/controllers/users.controller.ts @@ -253,7 +253,7 @@ export class UsersController { await trx.delete(User, { id: userToDelete.id }); }); - void this.internalHooks.onUserDeletion({ + this.internalHooks.onUserDeletion({ user: req.user, telemetryData, publicApi: false, @@ -294,7 +294,7 @@ export class UsersController { await this.userService.update(targetUser.id, { role: payload.newRoleName }); - void this.internalHooks.onUserRoleChange({ + this.internalHooks.onUserRoleChange({ user: req.user, target_user_id: targetUser.id, target_user_new_role: ['global', payload.newRoleName].join(' '), diff --git a/packages/cli/src/services/frontend.service.ts b/packages/cli/src/services/frontend.service.ts index 918de1793518c..4ada98a9cf7d7 100644 --- a/packages/cli/src/services/frontend.service.ts +++ b/packages/cli/src/services/frontend.service.ts @@ -244,7 +244,7 @@ export class FrontendService { } getSettings(pushRef?: string): IN8nUISettings { - void this.internalHooks.onFrontendSettingsAPI(pushRef); + this.internalHooks.onFrontendSettingsAPI(pushRef); const restEndpoint = config.getEnv('endpoints.rest'); diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index cc50e09f74607..007054c6aa980 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -144,14 +144,14 @@ export class UserService { if (result.emailSent) { invitedUser.user.emailSent = true; delete invitedUser.user?.inviteAcceptUrl; - void Container.get(InternalHooks).onUserTransactionalEmail({ + Container.get(InternalHooks).onUserTransactionalEmail({ user_id: id, message_type: 'New user invite', public_api: false, }); } - void Container.get(InternalHooks).onUserInvite({ + Container.get(InternalHooks).onUserInvite({ user: owner, target_user_id: Object.values(toInviteUsers), public_api: false, @@ -164,7 +164,7 @@ export class UserService { }); } catch (e) { if (e instanceof Error) { - void Container.get(InternalHooks).onEmailFailed({ + Container.get(InternalHooks).onEmailFailed({ user: owner, message_type: 'New user invite', public_api: false, diff --git a/packages/cli/src/telemetry/index.ts b/packages/cli/src/telemetry/index.ts index f63caf9b2c7b6..2d762297304cc 100644 --- a/packages/cli/src/telemetry/index.ts +++ b/packages/cli/src/telemetry/index.ts @@ -88,30 +88,28 @@ export class Telemetry { ); // every 6 hours } - private async pulse(): Promise { + private async pulse() { if (!this.rudderStack) { return; } - const allPromises = Object.keys(this.executionCountsBuffer) - .filter((workflowId) => { - const data = this.executionCountsBuffer[workflowId]; - const sum = - (data.manual_error?.count ?? 0) + - (data.manual_success?.count ?? 0) + - (data.prod_error?.count ?? 0) + - (data.prod_success?.count ?? 0); - return sum > 0; - }) - .map(async (workflowId) => { - const promise = this.track('Workflow execution count', { - event_version: '2', - workflow_id: workflowId, - ...this.executionCountsBuffer[workflowId], - }); - - return await promise; + const workflowIdsToReport = Object.keys(this.executionCountsBuffer).filter((workflowId) => { + const data = this.executionCountsBuffer[workflowId]; + const sum = + (data.manual_error?.count ?? 0) + + (data.manual_success?.count ?? 0) + + (data.prod_error?.count ?? 0) + + (data.prod_success?.count ?? 0); + return sum > 0; + }); + + for (const workflowId of workflowIdsToReport) { + this.track('Workflow execution count', { + event_version: '2', + workflow_id: workflowId, + ...this.executionCountsBuffer[workflowId], }); + } this.executionCountsBuffer = {}; @@ -131,11 +129,11 @@ export class Telemetry { team_projects: (await Container.get(ProjectRepository).getProjectCounts()).team, project_role_count: await Container.get(ProjectRelationRepository).countUsersByRole(), }; - allPromises.push(this.track('pulse', pulsePacket)); - return await Promise.all(allPromises); + + this.track('pulse', pulsePacket); } - async trackWorkflowExecution(properties: IExecutionTrackProperties): Promise { + trackWorkflowExecution(properties: IExecutionTrackProperties) { if (this.rudderStack) { const execTime = new Date(); const workflowId = properties.workflow_id; @@ -164,66 +162,60 @@ export class Telemetry { properties.is_manual && properties.error_node_type?.startsWith('n8n-nodes-base') ) { - void this.track('Workflow execution errored', properties); + this.track('Workflow execution errored', properties); } } } async trackN8nStop(): Promise { clearInterval(this.pulseIntervalReference); - await this.track('User instance stopped'); - void Promise.all([this.postHog.stop(), this.rudderStack?.flush()]); + + this.track('User instance stopped'); + + await Promise.all([this.postHog.stop(), this.rudderStack?.flush()]); } - async identify(traits?: { - [key: string]: string | number | boolean | object | undefined | null; - }): Promise { + identify(traits?: { [key: string]: string | number | boolean | object | undefined | null }) { + if (!this.rudderStack) { + return; + } + const { instanceId } = this.instanceSettings; - return await new Promise((resolve) => { - if (this.rudderStack) { - this.rudderStack.identify( - { - userId: instanceId, - traits: { ...traits, instanceId }, - }, - resolve, - ); - } else { - resolve(); - } + + this.rudderStack.identify({ + userId: instanceId, + traits: { ...traits, instanceId }, }); } - async track( + track( eventName: string, properties: ITelemetryTrackProperties = {}, { withPostHog } = { withPostHog: false }, // whether to additionally track with PostHog - ): Promise { - const { instanceId } = this.instanceSettings; - return await new Promise((resolve) => { - if (this.rudderStack) { - const { user_id } = properties; - const updatedProperties = { - ...properties, - instance_id: instanceId, - version_cli: N8N_VERSION, - }; + ) { + if (!this.rudderStack) { + return; + } - const payload = { - userId: `${instanceId}${user_id ? `#${user_id}` : ''}`, - event: eventName, - properties: updatedProperties, - }; + const { instanceId } = this.instanceSettings; + const { user_id } = properties; + const updatedProperties = { + ...properties, + instance_id: instanceId, + version_cli: N8N_VERSION, + }; - if (withPostHog) { - this.postHog?.track(payload); - } + const payload = { + userId: `${instanceId}${user_id ? `#${user_id}` : ''}`, + event: eventName, + properties: updatedProperties, + }; - return this.rudderStack.track(payload, resolve); - } + if (withPostHog) { + this.postHog?.track(payload); + } - return resolve(); - }); + return this.rudderStack.track(payload); } // test helpers diff --git a/packages/cli/src/telemetry/telemetry-event-relay.service.ts b/packages/cli/src/telemetry/telemetry-event-relay.service.ts index 63c7fe4d11e74..bb1d4b8d560a2 100644 --- a/packages/cli/src/telemetry/telemetry-event-relay.service.ts +++ b/packages/cli/src/telemetry/telemetry-event-relay.service.ts @@ -104,7 +104,7 @@ export class TelemetryEventRelay { } private teamProjectUpdated({ userId, role, members, projectId }: Event['team-project-updated']) { - void this.telemetry.track('Project settings updated', { + this.telemetry.track('Project settings updated', { user_id: userId, role, // eslint-disable-next-line @typescript-eslint/no-shadow @@ -120,7 +120,7 @@ export class TelemetryEventRelay { removalType, targetProjectId, }: Event['team-project-deleted']) { - void this.telemetry.track('User deleted project', { + this.telemetry.track('User deleted project', { user_id: userId, role, project_id: projectId, @@ -130,7 +130,7 @@ export class TelemetryEventRelay { } private teamProjectCreated({ userId, role }: Event['team-project-created']) { - void this.telemetry.track('User created project', { + this.telemetry.track('User created project', { user_id: userId, role, }); @@ -142,7 +142,7 @@ export class TelemetryEventRelay { repoType, connected, }: Event['source-control-settings-updated']) { - void this.telemetry.track('User updated source control settings', { + this.telemetry.track('User updated source control settings', { branch_name: branchName, read_only_instance: readOnlyInstance, repo_type: repoType, @@ -155,7 +155,7 @@ export class TelemetryEventRelay { workflowConflicts, credConflicts, }: Event['source-control-user-started-pull-ui']) { - void this.telemetry.track('User started pull via UI', { + this.telemetry.track('User started pull via UI', { workflow_updates: workflowUpdates, workflow_conflicts: workflowConflicts, cred_conflicts: credConflicts, @@ -165,7 +165,7 @@ export class TelemetryEventRelay { private sourceControlUserFinishedPullUi({ workflowUpdates, }: Event['source-control-user-finished-pull-ui']) { - void this.telemetry.track('User finished pull via UI', { + this.telemetry.track('User finished pull via UI', { workflow_updates: workflowUpdates, }); } @@ -178,7 +178,7 @@ export class TelemetryEventRelay { workflow_updates: workflowUpdates, forced, }); - void this.telemetry.track('User pulled via API', { + this.telemetry.track('User pulled via API', { workflow_updates: workflowUpdates, forced, }); @@ -191,7 +191,7 @@ export class TelemetryEventRelay { credsEligibleWithConflicts, variablesEligible, }: Event['source-control-user-started-push-ui']) { - void this.telemetry.track('User started push via UI', { + this.telemetry.track('User started push via UI', { workflows_eligible: workflowsEligible, workflows_eligible_with_conflicts: workflowsEligibleWithConflicts, creds_eligible: credsEligible, @@ -206,7 +206,7 @@ export class TelemetryEventRelay { credsPushed, variablesPushed, }: Event['source-control-user-finished-push-ui']) { - void this.telemetry.track('User finished push via UI', { + this.telemetry.track('User finished push via UI', { workflows_eligible: workflowsEligible, workflows_pushed: workflowsPushed, creds_pushed: credsPushed, @@ -215,13 +215,13 @@ export class TelemetryEventRelay { } private licenseRenewalAttempted({ success }: Event['license-renewal-attempted']) { - void this.telemetry.track('Instance attempted to refresh license', { + this.telemetry.track('Instance attempted to refresh license', { success, }); } private variableCreated() { - void this.telemetry.track('User created variable'); + this.telemetry.track('User created variable'); } private externalSecretsProviderSettingsSaved({ @@ -231,7 +231,7 @@ export class TelemetryEventRelay { isNew, errorMessage, }: Event['external-secrets-provider-settings-saved']) { - void this.telemetry.track('User updated external secrets settings', { + this.telemetry.track('User updated external secrets settings', { user_id: userId, vault_type: vaultType, is_valid: isValid, @@ -241,7 +241,7 @@ export class TelemetryEventRelay { } private publicApiInvoked({ userId, path, method, apiVersion }: Event['public-api-invoked']) { - void this.telemetry.track('User invoked API', { + this.telemetry.track('User invoked API', { user_id: userId, path, method, @@ -252,7 +252,7 @@ export class TelemetryEventRelay { private publicApiKeyCreated(event: Event['public-api-key-created']) { const { user, publicApi } = event; - void this.telemetry.track('API key created', { + this.telemetry.track('API key created', { user_id: user.id, public_api: publicApi, }); @@ -261,7 +261,7 @@ export class TelemetryEventRelay { private publicApiKeyDeleted(event: Event['public-api-key-deleted']) { const { user, publicApi } = event; - void this.telemetry.track('API key deleted', { + this.telemetry.track('API key deleted', { user_id: user.id, public_api: publicApi, }); @@ -278,7 +278,7 @@ export class TelemetryEventRelay { packageAuthorEmail, failureReason, }: Event['community-package-installed']) { - void this.telemetry.track('cnr package install finished', { + this.telemetry.track('cnr package install finished', { user_id: user.id, input_string: inputString, package_name: packageName, @@ -300,7 +300,7 @@ export class TelemetryEventRelay { packageAuthor, packageAuthorEmail, }: Event['community-package-updated']) { - void this.telemetry.track('cnr package updated', { + this.telemetry.track('cnr package updated', { user_id: user.id, package_name: packageName, package_version_current: packageVersionCurrent, @@ -319,7 +319,7 @@ export class TelemetryEventRelay { packageAuthor, packageAuthorEmail, }: Event['community-package-deleted']) { - void this.telemetry.track('cnr package deleted', { + this.telemetry.track('cnr package deleted', { user_id: user.id, package_name: packageName, package_version: packageVersion, @@ -336,7 +336,7 @@ export class TelemetryEventRelay { projectId, projectType, }: Event['credentials-created']) { - void this.telemetry.track('User created credentials', { + this.telemetry.track('User created credentials', { user_id: user.id, credential_type: credentialType, credential_id: credentialId, @@ -353,7 +353,7 @@ export class TelemetryEventRelay { userIdsShareesAdded, shareesRemoved, }: Event['credentials-shared']) { - void this.telemetry.track('User updated cred sharing', { + this.telemetry.track('User updated cred sharing', { user_id: user.id, credential_type: credentialType, credential_id: credentialId, @@ -364,7 +364,7 @@ export class TelemetryEventRelay { } private credentialsUpdated({ user, credentialId, credentialType }: Event['credentials-updated']) { - void this.telemetry.track('User updated credentials', { + this.telemetry.track('User updated credentials', { user_id: user.id, credential_type: credentialType, credential_id: credentialId, @@ -372,7 +372,7 @@ export class TelemetryEventRelay { } private credentialsDeleted({ user, credentialId, credentialType }: Event['credentials-deleted']) { - void this.telemetry.track('User deleted credentials', { + this.telemetry.track('User deleted credentials', { user_id: user.id, credential_type: credentialType, credential_id: credentialId, @@ -385,7 +385,7 @@ export class TelemetryEventRelay { usersSynced, error, }: Event['ldap-general-sync-finished']) { - void this.telemetry.track('Ldap general sync finished', { + this.telemetry.track('Ldap general sync finished', { type, succeeded, users_synced: usersSynced, @@ -407,7 +407,7 @@ export class TelemetryEventRelay { loginLabel, loginEnabled, }: Event['ldap-settings-updated']) { - void this.telemetry.track('User updated Ldap settings', { + this.telemetry.track('User updated Ldap settings', { user_id: userId, loginIdAttribute, firstNameAttribute, @@ -424,11 +424,11 @@ export class TelemetryEventRelay { } private ldapLoginSyncFailed({ error }: Event['ldap-login-sync-failed']) { - void this.telemetry.track('Ldap login sync failed', { error }); + this.telemetry.track('Ldap login sync failed', { error }); } private loginFailedDueToLdapDisabled({ userId }: Event['login-failed-due-to-ldap-disabled']) { - void this.telemetry.track('User login failed since ldap disabled', { user_ud: userId }); + this.telemetry.track('User login failed since ldap disabled', { user_ud: userId }); } private async serverStarted() { @@ -489,12 +489,10 @@ export class TelemetryEventRelay { where: {}, }); - void Promise.all([ - this.telemetry.identify(info), - this.telemetry.track('Instance started', { - ...info, - earliest_workflow_created: firstWorkflow?.createdAt, - }), - ]); + this.telemetry.identify(info); + this.telemetry.track('Instance started', { + ...info, + earliest_workflow_created: firstWorkflow?.createdAt, + }); } } diff --git a/packages/cli/src/workflows/workflow.service.ts b/packages/cli/src/workflows/workflow.service.ts index cf742acecef2e..7c0cbfc242e1b 100644 --- a/packages/cli/src/workflows/workflow.service.ts +++ b/packages/cli/src/workflows/workflow.service.ts @@ -282,7 +282,7 @@ export class WorkflowService { await this.workflowRepository.delete(workflowId); await this.binaryDataService.deleteMany(idsForDeletion); - void Container.get(InternalHooks).onWorkflowDeleted(user, workflowId, false); + Container.get(InternalHooks).onWorkflowDeleted(user, workflowId, false); this.eventService.emit('workflow-deleted', { user, workflowId }); await this.externalHooks.run('workflow.afterDelete', [workflowId]); diff --git a/packages/cli/src/workflows/workflows.controller.ts b/packages/cli/src/workflows/workflows.controller.ts index d0ec019586279..05863edb84c04 100644 --- a/packages/cli/src/workflows/workflows.controller.ts +++ b/packages/cli/src/workflows/workflows.controller.ts @@ -179,7 +179,7 @@ export class WorkflowsController { delete savedWorkflowWithMetaData.shared; await this.externalHooks.run('workflow.afterCreate', [savedWorkflow]); - void this.internalHooks.onWorkflowCreated(req.user, newWorkflow, project!, false); + this.internalHooks.onWorkflowCreated(req.user, newWorkflow, project!, false); this.eventService.emit('workflow-created', { user: req.user, workflow: newWorkflow }); const scopes = await this.workflowService.getWorkflowScopes(req.user, savedWorkflow.id); @@ -454,7 +454,7 @@ export class WorkflowsController { newShareeIds = toShare; }); - void this.internalHooks.onWorkflowSharingUpdate(workflowId, req.user.id, shareWithIds); + this.internalHooks.onWorkflowSharingUpdate(workflowId, req.user.id, shareWithIds); const projectsRelations = await this.projectRelationRepository.findBy({ projectId: In(newShareeIds), diff --git a/packages/cli/test/unit/Telemetry.test.ts b/packages/cli/test/unit/Telemetry.test.ts index 25f4a808675b0..e055abb1fdb74 100644 --- a/packages/cli/test/unit/Telemetry.test.ts +++ b/packages/cli/test/unit/Telemetry.test.ts @@ -14,11 +14,12 @@ describe('Telemetry', () => { let startPulseSpy: jest.SpyInstance; const spyTrack = jest.spyOn(Telemetry.prototype, 'track').mockName('track'); - const mockRudderStack: Pick = { - flush: (resolve) => resolve?.(), - identify: (data, resolve) => resolve?.(), - track: (data, resolve) => resolve?.(), - }; + const mockRudderStack = mock(); + mockRudderStack.track.mockImplementation(function (_, cb) { + cb?.(); + + return this; + }); let telemetry: Telemetry; const instanceId = 'Telemetry unit test'; @@ -26,9 +27,9 @@ describe('Telemetry', () => { const instanceSettings = mockInstance(InstanceSettings, { instanceId }); beforeAll(() => { - startPulseSpy = jest - .spyOn(Telemetry.prototype as any, 'startPulse') - .mockImplementation(() => {}); + // @ts-expect-error Spying on private method + startPulseSpy = jest.spyOn(Telemetry.prototype, 'startPulse').mockImplementation(() => {}); + jest.useFakeTimers(); jest.setSystemTime(testDateTime); config.set('diagnostics.enabled', true); @@ -49,7 +50,8 @@ describe('Telemetry', () => { await postHog.init(); telemetry = new Telemetry(mock(), postHog, mock(), instanceSettings, mock()); - (telemetry as any).rudderStack = mockRudderStack; + // @ts-expect-error Assigning to private property + telemetry.rudderStack = mockRudderStack; }); afterEach(async () => { @@ -79,30 +81,30 @@ describe('Telemetry', () => { payload.is_manual = true; payload.success = true; const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); fakeJestSystemTime('2022-01-01 12:30:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.is_manual = false; payload.success = true; const execTime2 = fakeJestSystemTime('2022-01-01 13:00:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); fakeJestSystemTime('2022-01-01 12:30:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.is_manual = true; payload.success = false; const execTime3 = fakeJestSystemTime('2022-01-01 14:00:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); fakeJestSystemTime('2022-01-01 12:30:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.is_manual = false; payload.success = false; const execTime4 = fakeJestSystemTime('2022-01-01 15:00:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); fakeJestSystemTime('2022-01-01 12:30:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); expect(spyTrack).toHaveBeenCalledTimes(0); @@ -127,9 +129,9 @@ describe('Telemetry', () => { }; const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); fakeJestSystemTime('2022-01-01 12:30:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); let execBuffer = telemetry.getCountsBuffer(); @@ -140,9 +142,9 @@ describe('Telemetry', () => { payload.error_node_type = 'n8n-nodes-base.node-type'; fakeJestSystemTime('2022-01-01 13:00:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); fakeJestSystemTime('2022-01-01 12:30:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); execBuffer = telemetry.getCountsBuffer(); @@ -163,7 +165,7 @@ describe('Telemetry', () => { // successful execution const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00'); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); expect(spyTrack).toHaveBeenCalledTimes(0); @@ -179,7 +181,7 @@ describe('Telemetry', () => { payload.error_node_type = 'n8n-nodes-base.merge'; payload.workflow_id = '2'; - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); expect(spyTrack).toHaveBeenCalledTimes(0); @@ -198,12 +200,12 @@ describe('Telemetry', () => { payload.error_node_type = 'n8n-nodes-base.merge'; payload.workflow_id = '2'; - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.error_node_type = 'n8n-nodes-base.merge'; payload.workflow_id = '1'; - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); expect(spyTrack).toHaveBeenCalledTimes(0); execBuffer = telemetry.getCountsBuffer(); @@ -225,7 +227,7 @@ describe('Telemetry', () => { const execTime2 = fakeJestSystemTime('2022-01-01 12:00:00'); payload.error_node_type = 'custom-package.custom-node'; payload.success = false; - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); expect(spyTrack).toHaveBeenCalledTimes(0); @@ -249,7 +251,7 @@ describe('Telemetry', () => { payload.success = false; payload.error_node_type = 'n8n-nodes-base.merge'; payload.is_manual = true; - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); expect(spyTrack).toHaveBeenCalledTimes(1); @@ -327,27 +329,27 @@ describe('Telemetry', () => { error_node_type: 'custom-nodes-base.node-type', }; - await telemetry.trackWorkflowExecution(payload); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.is_manual = false; payload.success = true; - await telemetry.trackWorkflowExecution(payload); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.is_manual = true; payload.success = false; - await telemetry.trackWorkflowExecution(payload); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.is_manual = false; payload.success = false; - await telemetry.trackWorkflowExecution(payload); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); payload.workflow_id = '2'; - await telemetry.trackWorkflowExecution(payload); - await telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); + telemetry.trackWorkflowExecution(payload); expect(spyTrack).toHaveBeenCalledTimes(0); expect(pulseSpy).toBeCalledTimes(0);