From 3980cfa2a885d966a783ba187e20960c6d930dd1 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Tue, 29 Apr 2025 10:36:02 +0200 Subject: [PATCH] feat: show backend and frontend sdks separately (#9857) --- .../application/ApplicationChart.tsx | 61 ++++++++++++++++--- .../ApplicationIssues.test.tsx | 6 ++ .../application/ApplicationOverview.test.tsx | 4 ++ frontend/src/interfaces/uiConfig.ts | 1 + .../applicationOverviewEnvironmentSchema.ts | 2 + src/lib/db/client-applications-store.ts | 12 ++++ .../metrics/instance/instance-service.test.ts | 2 + ...application-overview-environment-schema.ts | 26 +++++++- .../spec/application-overview-schema.test.ts | 4 ++ .../e2e/api/admin/applications.e2e.test.ts | 5 ++ 10 files changed, 114 insertions(+), 9 deletions(-) diff --git a/frontend/src/component/application/ApplicationChart.tsx b/frontend/src/component/application/ApplicationChart.tsx index 10707a664f..56a8e2bd0e 100644 --- a/frontend/src/component/application/ApplicationChart.tsx +++ b/frontend/src/component/application/ApplicationChart.tsx @@ -16,6 +16,7 @@ import WarningAmberRounded from '@mui/icons-material/WarningAmberRounded'; import { TimeAgo } from 'component/common/TimeAgo/TimeAgo'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import { getApplicationIssues } from './ApplicationIssues/ApplicationIssues'; +import { useUiFlag } from 'hooks/useUiFlag'; const StyledTable = styled('table')(({ theme }) => ({ fontSize: theme.fontSizes.smallerBody, @@ -196,6 +197,7 @@ export const ApplicationChart = ({ data }: IApplicationChartProps) => { const { elementRef, width } = useElementWidth(); const navigate = useNavigate(); const theme = useTheme(); + const registerFrontendClientEnabled = useUiFlag('registerFrontendClient'); const mode = getApplicationIssues(data); @@ -294,14 +296,57 @@ export const ApplicationChart = ({ data }: IApplicationChartProps) => { {environment.instanceCount} - - SDK: - - {environment.sdks.map((sdk) => ( -
{sdk}
- ))} -
- + {!registerFrontendClientEnabled ? ( + + SDK: + + {environment.sdks.map( + (sdk) => ( +
+ {sdk} +
+ ), + )} +
+ + ) : null} + + {registerFrontendClientEnabled && + environment.backendSdks.length > 0 ? ( + + + Backend SDK: + + + {environment.backendSdks.map( + (sdk) => ( +
+ {sdk} +
+ ), + )} +
+ + ) : null} + + {registerFrontendClientEnabled && + environment.frontendSdks.length > 0 ? ( + + + Frontend SDK: + + + {environment.frontendSdks.map( + (sdk) => ( +
+ {sdk} +
+ ), + )} +
+ + ) : null} + Last seen: diff --git a/frontend/src/component/application/ApplicationIssues/ApplicationIssues.test.tsx b/frontend/src/component/application/ApplicationIssues/ApplicationIssues.test.tsx index d34dd14aef..d52daafd58 100644 --- a/frontend/src/component/application/ApplicationIssues/ApplicationIssues.test.tsx +++ b/frontend/src/component/application/ApplicationIssues/ApplicationIssues.test.tsx @@ -14,6 +14,8 @@ test('Display all application issues', async () => { outdatedSdks: ['unleash-client-php:1.13.0'], }, sdks: [], + backendSdks: [], + frontendSdks: [], instanceCount: 0, lastSeen: new Date().toISOString(), name: 'development', @@ -49,6 +51,8 @@ test('Each SDK version should be displayed once', async () => { outdatedSdks: ['unleash-client-php:1.13.0'], }, sdks: [], + frontendSdks: [], + backendSdks: [], instanceCount: 0, lastSeen: new Date().toISOString(), name: 'development', @@ -59,6 +63,8 @@ test('Each SDK version should be displayed once', async () => { outdatedSdks: ['unleash-client-php:1.13.0'], }, sdks: [], + frontendSdks: [], + backendSdks: [], instanceCount: 0, lastSeen: new Date().toISOString(), name: 'production', diff --git a/frontend/src/component/application/ApplicationOverview.test.tsx b/frontend/src/component/application/ApplicationOverview.test.tsx index 284a95f582..a172f12898 100644 --- a/frontend/src/component/application/ApplicationOverview.test.tsx +++ b/frontend/src/component/application/ApplicationOverview.test.tsx @@ -26,6 +26,8 @@ test('Display application overview with environments', async () => { instanceCount: 999, lastSeen: new Date().toISOString(), sdks: ['unleash-client-node:5.5.0-beta.0'], + frontendSdks: [], + backendSdks: ['unleash-client-node:5.5.0-beta.0'], issues: { missingFeatures: [], outdatedSdks: [], @@ -88,6 +90,8 @@ test('Display application with issues', async () => { instanceCount: 999, lastSeen: new Date().toISOString(), sdks: ['unleash-client-node:5.5.0-beta.0'], + frontendSdks: [], + backendSdks: ['unleash-client-node:5.5.0-beta.0'], issues: { missingFeatures: ['feature1'], outdatedSdks: [], diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index 2f72b543ad..8219614d11 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -96,6 +96,7 @@ export type UiFlags = { newStrategyDropdown?: boolean; flagsReleaseManagementUI?: boolean; cleanupReminder?: boolean; + registerFrontendClient?: boolean; }; export interface IVersionInfo { diff --git a/frontend/src/openapi/models/applicationOverviewEnvironmentSchema.ts b/frontend/src/openapi/models/applicationOverviewEnvironmentSchema.ts index f4aaef83e7..a5e6a0ca0b 100644 --- a/frontend/src/openapi/models/applicationOverviewEnvironmentSchema.ts +++ b/frontend/src/openapi/models/applicationOverviewEnvironmentSchema.ts @@ -22,4 +22,6 @@ export interface ApplicationOverviewEnvironmentSchema { name: string; /** SDKs used in the application environment */ sdks: string[]; + backendSdks: string[]; + frontendSdks: string[]; } diff --git a/src/lib/db/client-applications-store.ts b/src/lib/db/client-applications-store.ts index cdd35b36b2..e6c7d8b922 100644 --- a/src/lib/db/client-applications-store.ts +++ b/src/lib/db/client-applications-store.ts @@ -328,6 +328,12 @@ export default class ClientApplicationsStore 'ARRAY_AGG(DISTINCT ci.sdk_version) FILTER (WHERE ci.sdk_version IS NOT NULL) as sdk_versions', ), this.db.raw('MAX(ci.last_seen) as latest_last_seen'), + this.db.raw( + "ARRAY_AGG(DISTINCT ci.sdk_version) FILTER (WHERE ci.sdk_type = 'frontend' AND ci.sdk_version IS NOT NULL) as frontend_sdks", + ), + this.db.raw( + "ARRAY_AGG(DISTINCT ci.sdk_version) FILTER (WHERE ci.sdk_type = 'backend' AND ci.sdk_version IS NOT NULL) as backend_sdks", + ), ]) .from('client_instances as ci') .where('ci.app_name', appName) @@ -340,6 +346,8 @@ export default class ClientApplicationsStore 'm.features', 'i.unique_instance_count', 'i.sdk_versions', + 'i.backend_sdks', + 'i.frontend_sdks', 'i.latest_last_seen', 'ca.strategies', ]) @@ -371,6 +379,8 @@ export default class ClientApplicationsStore environment, unique_instance_count, sdk_versions, + frontend_sdks, + backend_sdks, latest_last_seen, project, features, @@ -396,6 +406,8 @@ export default class ClientApplicationsStore name: environment, instanceCount: Number(unique_instance_count), sdks: sdk_versions || [], + frontendSdks: frontend_sdks || [], + backendSdks: backend_sdks || [], lastSeen: latest_last_seen, issues: { missingFeatures: featuresNotMappedToProject diff --git a/src/lib/features/metrics/instance/instance-service.test.ts b/src/lib/features/metrics/instance/instance-service.test.ts index 5c79419807..469ed5f4e2 100644 --- a/src/lib/features/metrics/instance/instance-service.test.ts +++ b/src/lib/features/metrics/instance/instance-service.test.ts @@ -202,6 +202,8 @@ test('filter out private projects from overview', async () => { name: 'development', instanceCount: 1, sdks: ['unleash-client-node:3.5.1'], + backendSdks: ['unleash-client-node:3.5.1'], + frontendSdks: [], lastSeen: new Date(), issues: { missingFeatures: [], diff --git a/src/lib/openapi/spec/application-overview-environment-schema.ts b/src/lib/openapi/spec/application-overview-environment-schema.ts index 66fbd26348..d8f8cd3d35 100644 --- a/src/lib/openapi/spec/application-overview-environment-schema.ts +++ b/src/lib/openapi/spec/application-overview-environment-schema.ts @@ -6,7 +6,15 @@ export const applicationOverviewEnvironmentSchema = { type: 'object', description: 'Data about an application environment', additionalProperties: false, - required: ['name', 'instanceCount', 'sdks', 'lastSeen', 'issues'], + required: [ + 'name', + 'instanceCount', + 'sdks', + 'frontendSdks', + 'backendSdks', + 'lastSeen', + 'issues', + ], properties: { name: { description: 'Name of the application environment', @@ -27,6 +35,22 @@ export const applicationOverviewEnvironmentSchema = { }, example: ['unleash-client-node:5.4.0', 'unleash-client-node:5.3.0'], }, + frontendSdks: { + description: 'Frontend SDKs used in the application environment', + type: 'array', + items: { + type: 'string', + }, + example: ['unleash-client-js:3.7.5'], + }, + backendSdks: { + description: 'Backend SDKs used in the application environment', + type: 'array', + items: { + type: 'string', + }, + example: ['unleash-client-node:5.4.0'], + }, lastSeen: { type: 'string', nullable: true, diff --git a/src/lib/openapi/spec/application-overview-schema.test.ts b/src/lib/openapi/spec/application-overview-schema.test.ts index c3483b3d4c..335252de1d 100644 --- a/src/lib/openapi/spec/application-overview-schema.test.ts +++ b/src/lib/openapi/spec/application-overview-schema.test.ts @@ -12,6 +12,8 @@ test('applicationOverviewSchema', () => { name: 'production', instanceCount: 34, sdks: ['unleash-client-node:5.4.0'], + backendSdks: ['unleash-client-node:5.4.0'], + frontendSdks: [], lastSeen: '2021-10-01T12:00:00Z', issues: { missingFeatures: ['feature1'], @@ -22,6 +24,8 @@ test('applicationOverviewSchema', () => { name: 'development', instanceCount: 16, sdks: ['unleash-client-java:5.4.0'], + backendSdks: ['unleash-client-java:5.4.0'], + frontendSdks: [], lastSeen: '2021-10-01T12:00:00Z', issues: { missingFeatures: [], diff --git a/src/test/e2e/api/admin/applications.e2e.test.ts b/src/test/e2e/api/admin/applications.e2e.test.ts index 4e484489b3..b1b191fa19 100644 --- a/src/test/e2e/api/admin/applications.e2e.test.ts +++ b/src/test/e2e/api/admin/applications.e2e.test.ts @@ -128,6 +128,11 @@ test('should show correct application metrics', async () => { { instanceCount: 2, name: 'default', + frontendSdks: [], + backendSdks: [ + 'unleash-client-node:3.2.1', + 'unleash-client-node:3.2.2', + ], sdks: [ 'unleash-client-node:3.2.1', 'unleash-client-node:3.2.2',