1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-09 00:18:00 +01:00

Create hook for fetching featureMetrics (#414)

* Create hook for fetching featureMetrics
This commit is contained in:
Christopher Kolstad 2021-10-13 10:20:34 +02:00 committed by GitHub
parent d821224a4b
commit 8a9dc32bad
5 changed files with 104 additions and 65 deletions

View File

@ -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": {

View File

@ -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 = ({
<div className={containerClasses}>
<div className={styles.headerContainer}>
<h2 data-loading className={styles.title}>
Traffic in {metric.name}
Traffic in {metric.environment} {hour}
</h2>
</div>
@ -75,7 +82,7 @@ const FeatureEnvironmentMetrics = ({
<div className={containerClasses}>
<div className={styles.headerContainer}>
<h2 data-loading className={styles.title}>
Traffic in {metric.name}
Traffic in {metric.environment} {hour}
</h2>
</div>

View File

@ -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<IFeatureViewParams>();
const { feature } = useFeature(projectId, featureId);
const [featureMetrics, setFeatureMetrics] = useState<IEnvironmentMetrics[]>(
[]
);
const { metrics } = useFeatureMetrics(projectId, featureId);
useEffect(() => {
const featureMetricList = feature?.environments.map(env => {
const metrics = data.lastHourUsage.find(
const featureMetrics = feature?.environments.map(env => {
const metric = metrics.lastHourUsage.find(
metric => metric.environment === env.name
);
if (!metrics) {
if (!metric) {
return {
name: env.name,
environment: env.name,
yes: 0,
no: 0,
timestamp: '',
timestamp: ''
};
}
return {
name: env.name,
yes: metrics.yes,
no: metrics.no,
timestamp: metrics.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 (
<FeatureEnvironmentMetrics
className={styles.firstContainer}
key={metric.name}
key={metric.environment}
metric={metric}
/>
);
}
return (
<FeatureEnvironmentMetrics
key={metric.name}
key={metric.environment}
metric={metric}
/>
);
@ -109,7 +70,7 @@ const FeatureOverviewMetrics = () => {
return (
<FeatureEnvironmentMetrics
primaryMetric
key={metric.name}
key={metric.environment}
metric={metric}
/>
);
@ -119,7 +80,7 @@ const FeatureOverviewMetrics = () => {
return (
<FeatureEnvironmentMetrics
className={styles.firstContainer}
key={metric.name}
key={metric.environment}
metric={metric}
/>
);
@ -127,7 +88,7 @@ const FeatureOverviewMetrics = () => {
return (
<FeatureEnvironmentMetrics
key={metric.name}
key={metric.environment}
metric={metric}
/>
);

View File

@ -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<IFeatureMetrics>(
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;

View File

@ -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[]
}