mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-21 11:49:59 +00:00
✨ Introduce telemetry (#2099)
* introduce analytics * add user survey backend * add user survey backend * set answers on survey submit Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> * change name to personalization * lint Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> * N8n 2495 add personalization modal (#2280) * update modals * add onboarding modal * implement questions * introduce analytics * simplify impl * implement survey handling * add personalized cateogry * update modal behavior * add thank you view * handle empty cases * rename modal * standarize modal names * update image, add tags to headings * remove unused file * remove unused interfaces * clean up footer spacing * introduce analytics * refactor to fix bug * update endpoint * set min height * update stories * update naming from questions to survey * remove spacing after core categories * fix bug in logic * sort nodes * rename types * merge with be * rename userSurvey * clean up rest api * use constants for keys * use survey keys * clean up types * move personalization to its own file Co-authored-by: ahsan-virani <ahsan.virani@gmail.com> * Survey new options (#2300) * split up options * fix quotes * remove unused import * add user created workflow event (#2301) * simplify env vars * fix versionCli on FE * update personalization env * fix event User opened Credentials panel * fix select modal spacing * fix nodes panel event * fix workflow id in workflow execute event * improve telemetry error logging * fix config and stop process events * add flush call on n8n stop * ready for release * improve telemetry process exit * fix merge * improve n8n stop events Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> Co-authored-by: Mutasem <mutdmour@gmail.com> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
105
packages/cli/src/InternalHooks.ts
Normal file
105
packages/cli/src/InternalHooks.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/* eslint-disable import/no-cycle */
|
||||
import { IDataObject, IRun, TelemetryHelpers } from 'n8n-workflow';
|
||||
import {
|
||||
IDiagnosticInfo,
|
||||
IInternalHooksClass,
|
||||
IPersonalizationSurveyAnswers,
|
||||
IWorkflowBase,
|
||||
} from '.';
|
||||
import { Telemetry } from './telemetry';
|
||||
|
||||
export class InternalHooksClass implements IInternalHooksClass {
|
||||
constructor(private telemetry: Telemetry) {}
|
||||
|
||||
async onServerStarted(diagnosticInfo: IDiagnosticInfo): Promise<void> {
|
||||
const info = {
|
||||
version_cli: diagnosticInfo.versionCli,
|
||||
db_type: diagnosticInfo.databaseType,
|
||||
n8n_version_notifications_enabled: diagnosticInfo.notificationsEnabled,
|
||||
n8n_disable_production_main_process: diagnosticInfo.disableProductionWebhooksOnMainProcess,
|
||||
n8n_basic_auth_active: diagnosticInfo.basicAuthActive,
|
||||
system_info: diagnosticInfo.systemInfo,
|
||||
execution_variables: diagnosticInfo.executionVariables,
|
||||
n8n_deployment_type: diagnosticInfo.deploymentType,
|
||||
};
|
||||
await this.telemetry.identify(info);
|
||||
await this.telemetry.track('Instance started', info);
|
||||
}
|
||||
|
||||
async onPersonalizationSurveySubmitted(answers: IPersonalizationSurveyAnswers): Promise<void> {
|
||||
await this.telemetry.track('User responded to personalization questions', {
|
||||
company_size: answers.companySize,
|
||||
coding_skill: answers.codingSkill,
|
||||
work_area: answers.workArea,
|
||||
other_work_area: answers.otherWorkArea,
|
||||
});
|
||||
}
|
||||
|
||||
async onWorkflowCreated(workflow: IWorkflowBase): Promise<void> {
|
||||
await this.telemetry.track('User created workflow', {
|
||||
workflow_id: workflow.id,
|
||||
node_graph: TelemetryHelpers.generateNodesGraph(workflow).nodeGraph,
|
||||
});
|
||||
}
|
||||
|
||||
async onWorkflowDeleted(workflowId: string): Promise<void> {
|
||||
await this.telemetry.track('User deleted workflow', {
|
||||
workflow_id: workflowId,
|
||||
});
|
||||
}
|
||||
|
||||
async onWorkflowSaved(workflow: IWorkflowBase): Promise<void> {
|
||||
await this.telemetry.track('User saved workflow', {
|
||||
workflow_id: workflow.id,
|
||||
node_graph: TelemetryHelpers.generateNodesGraph(workflow).nodeGraph,
|
||||
});
|
||||
}
|
||||
|
||||
async onWorkflowPostExecute(workflow: IWorkflowBase, runData?: IRun): Promise<void> {
|
||||
const properties: IDataObject = {
|
||||
workflow_id: workflow.id,
|
||||
is_manual: false,
|
||||
};
|
||||
|
||||
if (runData !== undefined) {
|
||||
properties.execution_mode = runData.mode;
|
||||
if (runData.mode === 'manual') {
|
||||
properties.is_manual = true;
|
||||
}
|
||||
|
||||
properties.success = !!runData.finished;
|
||||
|
||||
if (!properties.success && runData?.data.resultData.error) {
|
||||
properties.error_message = runData?.data.resultData.error.message;
|
||||
let errorNodeName = runData?.data.resultData.error.node?.name;
|
||||
properties.error_node_type = runData?.data.resultData.error.node?.type;
|
||||
|
||||
if (runData.data.resultData.lastNodeExecuted) {
|
||||
const lastNode = TelemetryHelpers.getNodeTypeForName(
|
||||
workflow,
|
||||
runData.data.resultData.lastNodeExecuted,
|
||||
);
|
||||
|
||||
if (lastNode !== undefined) {
|
||||
properties.error_node_type = lastNode.type;
|
||||
errorNodeName = lastNode.name;
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.is_manual) {
|
||||
const nodeGraphResult = TelemetryHelpers.generateNodesGraph(workflow);
|
||||
properties.node_graph = nodeGraphResult.nodeGraph;
|
||||
if (errorNodeName) {
|
||||
properties.error_node_id = nodeGraphResult.nameIndices[errorNodeName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void this.telemetry.trackWorkflowExecution(properties);
|
||||
}
|
||||
|
||||
async onN8nStop(): Promise<void> {
|
||||
await this.telemetry.trackN8nStop();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user