Files
Automata/packages/cli/src/events/WorkflowStatistics.ts
Omar Ajoue 2ad62bcd44 fix: Remove unnecessary console message (no-changelog) (#4848)
* refactor: Remove unnecessary console message (no-changelog)

* fix: Broken test now passing
2022-12-07 12:40:38 +01:00

105 lines
3.2 KiB
TypeScript

import { INode, IRun, IWorkflowBase } from 'n8n-workflow';
import { Db, InternalHooksManager } from '..';
import { StatisticsNames } from '../databases/entities/WorkflowStatistics';
import { getWorkflowOwner } from '../UserManagement/UserManagementHelper';
export async function workflowExecutionCompleted(
workflowData: IWorkflowBase,
runData: IRun,
): Promise<void> {
// Determine the name of the statistic
const finished = runData.finished ? runData.finished : false;
const manual = runData.mode === 'manual';
let name: StatisticsNames;
if (finished) {
if (manual) name = StatisticsNames.manualSuccess;
else name = StatisticsNames.productionSuccess;
} else {
if (manual) name = StatisticsNames.manualError;
else name = StatisticsNames.productionError;
}
// Get the workflow id
let workflowId: number;
try {
workflowId = parseInt(workflowData.id as string, 10);
if (isNaN(workflowId)) throw new Error('not a number');
} catch (error) {
console.error(`Error "${error as string}" when casting workflow ID to a number`);
return;
}
// Try insertion and if it fails due to key conflicts then update the existing entry instead
try {
await Db.collections.WorkflowStatistics.insert({
count: 1,
name,
workflowId,
latestEvent: new Date(),
});
// If we're here we can check if we're sending the first production success metric
if (name !== StatisticsNames.productionSuccess) return;
// Get the owner of the workflow so we can send the metric
const owner = await getWorkflowOwner(workflowId);
const metrics = {
user_id: owner.id,
workflow_id: workflowId,
};
// Send the metrics
await InternalHooksManager.getInstance().onFirstProductionWorkflowSuccess(metrics);
} catch (error) {
// Do we just assume it's a conflict error? If there is any other sort of error in the DB it should trigger here too
await Db.collections.WorkflowStatistics.update(
{ workflowId, name },
{ count: () => 'count + 1', latestEvent: new Date() },
);
}
}
export async function nodeFetchedData(workflowId: string, node: INode): Promise<void> {
// Get the workflow id
let id: number;
try {
id = parseInt(workflowId, 10);
if (isNaN(id)) throw new Error('not a number');
} catch (error) {
console.error(`Error ${error as string} when casting workflow ID to a number`);
return;
}
// Update only if necessary
const response = await Db.collections.Workflow.update(
{ id, dataLoaded: false },
{ dataLoaded: true },
);
// If response.affected is 1 then we know this was the first time data was loaded into the workflow; do posthog event here
if (!response.affected) return;
// Compile the metrics
const owner = await getWorkflowOwner(workflowId);
let metrics = {
user_id: owner.id,
workflow_id: id,
node_type: node.type,
node_id: node.id,
};
// This is probably naive but I can't see a way for a node to have multiple credentials attached so..
if (node.credentials) {
Object.entries(node.credentials).forEach(([credName, credDetails]) => {
metrics = Object.assign(metrics, {
credential_type: credName,
credential_id: credDetails.id,
});
});
}
// Send metrics to posthog
await InternalHooksManager.getInstance().onFirstWorkflowDataLoad(metrics);
}