mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-15 17:14:05 -08:00
1e42effc3a
* introduce binary data management
* merge fixes
* fixes
* init binary data manager for other modes
* improve binary manager
* improve binary manager
* delete binary data on executions delete
* lazy delete non-saved executions binary data
* merge fixes + error handing
* improve structure
* leftovers and cleanups
* formatting
* fix config description
* fixes
* fix races
* duplicate binary data for execute workflow node
* clean up and cr
* update mode name, add binary mode to diagnostics
* update mode name, add prefix to filename
* update filename
* allow multiple modes, backward compatibility
* improve file and id naming
* use execution id for binary data storage
* delete binary data by execution id
* add meta for persisted binary data
* delete marked persisted files
* mark deletion by executionid
* add env var for persisted binary data ttl
* improvements
* lint fix
* fix env var description
* cleanup
* cleanup
* ⚡ Minor improvements
Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
145 lines
4.3 KiB
TypeScript
145 lines
4.3 KiB
TypeScript
/* eslint-disable import/no-cycle */
|
|
import { BinaryDataManager } from 'n8n-core';
|
|
import { IDataObject, IRun, TelemetryHelpers } from 'n8n-workflow';
|
|
import {
|
|
IDiagnosticInfo,
|
|
IInternalHooksClass,
|
|
IPersonalizationSurveyAnswers,
|
|
IWorkflowBase,
|
|
} from '.';
|
|
import { Telemetry } from './telemetry';
|
|
|
|
export class InternalHooksClass implements IInternalHooksClass {
|
|
private versionCli: string;
|
|
|
|
constructor(private telemetry: Telemetry, versionCli: string) {
|
|
this.versionCli = versionCli;
|
|
}
|
|
|
|
async onServerStarted(
|
|
diagnosticInfo: IDiagnosticInfo,
|
|
earliestWorkflowCreatedAt?: Date,
|
|
): Promise<unknown[]> {
|
|
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,
|
|
n8n_binary_data_mode: diagnosticInfo.binaryDataMode,
|
|
};
|
|
|
|
return Promise.all([
|
|
this.telemetry.identify(info),
|
|
this.telemetry.track('Instance started', {
|
|
...info,
|
|
earliest_workflow_created: earliestWorkflowCreatedAt,
|
|
}),
|
|
]);
|
|
}
|
|
|
|
async onPersonalizationSurveySubmitted(answers: IPersonalizationSurveyAnswers): Promise<void> {
|
|
return 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,
|
|
company_industry: answers.companyIndustry,
|
|
other_company_industry: answers.otherCompanyIndustry,
|
|
});
|
|
}
|
|
|
|
async onWorkflowCreated(workflow: IWorkflowBase): Promise<void> {
|
|
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow);
|
|
return this.telemetry.track('User created workflow', {
|
|
workflow_id: workflow.id,
|
|
node_graph: nodeGraph,
|
|
node_graph_string: JSON.stringify(nodeGraph),
|
|
});
|
|
}
|
|
|
|
async onWorkflowDeleted(workflowId: string): Promise<void> {
|
|
return this.telemetry.track('User deleted workflow', {
|
|
workflow_id: workflowId,
|
|
});
|
|
}
|
|
|
|
async onWorkflowSaved(workflow: IWorkflowBase): Promise<void> {
|
|
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow);
|
|
|
|
return this.telemetry.track('User saved workflow', {
|
|
workflow_id: workflow.id,
|
|
node_graph: nodeGraph,
|
|
node_graph_string: JSON.stringify(nodeGraph),
|
|
version_cli: this.versionCli,
|
|
});
|
|
}
|
|
|
|
async onWorkflowPostExecute(
|
|
executionId: string,
|
|
workflow: IWorkflowBase,
|
|
runData?: IRun,
|
|
): Promise<void> {
|
|
const properties: IDataObject = {
|
|
workflow_id: workflow.id,
|
|
is_manual: false,
|
|
version_cli: this.versionCli,
|
|
};
|
|
|
|
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;
|
|
properties.node_graph_string = JSON.stringify(nodeGraphResult.nodeGraph);
|
|
|
|
if (errorNodeName) {
|
|
properties.error_node_id = nodeGraphResult.nameIndices[errorNodeName];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Promise.all([
|
|
BinaryDataManager.getInstance().persistBinaryDataForExecutionId(executionId),
|
|
this.telemetry.trackWorkflowExecution(properties),
|
|
]).then(() => {});
|
|
}
|
|
|
|
async onN8nStop(): Promise<void> {
|
|
const timeoutPromise = new Promise<void>((resolve) => {
|
|
setTimeout(() => {
|
|
resolve();
|
|
}, 3000);
|
|
});
|
|
|
|
return Promise.race([timeoutPromise, this.telemetry.trackN8nStop()]);
|
|
}
|
|
}
|