feat(core): Workflow Execution Statistics (#4200)

Add recording and reporting of workflow execution statistics
This commit is contained in:
freya
2022-12-06 14:55:40 +00:00
committed by GitHub
parent b71295e4de
commit 1722c6b0c5
28 changed files with 908 additions and 66 deletions

View File

@@ -13,6 +13,7 @@ import {
Column,
Entity,
Index,
JoinColumn,
JoinTable,
ManyToMany,
OneToMany,
@@ -24,6 +25,7 @@ import { TagEntity } from './TagEntity';
import { SharedWorkflow } from './SharedWorkflow';
import { objectRetriever, sqlite } from '../utils/transformers';
import { AbstractEntity, jsonColumnType } from './AbstractEntity';
import { WorkflowStatistics } from './WorkflowStatistics';
import type { IWorkflowDb } from '@/Interfaces';
@Entity()
@@ -78,6 +80,16 @@ export class WorkflowEntity extends AbstractEntity implements IWorkflowDb {
@OneToMany(() => SharedWorkflow, (sharedWorkflow) => sharedWorkflow.workflow)
shared: SharedWorkflow[];
@OneToMany(
() => WorkflowStatistics,
(workflowStatistics: WorkflowStatistics) => workflowStatistics.workflow,
)
@JoinColumn({ referencedColumnName: 'workflow' })
statistics: WorkflowStatistics[];
@Column({ default: false })
dataLoaded: boolean;
@Column({
type: config.getEnv('database.type') === 'sqlite' ? 'text' : 'json',
nullable: true,

View File

@@ -0,0 +1,32 @@
import { Column, Entity, RelationId, ManyToOne, PrimaryColumn } from 'typeorm';
import { datetimeColumnType } from './AbstractEntity';
import { WorkflowEntity } from './WorkflowEntity';
export enum StatisticsNames {
productionSuccess = 'production_success',
productionError = 'production_error',
manualSuccess = 'manual_success',
manualError = 'manual_error',
}
@Entity()
export class WorkflowStatistics {
@Column()
count: number;
@Column(datetimeColumnType)
latestEvent: Date;
@PrimaryColumn({ length: 128 })
name: StatisticsNames;
@ManyToOne(() => WorkflowEntity, (workflow) => workflow.shared, {
primary: true,
onDelete: 'CASCADE',
})
workflow: WorkflowEntity;
@RelationId((workflowStatistics: WorkflowStatistics) => workflowStatistics.workflow)
@PrimaryColumn()
workflowId: number;
}

View File

@@ -11,6 +11,7 @@ import { SharedWorkflow } from './SharedWorkflow';
import { SharedCredentials } from './SharedCredentials';
import { InstalledPackages } from './InstalledPackages';
import { InstalledNodes } from './InstalledNodes';
import { WorkflowStatistics } from './WorkflowStatistics';
export const entities = {
CredentialsEntity,
@@ -25,4 +26,5 @@ export const entities = {
SharedCredentials,
InstalledPackages,
InstalledNodes,
WorkflowStatistics,
};

View File

@@ -0,0 +1,38 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { logMigrationEnd, logMigrationStart } from '../../utils/migrationHelpers';
import config from '@/config';
export class WorkflowStatistics1664196174002 implements MigrationInterface {
name = 'WorkflowStatistics1664196174002';
async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(
`CREATE TABLE ${tablePrefix}workflow_statistics (
count INTEGER DEFAULT 0,
latestEvent DATETIME,
name VARCHAR(128) NOT NULL,
workflowId INTEGER,
PRIMARY KEY(workflowId, name),
FOREIGN KEY(workflowId) REFERENCES ${tablePrefix}workflow_entity(id) ON DELETE CASCADE
)`,
);
// Add dataLoaded column to workflow table
await queryRunner.query(
`ALTER TABLE ${tablePrefix}workflow_entity ADD COLUMN dataLoaded BOOLEAN DEFAULT false`,
);
logMigrationEnd(this.name);
}
async down(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(`DROP TABLE "${tablePrefix}workflow_statistics"`);
await queryRunner.query(`ALTER TABLE ${tablePrefix}workflow_entity DROP COLUMN dataLoaded`);
}
}

View File

@@ -20,6 +20,7 @@ import { IntroducePinData1654090101303 } from './1654090101303-IntroducePinData'
import { AddNodeIds1658932910559 } from './1658932910559-AddNodeIds';
import { AddJsonKeyPinData1659895550980 } from './1659895550980-AddJsonKeyPinData';
import { CreateCredentialsUserRole1660062385367 } from './1660062385367-CreateCredentialsUserRole';
import { WorkflowStatistics1664196174002 } from './1664196174002-WorkflowStatistics';
import { CreateWorkflowsEditorRole1663755770894 } from './1663755770894-CreateWorkflowsEditorRole';
import { CreateCredentialUsageTable1665484192213 } from './1665484192213-CreateCredentialUsageTable';
import { RemoveCredentialUsageTable1665754637026 } from './1665754637026-RemoveCredentialUsageTable';
@@ -52,4 +53,5 @@ export const mysqlMigrations = [
CreateCredentialUsageTable1665484192213,
RemoveCredentialUsageTable1665754637026,
AddWorkflowVersionIdColumn1669739707125,
WorkflowStatistics1664196174002,
];

View File

@@ -0,0 +1,42 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { getTablePrefix, logMigrationEnd, logMigrationStart } from '../../utils/migrationHelpers';
import config from '@/config';
export class WorkflowStatistics1664196174001 implements MigrationInterface {
name = 'WorkflowStatistics1664196174001';
async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = getTablePrefix();
// Create statistics table
await queryRunner.query(
`CREATE TABLE ${tablePrefix}workflow_statistics (
"count" INTEGER DEFAULT 0,
"latestEvent" TIMESTAMP,
"name" VARCHAR(128) NOT NULL,
"workflowId" INTEGER,
PRIMARY KEY("workflowId", "name"),
FOREIGN KEY("workflowId") REFERENCES ${tablePrefix}workflow_entity("id") ON DELETE CASCADE
)`,
);
// Add dataLoaded column to workflow table
await queryRunner.query(
`ALTER TABLE ${tablePrefix}workflow_entity ADD COLUMN "dataLoaded" BOOLEAN DEFAULT false;`,
);
logMigrationEnd(this.name);
}
async down(queryRunner: QueryRunner): Promise<void> {
let tablePrefix = config.getEnv('database.tablePrefix');
const schema = config.getEnv('database.postgresdb.schema');
if (schema) {
tablePrefix = schema + '.' + tablePrefix;
}
await queryRunner.query(`DROP TABLE ${tablePrefix}workflow_statistics`);
await queryRunner.query(`ALTER TABLE ${tablePrefix}workflow_entity DROP COLUMN dataLoaded`);
}
}

View File

@@ -18,6 +18,7 @@ import { IntroducePinData1654090467022 } from './1654090467022-IntroducePinData'
import { AddNodeIds1658932090381 } from './1658932090381-AddNodeIds';
import { AddJsonKeyPinData1659902242948 } from './1659902242948-AddJsonKeyPinData';
import { CreateCredentialsUserRole1660062385367 } from './1660062385367-CreateCredentialsUserRole';
import { WorkflowStatistics1664196174001 } from './1664196174001-WorkflowStatistics';
import { CreateWorkflowsEditorRole1663755770893 } from './1663755770893-CreateWorkflowsEditorRole';
import { CreateCredentialUsageTable1665484192212 } from './1665484192212-CreateCredentialUsageTable';
import { RemoveCredentialUsageTable1665754637025 } from './1665754637025-RemoveCredentialUsageTable';
@@ -48,4 +49,5 @@ export const postgresMigrations = [
CreateCredentialUsageTable1665484192212,
RemoveCredentialUsageTable1665754637025,
AddWorkflowVersionIdColumn1669739707126,
WorkflowStatistics1664196174001,
];

View File

@@ -0,0 +1,40 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { logMigrationEnd, logMigrationStart } from '../../utils/migrationHelpers';
import config from '@/config';
export class WorkflowStatistics1664196174000 implements MigrationInterface {
name = 'WorkflowStatistics1664196174000';
async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(
`CREATE TABLE \`${tablePrefix}workflow_statistics\` (
"count" INTEGER DEFAULT 0,
"latestEvent" DATETIME,
"name" VARCHAR(128) NOT NULL,
"workflowId" INTEGER,
PRIMARY KEY("workflowId", "name"),
FOREIGN KEY("workflowId") REFERENCES \`${tablePrefix}workflow_entity\`("id") ON DELETE CASCADE
)`,
);
// Add dataLoaded column to workflow table
await queryRunner.query(
`ALTER TABLE \`${tablePrefix}workflow_entity\` ADD COLUMN "dataLoaded" BOOLEAN DEFAULT false`,
);
logMigrationEnd(this.name);
}
async down(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(`DROP TABLE "${tablePrefix}workflow_statistics"`);
await queryRunner.query(
`ALTER TABLE \`${tablePrefix}workflow_entity\` DROP COLUMN "dataLoaded"`,
);
}
}

View File

@@ -17,6 +17,7 @@ import { IntroducePinData1654089251344 } from './1654089251344-IntroducePinData'
import { AddNodeIds1658930531669 } from './1658930531669-AddNodeIds';
import { AddJsonKeyPinData1659888469333 } from './1659888469333-AddJsonKeyPinData';
import { CreateCredentialsUserRole1660062385367 } from './1660062385367-CreateCredentialsUserRole';
import { WorkflowStatistics1664196174000 } from './1664196174000-WorkflowStatistics';
import { CreateWorkflowsEditorRole1663755770892 } from './1663755770892-CreateWorkflowsUserRole';
import { CreateCredentialUsageTable1665484192211 } from './1665484192211-CreateCredentialUsageTable';
import { RemoveCredentialUsageTable1665754637024 } from './1665754637024-RemoveCredentialUsageTable';
@@ -46,6 +47,7 @@ const sqliteMigrations = [
CreateCredentialUsageTable1665484192211,
RemoveCredentialUsageTable1665754637024,
AddWorkflowVersionIdColumn1669739707124,
WorkflowStatistics1664196174000,
];
export { sqliteMigrations };