mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: first draft of chart for instance traffic in frontend (#2670)
## What We've already added the backend for this. This is the initial work for drawing a chart for instance traffic in the frontend. It requires the environment variable `PROMETHEUS_API` set to a valid prometheus-query-language (promql) supported backend, such as Prometheus itself or Victoria Metrics. Besides, at the moment we're hiding this functionality behind the flag `UNLEASH_EXPERIMENTAL_NETWORK_VIEW` which has to be set to true Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai> Co-authored-by: Gastón Fournier <gaston@getunleash.ai>
This commit is contained in:
		
							parent
							
								
									8e5ca352c3
								
							
						
					
					
						commit
						23094b016e
					
				@ -87,6 +87,16 @@ function AdminMenu() {
 | 
				
			|||||||
                        </CenteredNavLink>
 | 
					                        </CenteredNavLink>
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
 | 
					                {flags.networkView && (
 | 
				
			||||||
 | 
					                    <Tab
 | 
				
			||||||
 | 
					                        value="/admin/traffic"
 | 
				
			||||||
 | 
					                        label={
 | 
				
			||||||
 | 
					                            <CenteredNavLink to="/admin/traffic">
 | 
				
			||||||
 | 
					                                Traffic
 | 
				
			||||||
 | 
					                            </CenteredNavLink>
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                )}
 | 
				
			||||||
                {isBilling && (
 | 
					                {isBilling && (
 | 
				
			||||||
                    <Tab
 | 
					                    <Tab
 | 
				
			||||||
                        value="/admin/billing"
 | 
					                        value="/admin/billing"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										11
									
								
								frontend/src/component/admin/traffic/Traffic.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								frontend/src/component/admin/traffic/Traffic.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import InstanceMetricsChart from './TrafficMetricsChart';
 | 
				
			||||||
 | 
					import AdminMenu from '../menu/AdminMenu';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Traffic = () => {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            <AdminMenu />
 | 
				
			||||||
 | 
					            <InstanceMetricsChart />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										212
									
								
								frontend/src/component/admin/traffic/TrafficMetricsChart.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								frontend/src/component/admin/traffic/TrafficMetricsChart.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,212 @@
 | 
				
			|||||||
 | 
					import {
 | 
				
			||||||
 | 
					    InstanceMetrics,
 | 
				
			||||||
 | 
					    useInstanceMetrics,
 | 
				
			||||||
 | 
					} from '../../../hooks/api/getters/useInstanceMetrics/useInstanceMetrics';
 | 
				
			||||||
 | 
					import { useMemo, VFC } from 'react';
 | 
				
			||||||
 | 
					import { Line } from 'react-chartjs-2';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    CategoryScale,
 | 
				
			||||||
 | 
					    Chart as ChartJS,
 | 
				
			||||||
 | 
					    ChartData,
 | 
				
			||||||
 | 
					    ChartDataset,
 | 
				
			||||||
 | 
					    ChartOptions,
 | 
				
			||||||
 | 
					    Legend,
 | 
				
			||||||
 | 
					    LinearScale,
 | 
				
			||||||
 | 
					    LineElement,
 | 
				
			||||||
 | 
					    PointElement,
 | 
				
			||||||
 | 
					    TimeScale,
 | 
				
			||||||
 | 
					    Title,
 | 
				
			||||||
 | 
					    Tooltip,
 | 
				
			||||||
 | 
					} from 'chart.js';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    ILocationSettings,
 | 
				
			||||||
 | 
					    useLocationSettings,
 | 
				
			||||||
 | 
					} from '../../../hooks/useLocationSettings';
 | 
				
			||||||
 | 
					import theme from '../../../themes/theme';
 | 
				
			||||||
 | 
					import { formatDateHM } from '../../../utils/formatDate';
 | 
				
			||||||
 | 
					import { RequestsPerSecondSchema } from 'openapi';
 | 
				
			||||||
 | 
					import 'chartjs-adapter-date-fns';
 | 
				
			||||||
 | 
					import { PaletteColor } from '@mui/material';
 | 
				
			||||||
 | 
					import { PageContent } from '../../common/PageContent/PageContent';
 | 
				
			||||||
 | 
					import { PageHeader } from '../../common/PageHeader/PageHeader';
 | 
				
			||||||
 | 
					import { Box } from '@mui/system';
 | 
				
			||||||
 | 
					import { current } from 'immer';
 | 
				
			||||||
 | 
					import { CyclicIterator } from 'utils/cyclicIterator';
 | 
				
			||||||
 | 
					interface IPoint {
 | 
				
			||||||
 | 
					    x: number;
 | 
				
			||||||
 | 
					    y: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ChartDatasetType = ChartDataset<'line', IPoint[]>;
 | 
				
			||||||
 | 
					type ChartDataType = ChartData<'line', IPoint[], string>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createChartPoints = (
 | 
				
			||||||
 | 
					    values: Array<Array<number | string>>,
 | 
				
			||||||
 | 
					    y: (m: string) => number
 | 
				
			||||||
 | 
					): IPoint[] => {
 | 
				
			||||||
 | 
					    return values.map(row => ({
 | 
				
			||||||
 | 
					        x: row[0] as number,
 | 
				
			||||||
 | 
					        y: y(row[1] as string),
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					const createInstanceChartOptions = (
 | 
				
			||||||
 | 
					    metrics: InstanceMetrics,
 | 
				
			||||||
 | 
					    locationSettings: ILocationSettings
 | 
				
			||||||
 | 
					): ChartOptions<'line'> => {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        locale: locationSettings.locale,
 | 
				
			||||||
 | 
					        responsive: true,
 | 
				
			||||||
 | 
					        maintainAspectRatio: false,
 | 
				
			||||||
 | 
					        interaction: {
 | 
				
			||||||
 | 
					            mode: 'index',
 | 
				
			||||||
 | 
					            intersect: false,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        plugins: {
 | 
				
			||||||
 | 
					            tooltip: {
 | 
				
			||||||
 | 
					                backgroundColor: 'white',
 | 
				
			||||||
 | 
					                bodyColor: theme.palette.text.primary,
 | 
				
			||||||
 | 
					                titleColor: theme.palette.grey[700],
 | 
				
			||||||
 | 
					                borderColor: theme.palette.primary.main,
 | 
				
			||||||
 | 
					                borderWidth: 1,
 | 
				
			||||||
 | 
					                padding: 10,
 | 
				
			||||||
 | 
					                boxPadding: 5,
 | 
				
			||||||
 | 
					                usePointStyle: true,
 | 
				
			||||||
 | 
					                callbacks: {
 | 
				
			||||||
 | 
					                    title: items =>
 | 
				
			||||||
 | 
					                        formatDateHM(
 | 
				
			||||||
 | 
					                            1000 * items[0].parsed.x,
 | 
				
			||||||
 | 
					                            locationSettings.locale
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                itemSort: (a, b) => b.parsed.y - a.parsed.y,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            legend: {
 | 
				
			||||||
 | 
					                position: 'top',
 | 
				
			||||||
 | 
					                align: 'end',
 | 
				
			||||||
 | 
					                labels: {
 | 
				
			||||||
 | 
					                    boxWidth: 10,
 | 
				
			||||||
 | 
					                    boxHeight: 10,
 | 
				
			||||||
 | 
					                    usePointStyle: true,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            title: {
 | 
				
			||||||
 | 
					                text: 'Requests per second in the last 6 hours',
 | 
				
			||||||
 | 
					                position: 'top',
 | 
				
			||||||
 | 
					                align: 'start',
 | 
				
			||||||
 | 
					                display: true,
 | 
				
			||||||
 | 
					                font: {
 | 
				
			||||||
 | 
					                    size: 16,
 | 
				
			||||||
 | 
					                    weight: '400',
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        scales: {
 | 
				
			||||||
 | 
					            y: {
 | 
				
			||||||
 | 
					                type: 'linear',
 | 
				
			||||||
 | 
					                title: {
 | 
				
			||||||
 | 
					                    display: true,
 | 
				
			||||||
 | 
					                    text: 'Requests per second',
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                // min: 0,
 | 
				
			||||||
 | 
					                suggestedMin: 0,
 | 
				
			||||||
 | 
					                ticks: { precision: 0 },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            x: {
 | 
				
			||||||
 | 
					                type: 'time',
 | 
				
			||||||
 | 
					                time: { unit: 'minute' },
 | 
				
			||||||
 | 
					                grid: { display: false },
 | 
				
			||||||
 | 
					                ticks: {
 | 
				
			||||||
 | 
					                    callback: (_, i, data) =>
 | 
				
			||||||
 | 
					                        formatDateHM(data[i].value, locationSettings.locale),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const toChartData = (
 | 
				
			||||||
 | 
					    rps: RequestsPerSecondSchema,
 | 
				
			||||||
 | 
					    color: PaletteColor,
 | 
				
			||||||
 | 
					    label: (name: string) => string
 | 
				
			||||||
 | 
					): ChartDatasetType[] => {
 | 
				
			||||||
 | 
					    if (rps.data?.result) {
 | 
				
			||||||
 | 
					        return rps.data.result.map(dataset => ({
 | 
				
			||||||
 | 
					            label: label(dataset.metric?.appName || 'unknown'),
 | 
				
			||||||
 | 
					            borderColor: color.main,
 | 
				
			||||||
 | 
					            backgroundColor: color.main,
 | 
				
			||||||
 | 
					            data: createChartPoints(dataset.values || [], y => parseFloat(y)),
 | 
				
			||||||
 | 
					            elements: {
 | 
				
			||||||
 | 
					                point: {
 | 
				
			||||||
 | 
					                    radius: 4,
 | 
				
			||||||
 | 
					                    pointStyle: 'circle',
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                line: {
 | 
				
			||||||
 | 
					                    borderDash: [8, 4],
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return [];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createInstanceChartData = (metrics?: InstanceMetrics): ChartDataType => {
 | 
				
			||||||
 | 
					    if (metrics) {
 | 
				
			||||||
 | 
					        const colors = new CyclicIterator<PaletteColor>([
 | 
				
			||||||
 | 
					            theme.palette.success,
 | 
				
			||||||
 | 
					            theme.palette.error,
 | 
				
			||||||
 | 
					            theme.palette.primary,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        let datasets: ChartDatasetType[] = [];
 | 
				
			||||||
 | 
					        for (let key in metrics) {
 | 
				
			||||||
 | 
					            datasets = datasets.concat(
 | 
				
			||||||
 | 
					                toChartData(
 | 
				
			||||||
 | 
					                    metrics[key],
 | 
				
			||||||
 | 
					                    colors.next(),
 | 
				
			||||||
 | 
					                    metricName => `${metricName}: ${key}`
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return { datasets };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return { datasets: [] };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const InstanceMetricsChart: VFC = () => {
 | 
				
			||||||
 | 
					    const { locationSettings } = useLocationSettings();
 | 
				
			||||||
 | 
					    const { metrics } = useInstanceMetrics();
 | 
				
			||||||
 | 
					    const options = useMemo(() => {
 | 
				
			||||||
 | 
					        return createInstanceChartOptions(metrics, locationSettings);
 | 
				
			||||||
 | 
					    }, [metrics, locationSettings]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const data = useMemo(() => {
 | 
				
			||||||
 | 
					        return createInstanceChartData(metrics);
 | 
				
			||||||
 | 
					    }, [metrics, locationSettings]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <PageContent header={<PageHeader title="Requests per second" />}>
 | 
				
			||||||
 | 
					            <Box sx={{ display: 'grid', gap: 4 }}>
 | 
				
			||||||
 | 
					                <div style={{ height: 400 }}>
 | 
				
			||||||
 | 
					                    <Line
 | 
				
			||||||
 | 
					                        data={data}
 | 
				
			||||||
 | 
					                        options={options}
 | 
				
			||||||
 | 
					                        aria-label="An instance metrics line chart with two lines: requests per second for admin API and requests per second for client API"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </Box>
 | 
				
			||||||
 | 
					        </PageContent>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					// Register dependencies that we need to draw the chart.
 | 
				
			||||||
 | 
					ChartJS.register(
 | 
				
			||||||
 | 
					    CategoryScale,
 | 
				
			||||||
 | 
					    LinearScale,
 | 
				
			||||||
 | 
					    PointElement,
 | 
				
			||||||
 | 
					    LineElement,
 | 
				
			||||||
 | 
					    TimeScale,
 | 
				
			||||||
 | 
					    Legend,
 | 
				
			||||||
 | 
					    Tooltip,
 | 
				
			||||||
 | 
					    Title
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Use a default export to lazy-load the charting library.
 | 
				
			||||||
 | 
					export default InstanceMetricsChart;
 | 
				
			||||||
@ -465,6 +465,17 @@ exports[`returns all baseRoutes 1`] = `
 | 
				
			|||||||
    "title": "Instance stats",
 | 
					    "title": "Instance stats",
 | 
				
			||||||
    "type": "protected",
 | 
					    "type": "protected",
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "component": [Function],
 | 
				
			||||||
 | 
					    "flag": "networkView",
 | 
				
			||||||
 | 
					    "menu": {
 | 
				
			||||||
 | 
					      "adminSettings": true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "parent": "/admin",
 | 
				
			||||||
 | 
					    "path": "/admin/traffic",
 | 
				
			||||||
 | 
					    "title": "Traffic",
 | 
				
			||||||
 | 
					    "type": "protected",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    "component": [Function],
 | 
					    "component": [Function],
 | 
				
			||||||
    "flag": "embedProxyFrontend",
 | 
					    "flag": "embedProxyFrontend",
 | 
				
			||||||
 | 
				
			|||||||
@ -60,6 +60,7 @@ import { CorsAdmin } from 'component/admin/cors';
 | 
				
			|||||||
import { InviteLink } from 'component/admin/users/InviteLink/InviteLink';
 | 
					import { InviteLink } from 'component/admin/users/InviteLink/InviteLink';
 | 
				
			||||||
import { Profile } from 'component/user/Profile/Profile';
 | 
					import { Profile } from 'component/user/Profile/Profile';
 | 
				
			||||||
import { InstanceAdmin } from '../admin/instance-admin/InstanceAdmin';
 | 
					import { InstanceAdmin } from '../admin/instance-admin/InstanceAdmin';
 | 
				
			||||||
 | 
					import { Traffic } from 'component/admin/traffic/Traffic';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const routes: IRoute[] = [
 | 
					export const routes: IRoute[] = [
 | 
				
			||||||
    // Splash
 | 
					    // Splash
 | 
				
			||||||
@ -509,6 +510,15 @@ export const routes: IRoute[] = [
 | 
				
			|||||||
        type: 'protected',
 | 
					        type: 'protected',
 | 
				
			||||||
        menu: { adminSettings: true },
 | 
					        menu: { adminSettings: true },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        path: '/admin/traffic',
 | 
				
			||||||
 | 
					        parent: '/admin',
 | 
				
			||||||
 | 
					        title: 'Traffic',
 | 
				
			||||||
 | 
					        component: Traffic,
 | 
				
			||||||
 | 
					        type: 'protected',
 | 
				
			||||||
 | 
					        menu: { adminSettings: true },
 | 
				
			||||||
 | 
					        flag: 'networkView',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        path: '/admin/cors',
 | 
					        path: '/admin/cors',
 | 
				
			||||||
        parent: '/admin',
 | 
					        parent: '/admin',
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					import useSWR from 'swr';
 | 
				
			||||||
 | 
					import { useMemo } from 'react';
 | 
				
			||||||
 | 
					import { formatApiPath } from 'utils/formatPath';
 | 
				
			||||||
 | 
					import handleErrorResponses from '../httpErrorResponseHandler';
 | 
				
			||||||
 | 
					import { RequestsPerSecondSchema } from 'openapi';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface InstanceMetrics {
 | 
				
			||||||
 | 
					    [key: string]: RequestsPerSecondSchema;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IInstanceMetricsResponse {
 | 
				
			||||||
 | 
					    metrics: InstanceMetrics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    refetch: () => void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    loading: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    error?: Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useInstanceMetrics = (): IInstanceMetricsResponse => {
 | 
				
			||||||
 | 
					    const { data, error, mutate } = useSWR(
 | 
				
			||||||
 | 
					        formatApiPath(`api/admin/metrics/rps`),
 | 
				
			||||||
 | 
					        fetcher
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return useMemo(
 | 
				
			||||||
 | 
					        () => ({
 | 
				
			||||||
 | 
					            metrics: data,
 | 
				
			||||||
 | 
					            loading: !error && !data,
 | 
				
			||||||
 | 
					            refetch: () => mutate(),
 | 
				
			||||||
 | 
					            error,
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					        [data, error, mutate]
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const fetcher = (path: string) => {
 | 
				
			||||||
 | 
					    return fetch(path)
 | 
				
			||||||
 | 
					        .then(handleErrorResponses('Instance Metrics'))
 | 
				
			||||||
 | 
					        .then(res => res.json());
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										80
									
								
								frontend/src/openapi/models/RequestsPerSecondSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								frontend/src/openapi/models/RequestsPerSecondSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unleash API
 | 
				
			||||||
 | 
					 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The version of the OpenAPI document: 4.19.0-beta.0
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
				
			||||||
 | 
					 * https://openapi-generator.tech
 | 
				
			||||||
 | 
					 * Do not edit the class manually.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { exists, mapValues } from '../runtime';
 | 
				
			||||||
 | 
					import type { RequestsPerSecondSchemaData } from './RequestsPerSecondSchemaData';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataFromJSON,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataFromJSONTyped,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataToJSON,
 | 
				
			||||||
 | 
					} from './RequestsPerSecondSchemaData';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface RequestsPerSecondSchema
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface RequestsPerSecondSchema {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSchema
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    status?: string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {RequestsPerSecondSchemaData}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSchema
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    data?: RequestsPerSecondSchemaData;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if a given object implements the RequestsPerSecondSchema interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function instanceOfRequestsPerSecondSchema(value: object): boolean {
 | 
				
			||||||
 | 
					    let isInstance = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return isInstance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaFromJSON(json: any): RequestsPerSecondSchema {
 | 
				
			||||||
 | 
					    return RequestsPerSecondSchemaFromJSONTyped(json, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): RequestsPerSecondSchema {
 | 
				
			||||||
 | 
					    if ((json === undefined) || (json === null)) {
 | 
				
			||||||
 | 
					        return json;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'status': !exists(json, 'status') ? undefined : json['status'],
 | 
				
			||||||
 | 
					        'data': !exists(json, 'data') ? undefined : RequestsPerSecondSchemaDataFromJSON(json['data']),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaToJSON(value?: RequestsPerSecondSchema | null): any {
 | 
				
			||||||
 | 
					    if (value === undefined) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (value === null) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'status': value.status,
 | 
				
			||||||
 | 
					        'data': RequestsPerSecondSchemaDataToJSON(value.data),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										80
									
								
								frontend/src/openapi/models/RequestsPerSecondSchemaData.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								frontend/src/openapi/models/RequestsPerSecondSchemaData.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unleash API
 | 
				
			||||||
 | 
					 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The version of the OpenAPI document: 4.19.0-beta.0
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
				
			||||||
 | 
					 * https://openapi-generator.tech
 | 
				
			||||||
 | 
					 * Do not edit the class manually.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { exists, mapValues } from '../runtime';
 | 
				
			||||||
 | 
					import type { RequestsPerSecondSchemaDataResultInner } from './RequestsPerSecondSchemaDataResultInner';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerFromJSON,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerFromJSONTyped,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerToJSON,
 | 
				
			||||||
 | 
					} from './RequestsPerSecondSchemaDataResultInner';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface RequestsPerSecondSchemaData
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface RequestsPerSecondSchemaData {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSchemaData
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    resultType?: string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * An array of values per metric. Each one represents a line in the graph labeled by its metric name
 | 
				
			||||||
 | 
					     * @type {Array<RequestsPerSecondSchemaDataResultInner>}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSchemaData
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    result?: Array<RequestsPerSecondSchemaDataResultInner>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if a given object implements the RequestsPerSecondSchemaData interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function instanceOfRequestsPerSecondSchemaData(value: object): boolean {
 | 
				
			||||||
 | 
					    let isInstance = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return isInstance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataFromJSON(json: any): RequestsPerSecondSchemaData {
 | 
				
			||||||
 | 
					    return RequestsPerSecondSchemaDataFromJSONTyped(json, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataFromJSONTyped(json: any, ignoreDiscriminator: boolean): RequestsPerSecondSchemaData {
 | 
				
			||||||
 | 
					    if ((json === undefined) || (json === null)) {
 | 
				
			||||||
 | 
					        return json;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'resultType': !exists(json, 'resultType') ? undefined : json['resultType'],
 | 
				
			||||||
 | 
					        'result': !exists(json, 'result') ? undefined : ((json['result'] as Array<any>).map(RequestsPerSecondSchemaDataResultInnerFromJSON)),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataToJSON(value?: RequestsPerSecondSchemaData | null): any {
 | 
				
			||||||
 | 
					    if (value === undefined) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (value === null) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'resultType': value.resultType,
 | 
				
			||||||
 | 
					        'result': value.result === undefined ? undefined : ((value.result as Array<any>).map(RequestsPerSecondSchemaDataResultInnerToJSON)),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unleash API
 | 
				
			||||||
 | 
					 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The version of the OpenAPI document: 4.19.0-beta.0
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
				
			||||||
 | 
					 * https://openapi-generator.tech
 | 
				
			||||||
 | 
					 * Do not edit the class manually.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { exists, mapValues } from '../runtime';
 | 
				
			||||||
 | 
					import type { RequestsPerSecondSchemaDataResultInnerMetric } from './RequestsPerSecondSchemaDataResultInnerMetric';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerMetricFromJSON,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerMetricFromJSONTyped,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerMetricToJSON,
 | 
				
			||||||
 | 
					} from './RequestsPerSecondSchemaDataResultInnerMetric';
 | 
				
			||||||
 | 
					import type { RequestsPerSecondSchemaDataResultInnerValuesInnerInner } from './RequestsPerSecondSchemaDataResultInnerValuesInnerInner';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerValuesInnerInnerFromJSON,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerValuesInnerInnerFromJSONTyped,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaDataResultInnerValuesInnerInnerToJSON,
 | 
				
			||||||
 | 
					} from './RequestsPerSecondSchemaDataResultInnerValuesInnerInner';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface RequestsPerSecondSchemaDataResultInner
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface RequestsPerSecondSchemaDataResultInner {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {RequestsPerSecondSchemaDataResultInnerMetric}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSchemaDataResultInner
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    metric?: RequestsPerSecondSchemaDataResultInnerMetric;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * An array of arrays. Each element of the array is an array of size 2 consisting of the 2 axis for the graph: in position zero the x axis represented as a number and position one the y axis represented as string
 | 
				
			||||||
 | 
					     * @type {Array<Array<RequestsPerSecondSchemaDataResultInnerValuesInnerInner>>}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSchemaDataResultInner
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    values?: Array<Array<RequestsPerSecondSchemaDataResultInnerValuesInnerInner>>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if a given object implements the RequestsPerSecondSchemaDataResultInner interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function instanceOfRequestsPerSecondSchemaDataResultInner(value: object): boolean {
 | 
				
			||||||
 | 
					    let isInstance = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return isInstance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerFromJSON(json: any): RequestsPerSecondSchemaDataResultInner {
 | 
				
			||||||
 | 
					    return RequestsPerSecondSchemaDataResultInnerFromJSONTyped(json, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerFromJSONTyped(json: any, ignoreDiscriminator: boolean): RequestsPerSecondSchemaDataResultInner {
 | 
				
			||||||
 | 
					    if ((json === undefined) || (json === null)) {
 | 
				
			||||||
 | 
					        return json;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'metric': !exists(json, 'metric') ? undefined : RequestsPerSecondSchemaDataResultInnerMetricFromJSON(json['metric']),
 | 
				
			||||||
 | 
					        'values': !exists(json, 'values') ? undefined : json['values'],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerToJSON(value?: RequestsPerSecondSchemaDataResultInner | null): any {
 | 
				
			||||||
 | 
					    if (value === undefined) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (value === null) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'metric': RequestsPerSecondSchemaDataResultInnerMetricToJSON(value.metric),
 | 
				
			||||||
 | 
					        'values': value.values,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unleash API
 | 
				
			||||||
 | 
					 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The version of the OpenAPI document: 4.19.0-beta.0
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
				
			||||||
 | 
					 * https://openapi-generator.tech
 | 
				
			||||||
 | 
					 * Do not edit the class manually.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { exists, mapValues } from '../runtime';
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A key value set representing the metric
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface RequestsPerSecondSchemaDataResultInnerMetric
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface RequestsPerSecondSchemaDataResultInnerMetric {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSchemaDataResultInnerMetric
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    appName?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if a given object implements the RequestsPerSecondSchemaDataResultInnerMetric interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function instanceOfRequestsPerSecondSchemaDataResultInnerMetric(value: object): boolean {
 | 
				
			||||||
 | 
					    let isInstance = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return isInstance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerMetricFromJSON(json: any): RequestsPerSecondSchemaDataResultInnerMetric {
 | 
				
			||||||
 | 
					    return RequestsPerSecondSchemaDataResultInnerMetricFromJSONTyped(json, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerMetricFromJSONTyped(json: any, ignoreDiscriminator: boolean): RequestsPerSecondSchemaDataResultInnerMetric {
 | 
				
			||||||
 | 
					    if ((json === undefined) || (json === null)) {
 | 
				
			||||||
 | 
					        return json;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'appName': !exists(json, 'appName') ? undefined : json['appName'],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerMetricToJSON(value?: RequestsPerSecondSchemaDataResultInnerMetric | null): any {
 | 
				
			||||||
 | 
					    if (value === undefined) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (value === null) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'appName': value.appName,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unleash API
 | 
				
			||||||
 | 
					 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The version of the OpenAPI document: 4.19.0-beta.0
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
				
			||||||
 | 
					 * https://openapi-generator.tech
 | 
				
			||||||
 | 
					 * Do not edit the class manually.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { exists, mapValues } from '../runtime';
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface RequestsPerSecondSchemaDataResultInnerValuesInnerInner
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export type RequestsPerSecondSchemaDataResultInnerValuesInnerInner = number | string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if a given object implements the RequestsPerSecondSchemaDataResultInnerValuesInnerInner interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function instanceOfRequestsPerSecondSchemaDataResultInnerValuesInnerInner(value: object): boolean {
 | 
				
			||||||
 | 
					    let isInstance = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return isInstance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerValuesInnerInnerFromJSON(json: any): RequestsPerSecondSchemaDataResultInnerValuesInnerInner {
 | 
				
			||||||
 | 
					    return RequestsPerSecondSchemaDataResultInnerValuesInnerInnerFromJSONTyped(json, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerValuesInnerInnerFromJSONTyped(json: any, ignoreDiscriminator: boolean): RequestsPerSecondSchemaDataResultInnerValuesInnerInner {
 | 
				
			||||||
 | 
					    return json;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSchemaDataResultInnerValuesInnerInnerToJSON(value?: RequestsPerSecondSchemaDataResultInnerValuesInnerInner | null): any {
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unleash API
 | 
				
			||||||
 | 
					 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The version of the OpenAPI document: 4.19.0-beta.0
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
				
			||||||
 | 
					 * https://openapi-generator.tech
 | 
				
			||||||
 | 
					 * Do not edit the class manually.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { exists, mapValues } from '../runtime';
 | 
				
			||||||
 | 
					import type { RequestsPerSecondSchema } from './RequestsPerSecondSchema';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaFromJSON,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaFromJSONTyped,
 | 
				
			||||||
 | 
					    RequestsPerSecondSchemaToJSON,
 | 
				
			||||||
 | 
					} from './RequestsPerSecondSchema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface RequestsPerSecondSegmentedSchema
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface RequestsPerSecondSegmentedSchema {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {RequestsPerSecondSchema}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSegmentedSchema
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    clientMetrics?: RequestsPerSecondSchema;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {RequestsPerSecondSchema}
 | 
				
			||||||
 | 
					     * @memberof RequestsPerSecondSegmentedSchema
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    adminMetrics?: RequestsPerSecondSchema;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if a given object implements the RequestsPerSecondSegmentedSchema interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function instanceOfRequestsPerSecondSegmentedSchema(value: object): boolean {
 | 
				
			||||||
 | 
					    let isInstance = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return isInstance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSegmentedSchemaFromJSON(json: any): RequestsPerSecondSegmentedSchema {
 | 
				
			||||||
 | 
					    return RequestsPerSecondSegmentedSchemaFromJSONTyped(json, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSegmentedSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): RequestsPerSecondSegmentedSchema {
 | 
				
			||||||
 | 
					    if ((json === undefined) || (json === null)) {
 | 
				
			||||||
 | 
					        return json;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'clientMetrics': !exists(json, 'clientMetrics') ? undefined : RequestsPerSecondSchemaFromJSON(json['clientMetrics']),
 | 
				
			||||||
 | 
					        'adminMetrics': !exists(json, 'adminMetrics') ? undefined : RequestsPerSecondSchemaFromJSON(json['adminMetrics']),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function RequestsPerSecondSegmentedSchemaToJSON(value?: RequestsPerSecondSegmentedSchema | null): any {
 | 
				
			||||||
 | 
					    if (value === undefined) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (value === null) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        'clientMetrics': RequestsPerSecondSchemaToJSON(value.clientMetrics),
 | 
				
			||||||
 | 
					        'adminMetrics': RequestsPerSecondSchemaToJSON(value.adminMetrics),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,3 +17,5 @@ export * from './UpdateFeatureSchema';
 | 
				
			|||||||
export * from './UpdateStrategySchema';
 | 
					export * from './UpdateStrategySchema';
 | 
				
			||||||
export * from './VariantSchema';
 | 
					export * from './VariantSchema';
 | 
				
			||||||
export * from './VariantSchemaPayload';
 | 
					export * from './VariantSchemaPayload';
 | 
				
			||||||
 | 
					export * from './RequestsPerSecondSchema';
 | 
				
			||||||
 | 
					export * from './RequestsPerSecondSchemaDataResultInnerValuesInnerInner';
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								frontend/src/utils/cyclicIterator.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								frontend/src/utils/cyclicIterator.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import { CyclicIterator } from './cyclicIterator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test('loops around the list', () => {
 | 
				
			||||||
 | 
					    const iterator = new CyclicIterator<number>([1, 3, 5, 7]);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(1);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(3);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(5);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(7);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(1);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(3);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(5);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(7);
 | 
				
			||||||
 | 
					    expect(iterator.next()).toEqual(1);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										12
									
								
								frontend/src/utils/cyclicIterator.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/src/utils/cyclicIterator.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					export class CyclicIterator<T> {
 | 
				
			||||||
 | 
					    private current = 0;
 | 
				
			||||||
 | 
					    readonly all: T[];
 | 
				
			||||||
 | 
					    constructor(defaultList: T[]) {
 | 
				
			||||||
 | 
					        this.all = defaultList;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    next(): T {
 | 
				
			||||||
 | 
					        const item = this.all[this.current];
 | 
				
			||||||
 | 
					        this.current = (this.current + 1) % this.all.length;
 | 
				
			||||||
 | 
					        return item;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -201,7 +201,8 @@ class MetricsController extends Controller {
 | 
				
			|||||||
                clientMetrics,
 | 
					                clientMetrics,
 | 
				
			||||||
                adminMetrics,
 | 
					                adminMetrics,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (err) {
 | 
				
			||||||
 | 
					            this.logger.error('Failed to fetch RPS metrics', err);
 | 
				
			||||||
            res.status(500).send('Error fetching RPS metrics');
 | 
					            res.status(500).send('Error fetching RPS metrics');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user