mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-10 06:34:05 -08:00
🐛 Swallow telemetry error and only log in warn and debug mode (#2858)
* catch nodegraph errors * use loglevel config for telemetry * Use getByNameAndVersion instead of getByName * remove any usage of nodeTypes.getByName method * deprecate getByName method
This commit is contained in:
parent
2b9f3aab1b
commit
8fc1095d1e
|
@ -54,13 +54,6 @@ const mockNodeTypes: INodeTypes = {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return Object.values(this.nodeTypes).map((data) => data.type);
|
return Object.values(this.nodeTypes).map((data) => data.type);
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
getByName(nodeType: string): INodeType | INodeVersionedType | undefined {
|
|
||||||
if (this.nodeTypes[nodeType] === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return this.nodeTypes[nodeType].type;
|
|
||||||
},
|
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType | undefined {
|
getByNameAndVersion(nodeType: string, version?: number): INodeType | undefined {
|
||||||
if (this.nodeTypes[nodeType] === undefined) {
|
if (this.nodeTypes[nodeType] === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -524,7 +517,7 @@ export class CredentialsHelper extends ICredentialsHelper {
|
||||||
nodeType = credentialTestFunction.nodeType;
|
nodeType = credentialTestFunction.nodeType;
|
||||||
} else {
|
} else {
|
||||||
const nodeTypes = NodeTypes();
|
const nodeTypes = NodeTypes();
|
||||||
nodeType = nodeTypes.getByName('n8n-nodes-base.noOp') as INodeType;
|
nodeType = nodeTypes.getByNameAndVersion('n8n-nodes-base.noOp');
|
||||||
}
|
}
|
||||||
|
|
||||||
const node: INode = {
|
const node: INode = {
|
||||||
|
|
|
@ -33,13 +33,6 @@ class NodeTypesClass implements INodeTypes {
|
||||||
return Object.values(this.nodeTypes).map((data) => data.type);
|
return Object.values(this.nodeTypes).map((data) => data.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
getByName(nodeType: string): INodeType | INodeVersionedType | undefined {
|
|
||||||
if (this.nodeTypes[nodeType] === undefined) {
|
|
||||||
throw new Error(`The node-type "${nodeType}" is not known!`);
|
|
||||||
}
|
|
||||||
return this.nodeTypes[nodeType].type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variant of `getByNameAndVersion` that includes the node's source path, used to locate a node's translations.
|
* Variant of `getByNameAndVersion` that includes the node's source path, used to locate a node's translations.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -58,6 +58,7 @@ export class Telemetry {
|
||||||
this.versionCli = versionCli;
|
this.versionCli = versionCli;
|
||||||
|
|
||||||
const enabled = config.get('diagnostics.enabled') as boolean;
|
const enabled = config.get('diagnostics.enabled') as boolean;
|
||||||
|
const logLevel = config.get('logs.level') as boolean;
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
const conf = config.get('diagnostics.config.backend') as string;
|
const conf = config.get('diagnostics.config.backend') as string;
|
||||||
const [key, url] = conf.split(';');
|
const [key, url] = conf.split(';');
|
||||||
|
@ -69,7 +70,7 @@ export class Telemetry {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.client = new TelemetryClient(key, url);
|
this.client = new TelemetryClient(key, url, { logLevel });
|
||||||
|
|
||||||
this.pulseIntervalReference = setInterval(async () => {
|
this.pulseIntervalReference = setInterval(async () => {
|
||||||
void this.pulse();
|
void this.pulse();
|
||||||
|
|
|
@ -24,7 +24,6 @@ import {
|
||||||
IRunExecutionData,
|
IRunExecutionData,
|
||||||
IWorfklowIssues,
|
IWorfklowIssues,
|
||||||
IWorkflowDataProxyAdditionalKeys,
|
IWorkflowDataProxyAdditionalKeys,
|
||||||
TelemetryHelpers,
|
|
||||||
Workflow,
|
Workflow,
|
||||||
NodeHelpers,
|
NodeHelpers,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
@ -224,17 +223,6 @@ export const workflowHelpers = mixins(
|
||||||
// Does not get used in Workflow so no need to return it
|
// Does not get used in Workflow so no need to return it
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
getByName: (nodeType: string): INodeType | INodeVersionedType | undefined => {
|
|
||||||
const nodeTypeDescription = this.$store.getters.nodeType(nodeType) as INodeTypeDescription | null;
|
|
||||||
|
|
||||||
if (nodeTypeDescription === null) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
description: nodeTypeDescription,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getByNameAndVersion: (nodeType: string, version?: number): INodeType | undefined => {
|
getByNameAndVersion: (nodeType: string, version?: number): INodeType | undefined => {
|
||||||
const nodeTypeDescription = this.$store.getters.nodeType(nodeType, version) as INodeTypeDescription | null;
|
const nodeTypeDescription = this.$store.getters.nodeType(nodeType, version) as INodeTypeDescription | null;
|
||||||
|
|
||||||
|
|
|
@ -1193,7 +1193,6 @@ export interface INodeTypes {
|
||||||
nodeTypes: INodeTypeData;
|
nodeTypes: INodeTypeData;
|
||||||
init(nodeTypes?: INodeTypeData): Promise<void>;
|
init(nodeTypes?: INodeTypeData): Promise<void>;
|
||||||
getAll(): Array<INodeType | INodeVersionedType>;
|
getAll(): Array<INodeType | INodeVersionedType>;
|
||||||
getByName(nodeType: string): INodeType | INodeVersionedType | undefined;
|
|
||||||
getByNameAndVersion(nodeType: string, version?: number): INodeType | undefined;
|
getByNameAndVersion(nodeType: string, version?: number): INodeType | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,10 @@ import {
|
||||||
INodesGraphResult,
|
INodesGraphResult,
|
||||||
IWorkflowBase,
|
IWorkflowBase,
|
||||||
INodeTypes,
|
INodeTypes,
|
||||||
INodeType,
|
|
||||||
} from '.';
|
} from '.';
|
||||||
|
|
||||||
|
import { getInstance as getLoggerInstance } from './LoggerProxy';
|
||||||
|
|
||||||
export function getNodeTypeForName(workflow: IWorkflowBase, nodeName: string): INode | undefined {
|
export function getNodeTypeForName(workflow: IWorkflowBase, nodeName: string): INode | undefined {
|
||||||
return workflow.nodes.find((node) => node.name === nodeName);
|
return workflow.nodes.find((node) => node.name === nodeName);
|
||||||
}
|
}
|
||||||
|
@ -26,51 +27,59 @@ export function generateNodesGraph(
|
||||||
};
|
};
|
||||||
const nodeNameAndIndex: INodeNameIndex = {};
|
const nodeNameAndIndex: INodeNameIndex = {};
|
||||||
|
|
||||||
workflow.nodes.forEach((node: INode, index: number) => {
|
try {
|
||||||
nodesGraph.node_types.push(node.type);
|
workflow.nodes.forEach((node: INode, index: number) => {
|
||||||
const nodeItem: INodeGraphItem = {
|
nodesGraph.node_types.push(node.type);
|
||||||
type: node.type,
|
const nodeItem: INodeGraphItem = {
|
||||||
position: node.position,
|
type: node.type,
|
||||||
|
position: node.position,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (node.type === 'n8n-nodes-base.httpRequest') {
|
||||||
|
try {
|
||||||
|
nodeItem.domain = new URL(node.parameters.url as string).hostname;
|
||||||
|
} catch (e) {
|
||||||
|
nodeItem.domain = node.parameters.url as string;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const nodeType = nodeTypes.getByNameAndVersion(node.type);
|
||||||
|
|
||||||
|
nodeType?.description.properties.forEach((property) => {
|
||||||
|
if (
|
||||||
|
property.name === 'operation' ||
|
||||||
|
property.name === 'resource' ||
|
||||||
|
property.name === 'mode'
|
||||||
|
) {
|
||||||
|
nodeItem[property.name] = property.default ? property.default.toString() : undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
nodeItem.operation = node.parameters.operation?.toString() ?? nodeItem.operation;
|
||||||
|
nodeItem.resource = node.parameters.resource?.toString() ?? nodeItem.resource;
|
||||||
|
nodeItem.mode = node.parameters.mode?.toString() ?? nodeItem.mode;
|
||||||
|
}
|
||||||
|
nodesGraph.nodes[`${index}`] = nodeItem;
|
||||||
|
nodeNameAndIndex[node.name] = index.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
const getGraphConnectionItem = (startNode: string, connectionItem: IConnection) => {
|
||||||
|
return { start: nodeNameAndIndex[startNode], end: nodeNameAndIndex[connectionItem.node] };
|
||||||
};
|
};
|
||||||
|
|
||||||
if (node.type === 'n8n-nodes-base.httpRequest') {
|
Object.keys(workflow.connections).forEach((nodeName) => {
|
||||||
try {
|
const connections = workflow.connections[nodeName];
|
||||||
nodeItem.domain = new URL(node.parameters.url as string).hostname;
|
connections.main.forEach((element) => {
|
||||||
} catch (e) {
|
element.forEach((element2) => {
|
||||||
nodeItem.domain = node.parameters.url as string;
|
nodesGraph.node_connections.push(getGraphConnectionItem(nodeName, element2));
|
||||||
}
|
});
|
||||||
} else {
|
|
||||||
const nodeType = nodeTypes.getByName(node.type) as INodeType;
|
|
||||||
nodeType.description.properties.forEach((property) => {
|
|
||||||
if (
|
|
||||||
property.name === 'operation' ||
|
|
||||||
property.name === 'resource' ||
|
|
||||||
property.name === 'mode'
|
|
||||||
) {
|
|
||||||
nodeItem[property.name] = property.default ? property.default.toString() : undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeItem.operation = node.parameters.operation?.toString() ?? nodeItem.operation;
|
|
||||||
nodeItem.resource = node.parameters.resource?.toString() ?? nodeItem.resource;
|
|
||||||
nodeItem.mode = node.parameters.mode?.toString() ?? nodeItem.mode;
|
|
||||||
}
|
|
||||||
nodesGraph.nodes[`${index}`] = nodeItem;
|
|
||||||
nodeNameAndIndex[node.name] = index.toString();
|
|
||||||
});
|
|
||||||
|
|
||||||
const getGraphConnectionItem = (startNode: string, connectionItem: IConnection) => {
|
|
||||||
return { start: nodeNameAndIndex[startNode], end: nodeNameAndIndex[connectionItem.node] };
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.keys(workflow.connections).forEach((nodeName) => {
|
|
||||||
const connections = workflow.connections[nodeName];
|
|
||||||
connections.main.forEach((element) => {
|
|
||||||
element.forEach((element2) => {
|
|
||||||
nodesGraph.node_connections.push(getGraphConnectionItem(nodeName, element2));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
} catch (e) {
|
||||||
|
const logger = getLoggerInstance();
|
||||||
|
logger.warn(`Failed to generate nodes graph for workflowId: ${workflow.id as string | number}`);
|
||||||
|
logger.warn((e as Error).message);
|
||||||
|
logger.warn((e as Error).stack ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
return { nodeGraph: nodesGraph, nameIndices: nodeNameAndIndex };
|
return { nodeGraph: nodesGraph, nameIndices: nodeNameAndIndex };
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeData,
|
INodeTypeData,
|
||||||
INodeTypes,
|
INodeTypes,
|
||||||
|
INodeVersionedType,
|
||||||
IRunExecutionData,
|
IRunExecutionData,
|
||||||
ITaskDataConnections,
|
ITaskDataConnections,
|
||||||
IWorkflowBase,
|
IWorkflowBase,
|
||||||
|
@ -614,7 +615,7 @@ class NodeTypesClass implements INodeTypes {
|
||||||
return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedNodeType(data.type));
|
return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedNodeType(data.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
getByName(nodeType: string): INodeType {
|
getByName(nodeType: string): INodeType | INodeVersionedType | undefined {
|
||||||
return this.getByNameAndVersion(nodeType);
|
return this.getByNameAndVersion(nodeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -618,7 +618,7 @@ describe('RoutingNode', () => {
|
||||||
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
|
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
|
||||||
const additionalData = Helpers.WorkflowExecuteAdditionalData();
|
const additionalData = Helpers.WorkflowExecuteAdditionalData();
|
||||||
const path = '';
|
const path = '';
|
||||||
const nodeType = nodeTypes.getByName(node.type);
|
const nodeType = nodeTypes.getByNameAndVersion(node.type);
|
||||||
|
|
||||||
const workflowData = {
|
const workflowData = {
|
||||||
nodes: [node],
|
nodes: [node],
|
||||||
|
@ -1596,7 +1596,7 @@ describe('RoutingNode', () => {
|
||||||
const connectionInputData: INodeExecutionData[] = [];
|
const connectionInputData: INodeExecutionData[] = [];
|
||||||
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
|
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
|
||||||
const additionalData = Helpers.WorkflowExecuteAdditionalData();
|
const additionalData = Helpers.WorkflowExecuteAdditionalData();
|
||||||
const nodeType = nodeTypes.getByName(baseNode.type);
|
const nodeType = nodeTypes.getByNameAndVersion(baseNode.type);
|
||||||
|
|
||||||
const inputData: ITaskDataConnections = {
|
const inputData: ITaskDataConnections = {
|
||||||
main: [
|
main: [
|
||||||
|
|
Loading…
Reference in a new issue