diff --git a/packages/cli/src/interfaces.ts b/packages/cli/src/interfaces.ts index 4d2cd9b2d9..65b3a56346 100644 --- a/packages/cli/src/interfaces.ts +++ b/packages/cli/src/interfaces.ts @@ -355,7 +355,7 @@ export type NumericLicenseFeature = ValuesOf; export interface ILicenseReadResponse { usage: { - executions: { + activeWorkflowTriggers: { limit: number; value: number; warningThreshold: number; diff --git a/packages/cli/src/license/__tests__/license.service.test.ts b/packages/cli/src/license/__tests__/license.service.test.ts index 77afe04a2c..9cd9c0ee0b 100644 --- a/packages/cli/src/license/__tests__/license.service.test.ts +++ b/packages/cli/src/license/__tests__/license.service.test.ts @@ -41,7 +41,7 @@ describe('LicenseService', () => { const data = await licenseService.getLicenseData(); expect(data).toEqual({ usage: { - executions: { + activeWorkflowTriggers: { limit: 400, value: 7, warningThreshold: 0.8, diff --git a/packages/cli/src/license/license.service.ts b/packages/cli/src/license/license.service.ts index 43f9961334..cdd6454036 100644 --- a/packages/cli/src/license/license.service.ts +++ b/packages/cli/src/license/license.service.ts @@ -37,7 +37,7 @@ export class LicenseService { return { usage: { - executions: { + activeWorkflowTriggers: { value: triggerCount, limit: this.license.getTriggerLimit(), warningThreshold: 0.8, diff --git a/packages/cli/src/metrics/__tests__/license-metrics.service.test.ts b/packages/cli/src/metrics/__tests__/license-metrics.service.test.ts index ec123a3f01..6771b13fb7 100644 --- a/packages/cli/src/metrics/__tests__/license-metrics.service.test.ts +++ b/packages/cli/src/metrics/__tests__/license-metrics.service.test.ts @@ -6,11 +6,14 @@ import { LicenseMetricsService } from '@/metrics/license-metrics.service'; describe('LicenseMetricsService', () => { const workflowRepository = mock(); + const licenseMetricsRespository = mock(); const licenseMetricsService = new LicenseMetricsService( - mock(), + licenseMetricsRespository, workflowRepository, ); + beforeEach(() => jest.clearAllMocks()); + describe('collectPassthroughData', () => { test('should return an object with active workflow IDs', async () => { /** @@ -30,4 +33,36 @@ describe('LicenseMetricsService', () => { expect(result).toEqual({ activeWorkflowIds }); }); }); + + describe('collectUsageMetrics', () => { + test('should return an array of expected usage metrics', async () => { + const mockActiveTriggerCount = 1234; + workflowRepository.getActiveTriggerCount.mockResolvedValue(mockActiveTriggerCount); + + const mockRenewalMetrics = { + activeWorkflows: 100, + totalWorkflows: 200, + enabledUsers: 300, + totalUsers: 400, + totalCredentials: 500, + productionExecutions: 600, + manualExecutions: 700, + }; + + licenseMetricsRespository.getLicenseRenewalMetrics.mockResolvedValue(mockRenewalMetrics); + + const result = await licenseMetricsService.collectUsageMetrics(); + + expect(result).toEqual([ + { name: 'activeWorkflows', value: mockRenewalMetrics.activeWorkflows }, + { name: 'totalWorkflows', value: mockRenewalMetrics.totalWorkflows }, + { name: 'enabledUsers', value: mockRenewalMetrics.enabledUsers }, + { name: 'totalUsers', value: mockRenewalMetrics.totalUsers }, + { name: 'totalCredentials', value: mockRenewalMetrics.totalCredentials }, + { name: 'productionExecutions', value: mockRenewalMetrics.productionExecutions }, + { name: 'manualExecutions', value: mockRenewalMetrics.manualExecutions }, + { name: 'activeWorkflowTriggers', value: mockActiveTriggerCount }, + ]); + }); + }); }); diff --git a/packages/cli/src/metrics/license-metrics.service.ts b/packages/cli/src/metrics/license-metrics.service.ts index ba546b3cc0..338fa70a3e 100644 --- a/packages/cli/src/metrics/license-metrics.service.ts +++ b/packages/cli/src/metrics/license-metrics.service.ts @@ -21,6 +21,8 @@ export class LicenseMetricsService { manualExecutions, } = await this.licenseMetricsRepository.getLicenseRenewalMetrics(); + const activeTriggerCount = await this.workflowRepository.getActiveTriggerCount(); + return [ { name: 'activeWorkflows', value: activeWorkflows }, { name: 'totalWorkflows', value: totalWorkflows }, @@ -29,6 +31,7 @@ export class LicenseMetricsService { { name: 'totalCredentials', value: totalCredentials }, { name: 'productionExecutions', value: productionExecutions }, { name: 'manualExecutions', value: manualExecutions }, + { name: 'activeWorkflowTriggers', value: activeTriggerCount }, ]; } diff --git a/packages/cli/test/integration/license.api.test.ts b/packages/cli/test/integration/license.api.test.ts index ff40a699ea..a06408c6cb 100644 --- a/packages/cli/test/integration/license.api.test.ts +++ b/packages/cli/test/integration/license.api.test.ts @@ -116,7 +116,7 @@ describe('POST /license/renew', () => { const DEFAULT_LICENSE_RESPONSE: { data: ILicenseReadResponse } = { data: { usage: { - executions: { + activeWorkflowTriggers: { value: 0, limit: -1, warningThreshold: 0.8, @@ -132,7 +132,7 @@ const DEFAULT_LICENSE_RESPONSE: { data: ILicenseReadResponse } = { const DEFAULT_POST_RESPONSE: { data: ILicensePostResponse } = { data: { usage: { - executions: { + activeWorkflowTriggers: { value: 0, limit: -1, warningThreshold: 0.8, diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index add7905fcf..e639f537df 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -1296,7 +1296,7 @@ export type UsageState = { loading: boolean; data: { usage: { - executions: { + activeWorkflowTriggers: { limit: number; // -1 for unlimited, from license value: number; warningThreshold: number; // hardcoded value in BE diff --git a/packages/editor-ui/src/stores/__tests__/usage.test.ts b/packages/editor-ui/src/stores/__tests__/usage.test.ts index 9a2dbc419d..def731e4af 100644 --- a/packages/editor-ui/src/stores/__tests__/usage.test.ts +++ b/packages/editor-ui/src/stores/__tests__/usage.test.ts @@ -21,7 +21,7 @@ describe('Usage and plan store', () => { const store = useUsageStore(); store.setData({ usage: { - executions: { + activeWorkflowTriggers: { limit, value, warningThreshold, diff --git a/packages/editor-ui/src/stores/usage.store.ts b/packages/editor-ui/src/stores/usage.store.ts index 6fc91c4221..bc62d1df8b 100644 --- a/packages/editor-ui/src/stores/usage.store.ts +++ b/packages/editor-ui/src/stores/usage.store.ts @@ -18,7 +18,7 @@ const DEFAULT_STATE: UsageState = { loading: true, data: { usage: { - executions: { + activeWorkflowTriggers: { limit: -1, value: 0, warningThreshold: 0.8, @@ -39,9 +39,11 @@ export const useUsageStore = defineStore('usage', () => { const planName = computed(() => state.data.license.planName || DEFAULT_PLAN_NAME); const planId = computed(() => state.data.license.planId); - const executionLimit = computed(() => state.data.usage.executions.limit); - const executionCount = computed(() => state.data.usage.executions.value); - const executionPercentage = computed(() => (executionCount.value / executionLimit.value) * 100); + const activeWorkflowTriggersLimit = computed(() => state.data.usage.activeWorkflowTriggers.limit); + const activeWorkflowTriggersCount = computed(() => state.data.usage.activeWorkflowTriggers.value); + const executionPercentage = computed( + () => (activeWorkflowTriggersCount.value / activeWorkflowTriggersLimit.value) * 100, + ); const instanceId = computed(() => settingsStore.settings.instanceId); const managementToken = computed(() => state.data.managementToken); const appVersion = computed(() => settingsStore.settings.versionCli); @@ -99,17 +101,17 @@ export const useUsageStore = defineStore('usage', () => { registerCommunityEdition, planName, planId, - executionLimit, - executionCount, + activeWorkflowTriggersLimit, + activeWorkflowTriggersCount, executionPercentage, instanceId, managementToken, appVersion, isCloseToLimit: computed(() => - state.data.usage.executions.limit < 0 + state.data.usage.activeWorkflowTriggers.limit < 0 ? false - : executionCount.value / executionLimit.value >= - state.data.usage.executions.warningThreshold, + : activeWorkflowTriggersCount.value / activeWorkflowTriggersLimit.value >= + state.data.usage.activeWorkflowTriggers.warningThreshold, ), viewPlansUrl: computed( () => `${subscriptionAppUrl.value}?${commonSubscriptionAppUrlQueryParams.value}`, @@ -123,8 +125,8 @@ export const useUsageStore = defineStore('usage', () => { instance_id: instanceId.value, action: 'view_plans', plan_name_current: planName.value, - usage: executionCount.value, - quota: executionLimit.value, + usage: activeWorkflowTriggersCount.value, + quota: activeWorkflowTriggersLimit.value, })), }; }); diff --git a/packages/editor-ui/src/views/SettingsUsageAndPlan.vue b/packages/editor-ui/src/views/SettingsUsageAndPlan.vue index 82a6da8b39..e3575c6c17 100644 --- a/packages/editor-ui/src/views/SettingsUsageAndPlan.vue +++ b/packages/editor-ui/src/views/SettingsUsageAndPlan.vue @@ -198,7 +198,7 @@ const openCommunityRegisterModal = () => { {{ locale.baseText('settings.usageAndPlan.activeWorkflows') }}
- + { :class="$style.count" keypath="settings.usageAndPlan.activeWorkflows.count" > - +