diff --git a/frontend/src/component/admin/network/Network.tsx b/frontend/src/component/admin/network/Network.tsx
index cd82e8f547..0943df226e 100644
--- a/frontend/src/component/admin/network/Network.tsx
+++ b/frontend/src/component/admin/network/Network.tsx
@@ -14,6 +14,9 @@ const NetworkTraffic = lazy(() => import('./NetworkTraffic/NetworkTraffic'));
const NetworkTrafficUsage = lazy(
() => import('./NetworkTrafficUsage/NetworkTrafficUsage'),
);
+const BackendConnections = lazy(
+ () => import('./NetworkTrafficUsage/BackendConnections'),
+);
const tabs = [
{
@@ -28,17 +31,31 @@ const tabs = [
label: 'Connected Edges',
path: '/admin/network/connected-edges',
},
+];
+
+const seatModelTabs = [
{
label: 'Data Usage',
path: '/admin/network/data-usage',
},
];
+const consumptionModelTabs = [
+ {
+ label: 'Backend Connections',
+ path: '/admin/network/backend-connections',
+ },
+];
+
export const Network = () => {
const { pathname } = useLocation();
const edgeObservabilityEnabled = useUiFlag('edgeObservability');
+ const consumptionModelEnabled = useUiFlag('consumptionModel');
+ const allTabs = consumptionModelEnabled
+ ? [...tabs, ...consumptionModelTabs]
+ : [...tabs, ...seatModelTabs];
- const filteredTabs = tabs.filter(
+ const filteredTabs = allTabs.filter(
({ label }) => label !== 'Connected Edges' || edgeObservabilityEnabled,
);
@@ -82,6 +99,10 @@ export const Network = () => {
path='data-usage'
element={}
/>
+ }
+ />
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/BackendConnections.tsx b/frontend/src/component/admin/network/NetworkTrafficUsage/BackendConnections.tsx
new file mode 100644
index 0000000000..2c0c4dfdfb
--- /dev/null
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/BackendConnections.tsx
@@ -0,0 +1,75 @@
+import type { FC } from 'react';
+import { usePageTitle } from 'hooks/usePageTitle';
+import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
+import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
+import { Alert, Box } from '@mui/material';
+import { PeriodSelector } from './PeriodSelector';
+import { Bar } from 'react-chartjs-2';
+import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
+import { getChartLabel } from './chart-functions';
+import { useConsumptionStats } from './hooks/useStats';
+import { StyledBox, TopRow } from './SharedComponents';
+import {
+ BarElement,
+ CategoryScale,
+ Chart as ChartJS,
+ Legend,
+ LinearScale,
+ Title,
+ Tooltip,
+} from 'chart.js';
+import annotationPlugin from 'chartjs-plugin-annotation';
+import { useChartDataSelection } from './hooks/useChartDataSelection';
+
+export const BackendConnections: FC = () => {
+ usePageTitle('Network - Backend Connections');
+
+ const { isOss } = useUiConfig();
+
+ const { chartDataSelection, setChartDataSelection, options } =
+ useChartDataSelection();
+
+ const { chartData } = useConsumptionStats(chartDataSelection);
+
+ return (
+ Not enabled.}
+ elseShow={
+ <>
+
+
+
+ 1 connection = 7200 backend SDK requests per day
+
+
+
+
+
+ >
+ }
+ />
+ );
+};
+
+// Register dependencies that we need to draw the chart.
+ChartJS.register(
+ annotationPlugin,
+ CategoryScale,
+ LinearScale,
+ BarElement,
+ Title,
+ Tooltip,
+ Legend,
+);
+
+// Use a default export to lazy-load the charting library.
+export default BackendConnections;
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/NetworkTrafficUsage.tsx b/frontend/src/component/admin/network/NetworkTrafficUsage/NetworkTrafficUsage.tsx
index 54d931d54a..1484df2426 100644
--- a/frontend/src/component/admin/network/NetworkTrafficUsage/NetworkTrafficUsage.tsx
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/NetworkTrafficUsage.tsx
@@ -1,172 +1,45 @@
-import { useMemo, useState, useEffect, type FC } from 'react';
+import { type FC, useEffect, useMemo, useState } from 'react';
import useTheme from '@mui/material/styles/useTheme';
import styled from '@mui/material/styles/styled';
import { usePageTitle } from 'hooks/usePageTitle';
import Select from 'component/common/select';
-import Box from '@mui/system/Box';
import { Link as RouterLink } from 'react-router-dom';
import { Alert, Link } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import {
- Chart as ChartJS,
- type ChartOptions,
- CategoryScale,
- LinearScale,
BarElement,
+ CategoryScale,
+ Chart as ChartJS,
+ Legend,
+ LinearScale,
Title,
Tooltip,
- Legend,
} from 'chart.js';
import { Bar } from 'react-chartjs-2';
-import {
- useInstanceTrafficMetrics,
- useTrafficSearch,
-} from 'hooks/api/getters/useInstanceTrafficMetrics/useInstanceTrafficMetrics';
-import type { Theme } from '@mui/material/styles/createTheme';
+import { useInstanceTrafficMetrics } from 'hooks/api/getters/useInstanceTrafficMetrics/useInstanceTrafficMetrics';
import Grid from '@mui/material/Grid';
import { NetworkTrafficUsagePlanSummary } from './NetworkTrafficUsagePlanSummary';
import annotationPlugin from 'chartjs-plugin-annotation';
import {
- useTrafficDataEstimation,
calculateEstimatedMonthlyCost as deprecatedCalculateEstimatedMonthlyCost,
+ useTrafficDataEstimation,
} from 'hooks/useTrafficData';
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
-import { formatTickValue } from 'component/common/Chart/formatTickValue';
import { useTrafficLimit } from './hooks/useTrafficLimit';
import { BILLING_TRAFFIC_BUNDLE_PRICE } from 'component/admin/billing/BillingDashboard/BillingPlan/BillingPlan';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { PeriodSelector } from './PeriodSelector';
import { useUiFlag } from 'hooks/useUiFlag';
import { OverageInfo, RequestSummary } from './RequestSummary';
-import { averageTrafficPreviousMonths } from './average-traffic-previous-months';
-import {
- calculateTotalUsage,
- calculateOverageCost,
- calculateEstimatedMonthlyCost,
-} from 'utils/traffic-calculations';
-import { currentDate, currentMonth } from './dates';
-import { type ChartDataSelection, toDateRange } from './chart-data-selection';
-import {
- type ChartDatasetType,
- getChartLabel,
- toChartData as newToChartData,
- toConnectionChartData,
-} from './chart-functions';
-import { periodsRecord, selectablePeriods } from './selectable-periods';
-
-const StyledBox = styled(Box)(({ theme }) => ({
- display: 'grid',
- gap: theme.spacing(5),
-}));
-
-const createBarChartOptions = (
- theme: Theme,
- tooltipTitleCallback: (tooltipItems: any) => string,
- includedTraffic?: number,
-): ChartOptions<'bar'> => ({
- plugins: {
- annotation: {
- clip: false,
- annotations: {
- line: {
- type: 'line',
- borderDash: [5, 5],
- yMin: includedTraffic ? includedTraffic / 30 : 0,
- yMax: includedTraffic ? includedTraffic / 30 : 0,
- borderColor: 'gray',
- borderWidth: 1,
- display: !!includedTraffic,
-
- label: {
- backgroundColor: 'rgba(192, 192, 192, 0.8)',
- color: 'black',
- padding: {
- top: 10,
- bottom: 10,
- left: 10,
- right: 10,
- },
- content: 'Average daily requests included in your plan',
- display: !!includedTraffic,
- },
- },
- },
- },
- legend: {
- position: 'bottom',
- labels: {
- color: theme.palette.text.primary,
- pointStyle: 'circle',
- usePointStyle: true,
- boxHeight: 6,
- padding: 15,
- boxPadding: 5,
- },
- },
- tooltip: {
- backgroundColor: theme.palette.background.paper,
- titleColor: theme.palette.text.primary,
- bodyColor: theme.palette.text.primary,
- bodySpacing: 6,
- padding: {
- top: 20,
- bottom: 20,
- left: 30,
- right: 30,
- },
- borderColor: 'rgba(0, 0, 0, 0.05)',
- borderWidth: 3,
- usePointStyle: true,
- caretSize: 0,
- boxPadding: 10,
- callbacks: {
- title: tooltipTitleCallback,
- },
- },
- },
- responsive: true,
- scales: {
- x: {
- stacked: true,
- ticks: {
- color: theme.palette.text.secondary,
- },
- grid: {
- display: false,
- },
- },
- y: {
- stacked: true,
- ticks: {
- color: theme.palette.text.secondary,
- maxTicksLimit: 5,
- callback: formatTickValue,
- },
- grid: {
- drawBorder: false,
- },
- },
- },
- elements: {
- bar: {
- borderRadius: 5,
- },
- },
- interaction: {
- mode: 'index',
- intersect: false,
- },
-});
-
-const TopRow = styled('div')(({ theme }) => ({
- display: 'flex',
- flexFlow: 'row wrap',
- justifyContent: 'space-between',
- gap: theme.spacing(2, 4),
- alignItems: 'start',
-}));
+import { calculateOverageCost } from 'utils/traffic-calculations';
+import { currentMonth } from './dates';
+import { type ChartDatasetType, getChartLabel } from './chart-functions';
+import { createBarChartOptions } from './bar-chart-options';
+import { useTrafficStats } from './hooks/useStats';
+import { BoldText, StyledBox, TopRow } from './SharedComponents';
+import { useChartDataSelection } from './hooks/useChartDataSelection';
const TrafficInfoBoxes = styled('div')(({ theme }) => ({
display: 'grid',
@@ -175,123 +48,17 @@ const TrafficInfoBoxes = styled('div')(({ theme }) => ({
gap: theme.spacing(2, 4),
}));
-const BoldText = styled('span')(({ theme }) => ({
- fontWeight: 'bold',
-}));
-
-const useTrafficStats = (
- includedTraffic: number,
- chartDataSelection: ChartDataSelection,
-) => {
- const consumptionModelEnabled = useUiFlag('consumptionModel');
- const { result } = useTrafficSearch(
- chartDataSelection.grouping,
- toDateRange(chartDataSelection, currentDate),
- );
- const results = useMemo(() => {
- if (result.state !== 'success') {
- return {
- chartData: { datasets: [], labels: [] },
- usageTotal: 0,
- overageCost: 0,
- estimatedMonthlyCost: 0,
- requestSummaryUsage: 0,
- };
- }
- const traffic = result.data;
-
- const chartData = consumptionModelEnabled
- ? toConnectionChartData(traffic)
- : newToChartData(traffic);
- const usageTotal = calculateTotalUsage(traffic);
- const overageCost = calculateOverageCost(
- usageTotal,
- includedTraffic,
- BILLING_TRAFFIC_BUNDLE_PRICE,
- );
-
- const estimatedMonthlyCost = calculateEstimatedMonthlyCost(
- traffic.apiData,
- includedTraffic,
- currentDate,
- BILLING_TRAFFIC_BUNDLE_PRICE,
- );
-
- const requestSummaryUsage =
- chartDataSelection.grouping === 'daily'
- ? usageTotal
- : averageTrafficPreviousMonths(traffic);
-
- return {
- chartData,
- usageTotal,
- overageCost,
- estimatedMonthlyCost,
- requestSummaryUsage,
- };
- }, [
- JSON.stringify(result),
- includedTraffic,
- JSON.stringify(chartDataSelection),
- ]);
-
- return results;
-};
-
const NewNetworkTrafficUsage: FC = () => {
usePageTitle('Network - Data Usage');
- const theme = useTheme();
const estimateTrafficDataCost = useUiFlag('estimateTrafficDataCost');
const { isOss } = useUiConfig();
- const { locationSettings } = useLocationSettings();
-
- const [chartDataSelection, setChartDataSelection] =
- useState({
- grouping: 'daily',
- month: selectablePeriods[0].key,
- });
-
const includedTraffic = useTrafficLimit();
- const options = useMemo(() => {
- return createBarChartOptions(
- theme,
- (tooltipItems: any) => {
- if (chartDataSelection.grouping === 'daily') {
- const periodItem = periodsRecord[chartDataSelection.month];
- const tooltipDate = new Date(
- periodItem.year,
- periodItem.month,
- Number.parseInt(tooltipItems[0].label),
- );
- return tooltipDate.toLocaleDateString(
- locationSettings?.locale ?? 'en-US',
- {
- month: 'long',
- day: 'numeric',
- year: 'numeric',
- },
- );
- } else {
- const timestamp = Date.parse(tooltipItems[0].label);
- if (Number.isNaN(timestamp)) {
- return 'Current month to date';
- }
- return new Date(timestamp).toLocaleDateString(
- locationSettings?.locale ?? 'en-US',
- {
- month: 'long',
- year: 'numeric',
- },
- );
- }
- },
- includedTraffic,
- );
- }, [theme, chartDataSelection]);
+ const { chartDataSelection, setChartDataSelection, options } =
+ useChartDataSelection(includedTraffic);
const {
chartData,
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/SharedComponents.tsx b/frontend/src/component/admin/network/NetworkTrafficUsage/SharedComponents.tsx
new file mode 100644
index 0000000000..a6f29c97cf
--- /dev/null
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/SharedComponents.tsx
@@ -0,0 +1,19 @@
+import styled from '@mui/material/styles/styled';
+import Box from '@mui/system/Box';
+
+export const StyledBox = styled(Box)(({ theme }) => ({
+ display: 'grid',
+ gap: theme.spacing(5),
+}));
+
+export const TopRow = styled('div')(({ theme }) => ({
+ display: 'flex',
+ flexFlow: 'row wrap',
+ justifyContent: 'space-between',
+ gap: theme.spacing(2, 4),
+ alignItems: 'start',
+}));
+
+export const BoldText = styled('span')(({ theme }) => ({
+ fontWeight: 'bold',
+}));
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/bar-chart-options.ts b/frontend/src/component/admin/network/NetworkTrafficUsage/bar-chart-options.ts
new file mode 100644
index 0000000000..2f09ab5d23
--- /dev/null
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/bar-chart-options.ts
@@ -0,0 +1,102 @@
+import type { Theme } from '@mui/material/styles/createTheme';
+import type { ChartOptions } from 'chart.js';
+import { formatTickValue } from 'component/common/Chart/formatTickValue';
+
+export const createBarChartOptions = (
+ theme: Theme,
+ tooltipTitleCallback: (tooltipItems: any) => string,
+ includedTraffic?: number,
+): ChartOptions<'bar'> => ({
+ plugins: {
+ annotation: {
+ clip: false,
+ annotations: {
+ line: {
+ type: 'line',
+ borderDash: [5, 5],
+ yMin: includedTraffic ? includedTraffic / 30 : 0,
+ yMax: includedTraffic ? includedTraffic / 30 : 0,
+ borderColor: 'gray',
+ borderWidth: 1,
+ display: !!includedTraffic,
+
+ label: {
+ backgroundColor: 'rgba(192, 192, 192, 0.8)',
+ color: 'black',
+ padding: {
+ top: 10,
+ bottom: 10,
+ left: 10,
+ right: 10,
+ },
+ content: 'Average daily requests included in your plan',
+ display: !!includedTraffic,
+ },
+ },
+ },
+ },
+ legend: {
+ position: 'bottom',
+ labels: {
+ color: theme.palette.text.primary,
+ pointStyle: 'circle',
+ usePointStyle: true,
+ boxHeight: 6,
+ padding: 15,
+ boxPadding: 5,
+ },
+ },
+ tooltip: {
+ backgroundColor: theme.palette.background.paper,
+ titleColor: theme.palette.text.primary,
+ bodyColor: theme.palette.text.primary,
+ bodySpacing: 6,
+ padding: {
+ top: 20,
+ bottom: 20,
+ left: 30,
+ right: 30,
+ },
+ borderColor: 'rgba(0, 0, 0, 0.05)',
+ borderWidth: 3,
+ usePointStyle: true,
+ caretSize: 0,
+ boxPadding: 10,
+ callbacks: {
+ title: tooltipTitleCallback,
+ },
+ },
+ },
+ responsive: true,
+ scales: {
+ x: {
+ stacked: true,
+ ticks: {
+ color: theme.palette.text.secondary,
+ },
+ grid: {
+ display: false,
+ },
+ },
+ y: {
+ stacked: true,
+ ticks: {
+ color: theme.palette.text.secondary,
+ maxTicksLimit: 5,
+ callback: formatTickValue,
+ },
+ grid: {
+ drawBorder: false,
+ },
+ },
+ },
+ elements: {
+ bar: {
+ borderRadius: 5,
+ },
+ },
+ interaction: {
+ mode: 'index',
+ intersect: false,
+ },
+});
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.test.ts b/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.test.ts
index ddcd3e8fc0..097f9988fa 100644
--- a/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.test.ts
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.test.ts
@@ -1,5 +1,5 @@
import type { TrafficUsageDataSegmentedCombinedSchema } from 'openapi';
-import { toChartData } from './chart-functions';
+import { toTrafficUsageChartData } from './chart-functions';
import { endpointsInfo } from './endpoint-info';
describe('toChartData', () => {
@@ -67,7 +67,7 @@ describe('toChartData', () => {
],
};
- expect(toChartData(input)).toMatchObject(expectedOutput);
+ expect(toTrafficUsageChartData(input)).toMatchObject(expectedOutput);
});
test('daily data conversion', () => {
@@ -121,7 +121,7 @@ describe('toChartData', () => {
),
};
- expect(toChartData(input)).toMatchObject(expectedOutput);
+ expect(toTrafficUsageChartData(input)).toMatchObject(expectedOutput);
});
test('sorts endpoints according to endpoint data spec', () => {
@@ -146,6 +146,6 @@ describe('toChartData', () => {
],
};
- expect(toChartData(input)).toMatchObject(expectedOutput);
+ expect(toTrafficUsageChartData(input)).toMatchObject(expectedOutput);
});
});
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.ts b/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.ts
index 44c86a9eeb..1ba2a98fce 100644
--- a/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.ts
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/chart-functions.ts
@@ -13,7 +13,7 @@ import { formatDay, formatMonth } from './dates';
import type { ChartDataSelection } from './chart-data-selection';
export type ChartDatasetType = ChartDataset<'bar'>;
-export const toChartData = (
+export const toTrafficUsageChartData = (
traffic: TrafficUsageDataSegmentedCombinedSchema,
): { datasets: ChartDatasetType[]; labels: string[] } => {
const { newRecord, labels } = getLabelsAndRecords(traffic);
@@ -47,6 +47,7 @@ export const toConnectionChartData = (
): { datasets: ChartDatasetType[]; labels: string[] } => {
const { newRecord, labels } = getLabelsAndRecords(traffic);
const datasets = traffic.apiData
+ .filter((apiData) => apiData.apiPath === '/api/client')
.sort(
(item1, item2) =>
endpointsInfo[item1.apiPath].order -
@@ -61,11 +62,14 @@ export const toConnectionChartData = (
if (traffic.grouping === 'monthly') {
// 1 connections = 7200 * days in month requests per day
const daysInMonth = getDaysInMonth(date);
- record[dataPoint.period] =
- requestCount / (daysInMonth * 7200);
+ record[dataPoint.period] = Number(
+ (requestCount / (daysInMonth * 7200)).toFixed(1),
+ );
} else {
// 1 connection = 7200 requests per day
- record[dataPoint.period] = requestCount / 7200;
+ record[dataPoint.period] = Number(
+ (requestCount / 7200).toFixed(1),
+ );
}
}
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/hooks/useChartDataSelection.ts b/frontend/src/component/admin/network/NetworkTrafficUsage/hooks/useChartDataSelection.ts
new file mode 100644
index 0000000000..9b6618809f
--- /dev/null
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/hooks/useChartDataSelection.ts
@@ -0,0 +1,56 @@
+import { useMemo, useState } from 'react';
+import type { ChartDataSelection } from '../chart-data-selection';
+import { periodsRecord, selectablePeriods } from '../selectable-periods';
+import { createBarChartOptions } from '../bar-chart-options';
+import useTheme from '@mui/material/styles/useTheme';
+import { useLocationSettings } from 'hooks/useLocationSettings';
+
+export const useChartDataSelection = (includedTraffic?: number) => {
+ const theme = useTheme();
+ const { locationSettings } = useLocationSettings();
+
+ const [chartDataSelection, setChartDataSelection] =
+ useState({
+ grouping: 'daily',
+ month: selectablePeriods[0].key,
+ });
+
+ const options = useMemo(() => {
+ return createBarChartOptions(
+ theme,
+ (tooltipItems: any) => {
+ if (chartDataSelection.grouping === 'daily') {
+ const periodItem = periodsRecord[chartDataSelection.month];
+ const tooltipDate = new Date(
+ periodItem.year,
+ periodItem.month,
+ Number.parseInt(tooltipItems[0].label),
+ );
+ return tooltipDate.toLocaleDateString(
+ locationSettings?.locale ?? 'en-US',
+ {
+ month: 'long',
+ day: 'numeric',
+ year: 'numeric',
+ },
+ );
+ } else {
+ const timestamp = Date.parse(tooltipItems[0].label);
+ if (Number.isNaN(timestamp)) {
+ return 'Current month to date';
+ }
+ return new Date(timestamp).toLocaleDateString(
+ locationSettings?.locale ?? 'en-US',
+ {
+ month: 'long',
+ year: 'numeric',
+ },
+ );
+ }
+ },
+ includedTraffic,
+ );
+ }, [theme, chartDataSelection]);
+
+ return { chartDataSelection, setChartDataSelection, options };
+};
diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/hooks/useStats.ts b/frontend/src/component/admin/network/NetworkTrafficUsage/hooks/useStats.ts
new file mode 100644
index 0000000000..1fc29c5335
--- /dev/null
+++ b/frontend/src/component/admin/network/NetworkTrafficUsage/hooks/useStats.ts
@@ -0,0 +1,98 @@
+import { type ChartDataSelection, toDateRange } from '../chart-data-selection';
+import { useTrafficSearch } from 'hooks/api/getters/useInstanceTrafficMetrics/useInstanceTrafficMetrics';
+import { currentDate } from '../dates';
+import { useMemo } from 'react';
+import {
+ toTrafficUsageChartData as newToChartData,
+ toConnectionChartData,
+} from '../chart-functions';
+import {
+ calculateEstimatedMonthlyCost,
+ calculateOverageCost,
+ calculateTotalUsage,
+} from 'utils/traffic-calculations';
+import { BILLING_TRAFFIC_BUNDLE_PRICE } from '../../../billing/BillingDashboard/BillingPlan/BillingPlan';
+import { averageTrafficPreviousMonths } from '../average-traffic-previous-months';
+
+export const useTrafficStats = (
+ includedTraffic: number,
+ chartDataSelection: ChartDataSelection,
+) => {
+ const { result } = useTrafficSearch(
+ chartDataSelection.grouping,
+ toDateRange(chartDataSelection, currentDate),
+ );
+ const results = useMemo(() => {
+ if (result.state !== 'success') {
+ return {
+ chartData: { datasets: [], labels: [] },
+ usageTotal: 0,
+ overageCost: 0,
+ estimatedMonthlyCost: 0,
+ requestSummaryUsage: 0,
+ };
+ }
+ const traffic = result.data;
+
+ const chartData = newToChartData(traffic);
+ const usageTotal = calculateTotalUsage(traffic);
+ const overageCost = calculateOverageCost(
+ usageTotal,
+ includedTraffic,
+ BILLING_TRAFFIC_BUNDLE_PRICE,
+ );
+
+ const estimatedMonthlyCost = calculateEstimatedMonthlyCost(
+ traffic.apiData,
+ includedTraffic,
+ currentDate,
+ BILLING_TRAFFIC_BUNDLE_PRICE,
+ );
+
+ const requestSummaryUsage =
+ chartDataSelection.grouping === 'daily'
+ ? usageTotal
+ : averageTrafficPreviousMonths(traffic);
+
+ return {
+ chartData,
+ usageTotal,
+ overageCost,
+ estimatedMonthlyCost,
+ requestSummaryUsage,
+ };
+ }, [
+ JSON.stringify(result),
+ includedTraffic,
+ JSON.stringify(chartDataSelection),
+ ]);
+
+ return results;
+};
+
+export const useConsumptionStats = (chartDataSelection: ChartDataSelection) => {
+ const { result } = useTrafficSearch(
+ chartDataSelection.grouping,
+ toDateRange(chartDataSelection, currentDate),
+ );
+ const results = useMemo(() => {
+ if (result.state !== 'success') {
+ return {
+ chartData: { datasets: [], labels: [] },
+ usageTotal: 0,
+ overageCost: 0,
+ estimatedMonthlyCost: 0,
+ requestSummaryUsage: 0,
+ };
+ }
+ const traffic = result.data;
+
+ const chartData = toConnectionChartData(traffic);
+
+ return {
+ chartData,
+ };
+ }, [JSON.stringify(result), JSON.stringify(chartDataSelection)]);
+
+ return results;
+};