diff --git a/frontend/package.json b/frontend/package.json
index f7ed39dfe1..841355c1c6 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -61,6 +61,7 @@
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"enzyme-to-json": "3.6.2",
+ "fast-json-patch": "3.1.0",
"fetch-mock": "9.11.0",
"http-proxy-middleware": "2.0.1",
"immutable": "4.0.0",
@@ -83,8 +84,7 @@
"sass": "1.42.1",
"swr": "1.0.1",
"typescript": "4.4.4",
- "web-vitals": "2.1.2",
- "fast-json-patch": "3.1.0"
+ "web-vitals": "2.1.2"
},
"jest": {
"moduleNameMapper": {
diff --git a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureEnvironmentMetrics/FeatureEnvironmentMetrics.tsx b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureEnvironmentMetrics/FeatureEnvironmentMetrics.tsx
index 08dbc95086..a02a307f3e 100644
--- a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureEnvironmentMetrics/FeatureEnvironmentMetrics.tsx
+++ b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureEnvironmentMetrics/FeatureEnvironmentMetrics.tsx
@@ -1,13 +1,15 @@
import classNames from 'classnames';
import PercentageCircle from '../../../../common/PercentageCircle/PercentageCircle';
import { useStyles } from './FeatureEnvironmentMetrics.styles';
-import { IEnvironmentMetrics } from '../../../../../interfaces/environments';
import PieChartIcon from '@material-ui/icons/PieChart';
import { useMediaQuery } from '@material-ui/core';
+import { IFeatureEnvironmentMetrics } from '../../../../../interfaces/featureToggle';
+import { parseISO } from 'date-fns';
+
interface IFeatureEnvironmentProps {
className?: string;
primaryMetric?: boolean;
- metric: IEnvironmentMetrics;
+ metric: IFeatureEnvironmentMetrics;
}
const FeatureEnvironmentMetrics = ({
@@ -21,6 +23,11 @@ const FeatureEnvironmentMetrics = ({
const containerClasses = classNames(styles.container, className, {
[styles.primaryMetric]: primaryMetric,
});
+ let hour = '';
+ if (metric?.timestamp) {
+ const metricTime = parseISO(metric.timestamp);
+ hour = `since ${metricTime.getHours()}:${metricTime.getMinutes()}`;
+ }
const calculatePercentage = () => {
const total = metric.yes + metric.no;
@@ -52,7 +59,7 @@ const FeatureEnvironmentMetrics = ({
- Traffic in {metric.name}
+ Traffic in {metric.environment} {hour}
@@ -75,7 +82,7 @@ const FeatureEnvironmentMetrics = ({
- Traffic in {metric.name}
+ Traffic in {metric.environment} {hour}
diff --git a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewMetrics/FeatureOverviewMetrics.tsx b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewMetrics/FeatureOverviewMetrics.tsx
index 848a4b678e..629f93e178 100644
--- a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewMetrics/FeatureOverviewMetrics.tsx
+++ b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewMetrics/FeatureOverviewMetrics.tsx
@@ -1,72 +1,33 @@
import { useParams } from 'react-router';
-import { useState, useEffect } from 'react';
import useFeature from '../../../../../hooks/api/getters/useFeature/useFeature';
import { IFeatureViewParams } from '../../../../../interfaces/params';
-import { IEnvironmentMetrics } from '../../../../../interfaces/environments';
import FeatureEnvironmentMetrics from '../FeatureEnvironmentMetrics/FeatureEnvironmentMetrics';
import { useStyles } from './FeatureOverviewMetrics.styles';
-
-const data = {
- version: 1,
- maturity: 'experimental',
- lastHourUsage: [
- {
- environment: 'default',
- timestamp: '2021-10-07 10:00:00',
- yes: 250,
- no: 60,
- },
- {
- environment: 'production',
- timestamp: '2021-10-07 10:00:00',
- yes: 200,
- no: 500,
- },
- {
- environment: 'development',
- timestamp: '2021-10-07 10:00:00',
- yes: 0,
- no: 0,
- },
- ],
- seenApplications: ['web', 'backend-api', 'commerce'],
-};
+import useFeatureMetrics from '../../../../../hooks/api/getters/useFeatureMetrics/useFeatureMetrics';
const FeatureOverviewMetrics = () => {
const styles = useStyles();
const { projectId, featureId } = useParams
();
const { feature } = useFeature(projectId, featureId);
- const [featureMetrics, setFeatureMetrics] = useState(
- []
- );
+ const { metrics } = useFeatureMetrics(projectId, featureId);
- useEffect(() => {
- const featureMetricList = feature?.environments.map(env => {
- const metrics = data.lastHourUsage.find(
- metric => metric.environment === env.name
- );
-
- if (!metrics) {
- return {
- name: env.name,
- yes: 0,
- no: 0,
- timestamp: '',
- };
- }
+ const featureMetrics = feature?.environments.map(env => {
+ const metric = metrics.lastHourUsage.find(
+ metric => metric.environment === env.name
+ );
+ if (!metric) {
return {
- name: env.name,
- yes: metrics.yes,
- no: metrics.no,
- timestamp: metrics.timestamp,
+ environment: env.name,
+ yes: 0,
+ no: 0,
+ timestamp: ''
};
- });
+ }
+
+ return metric;
+ });
- setFeatureMetrics(featureMetricList);
- /* Update on useSWR metrics change */
- /* eslint-disable-next-line */
- }, []);
const renderFeatureMetrics = () => {
if (featureMetrics.length === 0) {
@@ -88,14 +49,14 @@ const FeatureOverviewMetrics = () => {
return (
);
}
return (
);
@@ -109,7 +70,7 @@ const FeatureOverviewMetrics = () => {
return (
);
@@ -119,7 +80,7 @@ const FeatureOverviewMetrics = () => {
return (
);
@@ -127,7 +88,7 @@ const FeatureOverviewMetrics = () => {
return (
);
diff --git a/frontend/src/hooks/api/getters/useFeatureMetrics/useFeatureMetrics.ts b/frontend/src/hooks/api/getters/useFeatureMetrics/useFeatureMetrics.ts
new file mode 100644
index 0000000000..c43ca34802
--- /dev/null
+++ b/frontend/src/hooks/api/getters/useFeatureMetrics/useFeatureMetrics.ts
@@ -0,0 +1,57 @@
+import { formatApiPath } from '../../../../utils/format-path';
+import { useEffect, useState } from 'react';
+import useSWR, { mutate } from 'swr';
+import { IFeatureMetrics } from '../../../../interfaces/featureToggle';
+
+interface IUseFeatureMetricsOptions {
+ refreshInterval?: number;
+ revalidateOnFocus?: boolean;
+ revalidateOnReconnect?: boolean;
+ revalidateIfStale?: boolean;
+ revalidateOnMount?: boolean;
+}
+
+const emptyMetrics = { lastHourUsage: [], seenApplications: [] };
+
+const useFeatureMetrics = (projectId: string, featureId: string, options: IUseFeatureMetricsOptions = {}) => {
+ const fetcher = async () => {
+ const path = formatApiPath(`api/admin/client-metrics/features/${featureId}`);
+ const res = await fetch(path, {
+ method: 'GET'
+ });
+ if (res.ok) {
+ return res.json();
+ } else {
+ return emptyMetrics;
+ }
+ };
+
+ const FEATURE_METRICS_CACHE_KEY = `${projectId}_${featureId}_metrics`;
+ const { data, error } = useSWR(
+ FEATURE_METRICS_CACHE_KEY,
+ fetcher,
+ {
+ ...options
+ }
+ );
+
+ const [loading, setLoading] = useState(!error && !data);
+
+ const refetch = () => {
+ mutate(FEATURE_METRICS_CACHE_KEY);
+ };
+
+ useEffect(() => {
+ setLoading(!error && !data);
+ }, [data, error]);
+
+ return {
+ metrics: data || emptyMetrics,
+ error,
+ loading,
+ refetch,
+ FEATURE_METRICS_CACHE_KEY
+ };
+};
+
+export default useFeatureMetrics;
diff --git a/frontend/src/interfaces/featureToggle.ts b/frontend/src/interfaces/featureToggle.ts
index df626478b2..ca2d54b86b 100644
--- a/frontend/src/interfaces/featureToggle.ts
+++ b/frontend/src/interfaces/featureToggle.ts
@@ -48,3 +48,17 @@ export interface IPayload {
name: string;
value: string;
}
+
+export interface IFeatureEnvironmentMetrics {
+ environment: string;
+ timestamp: string;
+ yes: number;
+ no: number;
+}
+
+export interface IFeatureMetrics {
+ version: number;
+ maturity: string;
+ lastHourUsage: IFeatureEnvironmentMetrics[],
+ seenApplication: string[]
+}