1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-03 01:18:43 +02:00
unleash.unleash/frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureMetrics.tsx
2023-03-30 16:57:35 +01:00

130 lines
4.9 KiB
TypeScript

import { useFeatureMetricsRaw } from 'hooks/api/getters/useFeatureMetricsRaw/useFeatureMetricsRaw';
import { PageContent } from 'component/common/PageContent/PageContent';
import { useEffect, useMemo, useState } from 'react';
import {
FEATURE_METRIC_HOURS_BACK_MAX,
FeatureMetricsHours,
} from './FeatureMetricsHours/FeatureMetricsHours';
import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
import { Grid } from '@mui/material';
import { FeatureMetricsContent } from './FeatureMetricsContent/FeatureMetricsContent';
import { useQueryStringNumberState } from 'hooks/useQueryStringNumberState';
import { useQueryStringState } from 'hooks/useQueryStringState';
import { FeatureMetricsChips } from './FeatureMetricsChips/FeatureMetricsChips';
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { usePageTitle } from 'hooks/usePageTitle';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
export const FeatureMetrics = () => {
const projectId = useRequiredPathParam('projectId');
const featureId = useRequiredPathParam('featureId');
const environments = useFeatureMetricsEnvironments(projectId, featureId);
const applications = useFeatureMetricsApplications(featureId);
usePageTitle('Metrics');
const [hoursBack = FEATURE_METRIC_HOURS_BACK_MAX, setHoursBack] =
useQueryStringNumberState('hoursBack');
const { featureMetrics } = useFeatureMetricsRaw(featureId, hoursBack);
// Keep a cache of the fetched metrics so that we can
// show the cached result while fetching new metrics.
const [cachedMetrics, setCachedMetrics] = useState<
Readonly<IFeatureMetricsRaw[]> | undefined
>(featureMetrics);
useEffect(() => {
featureMetrics && setCachedMetrics(featureMetrics);
}, [featureMetrics]);
const defaultEnvironment = Array.from(environments)[0];
const defaultApplication = Array.from(applications)[0];
const [environment = defaultEnvironment, setEnvironment] =
useQueryStringState('environment');
const [application = defaultApplication, setApplication] =
useQueryStringState('application');
const filteredMetrics = useMemo(() => {
return cachedMetrics
?.filter(metric => metric.environment === environment)
.filter(metric => metric.appName === application);
}, [cachedMetrics, environment, application]);
if (!filteredMetrics) {
return null;
}
return (
<PageContent>
<Grid container component="header" spacing={2}>
<Grid item xs={12} md={5}>
<ConditionallyRender
condition={environments.size > 0}
show={
<FeatureMetricsChips
title="Environments"
values={environments}
value={environment}
setValue={setEnvironment}
/>
}
/>
</Grid>
<Grid item xs={12} md={5}>
<ConditionallyRender
condition={applications.size > 0}
show={
<FeatureMetricsChips
title="Applications"
values={applications}
value={application}
setValue={setApplication}
/>
}
/>
</Grid>
<Grid item xs={12} md={2}>
<FeatureMetricsHours
hoursBack={hoursBack}
setHoursBack={setHoursBack}
/>
</Grid>
</Grid>
<FeatureMetricsContent
metrics={filteredMetrics}
hoursBack={hoursBack}
/>
</PageContent>
);
};
// Get all the environment names for a feature,
// not just the one's we have metrics for.
const useFeatureMetricsEnvironments = (
projectId: string,
featureId: string
): Set<string> => {
const { feature } = useFeature(projectId, featureId);
const environments = feature.environments.map(environment => {
return environment.name;
});
return new Set(environments);
};
// Get all application names for a feature. Fetch apps for the max time range
// so that the list of apps doesn't change when selecting a shorter range.
const useFeatureMetricsApplications = (featureId: string): Set<string> => {
const { featureMetrics = [] } = useFeatureMetricsRaw(
featureId,
FEATURE_METRIC_HOURS_BACK_MAX
);
const applications = featureMetrics.map(metric => {
return metric.appName;
});
return new Set(applications);
};