mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 04:05:56 +08:00
parent
cf451d335c
commit
75d86cea60
@ -316,7 +316,7 @@ describe('API Monitoring Utils', () => {
|
|||||||
{
|
{
|
||||||
metric: {
|
metric: {
|
||||||
[SPAN_ATTRIBUTES.URL_PATH]: '/api/test',
|
[SPAN_ATTRIBUTES.URL_PATH]: '/api/test',
|
||||||
[SPAN_ATTRIBUTES.STATUS_CODE]: '500',
|
[SPAN_ATTRIBUTES.RESPONSE_STATUS_CODE]: '500',
|
||||||
status_message: 'Internal Server Error',
|
status_message: 'Internal Server Error',
|
||||||
},
|
},
|
||||||
values: [[1000000100, '10']],
|
values: [[1000000100, '10']],
|
||||||
|
@ -35,6 +35,11 @@ function AllEndPoints({
|
|||||||
initialFilters: IBuilderQuery['filters'];
|
initialFilters: IBuilderQuery['filters'];
|
||||||
setInitialFiltersEndPointStats: (filters: IBuilderQuery['filters']) => void;
|
setInitialFiltersEndPointStats: (filters: IBuilderQuery['filters']) => void;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
|
const [groupBySearchValue, setGroupBySearchValue] = useState<string>('');
|
||||||
|
const [allAvailableGroupByOptions, setAllAvailableGroupByOptions] = useState<{
|
||||||
|
[key: string]: any;
|
||||||
|
}>({});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: groupByFiltersData,
|
data: groupByFiltersData,
|
||||||
isLoading: isLoadingGroupByFilters,
|
isLoading: isLoadingGroupByFilters,
|
||||||
@ -42,7 +47,7 @@ function AllEndPoints({
|
|||||||
dataSource: DataSource.TRACES,
|
dataSource: DataSource.TRACES,
|
||||||
aggregateAttribute: '',
|
aggregateAttribute: '',
|
||||||
aggregateOperator: 'noop',
|
aggregateOperator: 'noop',
|
||||||
searchText: '',
|
searchText: groupBySearchValue,
|
||||||
tagType: '',
|
tagType: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -52,34 +57,66 @@ function AllEndPoints({
|
|||||||
|
|
||||||
const handleGroupByChange = useCallback(
|
const handleGroupByChange = useCallback(
|
||||||
(value: IBuilderQuery['groupBy']) => {
|
(value: IBuilderQuery['groupBy']) => {
|
||||||
const groupBy = [];
|
const newGroupBy = [];
|
||||||
|
|
||||||
for (let index = 0; index < value.length; index++) {
|
for (let index = 0; index < value.length; index++) {
|
||||||
const element = (value[index] as unknown) as string;
|
const element = (value[index] as unknown) as string;
|
||||||
|
|
||||||
const key = groupByFiltersData?.payload?.attributeKeys?.find(
|
// Check if the key exists in our cached options first
|
||||||
(key) => key.key === element,
|
if (allAvailableGroupByOptions[element]) {
|
||||||
);
|
newGroupBy.push(allAvailableGroupByOptions[element]);
|
||||||
|
} else {
|
||||||
|
// If not found in cache, check the current filtered results
|
||||||
|
const key = groupByFiltersData?.payload?.attributeKeys?.find(
|
||||||
|
(key) => key.key === element,
|
||||||
|
);
|
||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
groupBy.push(key);
|
newGroupBy.push(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setGroupBy(groupBy);
|
|
||||||
|
setGroupBy(newGroupBy);
|
||||||
|
setGroupBySearchValue('');
|
||||||
},
|
},
|
||||||
[groupByFiltersData, setGroupBy],
|
[groupByFiltersData, setGroupBy, allAvailableGroupByOptions],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupByFiltersData?.payload) {
|
if (groupByFiltersData?.payload) {
|
||||||
|
// Update dropdown options
|
||||||
setGroupByOptions(
|
setGroupByOptions(
|
||||||
groupByFiltersData?.payload?.attributeKeys?.map((filter) => ({
|
groupByFiltersData?.payload?.attributeKeys?.map((filter) => ({
|
||||||
value: filter.key,
|
value: filter.key,
|
||||||
label: filter.key,
|
label: filter.key,
|
||||||
})) || [],
|
})) || [],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Cache all available options to preserve selected values using functional update
|
||||||
|
// to avoid dependency on allAvailableGroupByOptions
|
||||||
|
setAllAvailableGroupByOptions((prevOptions) => {
|
||||||
|
const newOptions = { ...prevOptions };
|
||||||
|
groupByFiltersData?.payload?.attributeKeys?.forEach((filter) => {
|
||||||
|
newOptions[filter.key] = filter;
|
||||||
|
});
|
||||||
|
return newOptions;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [groupByFiltersData]);
|
}, [groupByFiltersData]); // Only depends on groupByFiltersData now
|
||||||
|
|
||||||
|
// Cache existing selected options on component mount
|
||||||
|
useEffect(() => {
|
||||||
|
if (groupBy && groupBy.length > 0) {
|
||||||
|
setAllAvailableGroupByOptions((prevOptions) => {
|
||||||
|
const newOptions = { ...prevOptions };
|
||||||
|
groupBy.forEach((option) => {
|
||||||
|
newOptions[option.key] = option;
|
||||||
|
});
|
||||||
|
return newOptions;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [groupBy]); // Removed allAvailableGroupByOptions from dependencies
|
||||||
|
|
||||||
const currentQuery = initialQueriesMap[DataSource.TRACES];
|
const currentQuery = initialQueriesMap[DataSource.TRACES];
|
||||||
|
|
||||||
@ -168,6 +205,7 @@ function AllEndPoints({
|
|||||||
placeholder="Search for attribute"
|
placeholder="Search for attribute"
|
||||||
options={groupByOptions}
|
options={groupByOptions}
|
||||||
onChange={handleGroupByChange}
|
onChange={handleGroupByChange}
|
||||||
|
onSearch={(value: string): void => setGroupBySearchValue(value)}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
</div>
|
</div>
|
||||||
<div className="endpoints-table-container">
|
<div className="endpoints-table-container">
|
||||||
|
@ -229,7 +229,7 @@ function DomainDetails({
|
|||||||
<TopErrors
|
<TopErrors
|
||||||
domainName={domainData.domainName}
|
domainName={domainData.domainName}
|
||||||
timeRange={modalTimeRange}
|
timeRange={modalTimeRange}
|
||||||
handleTimeChange={handleTimeChange}
|
initialFilters={domainListFilters}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -12,17 +12,14 @@ import {
|
|||||||
getTopErrorsQueryPayload,
|
getTopErrorsQueryPayload,
|
||||||
TopErrorsResponseRow,
|
TopErrorsResponseRow,
|
||||||
} from 'container/ApiMonitoring/utils';
|
} from 'container/ApiMonitoring/utils';
|
||||||
import {
|
|
||||||
CustomTimeType,
|
|
||||||
Time,
|
|
||||||
} from 'container/TopNav/DateTimeSelectionV2/config';
|
|
||||||
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
|
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
|
||||||
import { Info } from 'lucide-react';
|
import { Info } from 'lucide-react';
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useQueries } from 'react-query';
|
import { useQueries } from 'react-query';
|
||||||
import { SuccessResponse } from 'types/api';
|
import { SuccessResponse } from 'types/api';
|
||||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
import EndPointsDropDown from './components/EndPointsDropDown';
|
import EndPointsDropDown from './components/EndPointsDropDown';
|
||||||
@ -32,17 +29,14 @@ import { SPAN_ATTRIBUTES } from './constants';
|
|||||||
function TopErrors({
|
function TopErrors({
|
||||||
domainName,
|
domainName,
|
||||||
timeRange,
|
timeRange,
|
||||||
handleTimeChange,
|
initialFilters,
|
||||||
}: {
|
}: {
|
||||||
domainName: string;
|
domainName: string;
|
||||||
timeRange: {
|
timeRange: {
|
||||||
startTime: number;
|
startTime: number;
|
||||||
endTime: number;
|
endTime: number;
|
||||||
};
|
};
|
||||||
handleTimeChange: (
|
initialFilters: IBuilderQuery['filters'];
|
||||||
interval: Time | CustomTimeType,
|
|
||||||
dateTimeRange?: [number, number],
|
|
||||||
) => void;
|
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const { startTime: minTime, endTime: maxTime } = timeRange;
|
const { startTime: minTime, endTime: maxTime } = timeRange;
|
||||||
|
|
||||||
@ -65,11 +59,12 @@ function TopErrors({
|
|||||||
op: '=',
|
op: '=',
|
||||||
value: endPointName,
|
value: endPointName,
|
||||||
},
|
},
|
||||||
|
...initialFilters.items,
|
||||||
]
|
]
|
||||||
: [],
|
: [...initialFilters.items],
|
||||||
op: 'AND',
|
op: 'AND',
|
||||||
}),
|
}),
|
||||||
[domainName, endPointName, minTime, maxTime],
|
[domainName, endPointName, minTime, maxTime, initialFilters],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Since only one query here
|
// Since only one query here
|
||||||
@ -135,10 +130,6 @@ function TopErrors({
|
|||||||
[endPointDropDownDataQueries],
|
[endPointDropDownDataQueries],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
handleTimeChange('6h');
|
|
||||||
}, [handleTimeChange]);
|
|
||||||
|
|
||||||
const navigateToExplorer = useNavigateToExplorer();
|
const navigateToExplorer = useNavigateToExplorer();
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
|
@ -146,13 +146,13 @@ function DomainMetrics({
|
|||||||
<Progress
|
<Progress
|
||||||
status="active"
|
status="active"
|
||||||
percent={Number(
|
percent={Number(
|
||||||
Number(formattedDomainMetricsData.errorRate).toFixed(1),
|
Number(formattedDomainMetricsData.errorRate).toFixed(2),
|
||||||
)}
|
)}
|
||||||
strokeLinecap="butt"
|
strokeLinecap="butt"
|
||||||
size="small"
|
size="small"
|
||||||
strokeColor={((): string => {
|
strokeColor={((): string => {
|
||||||
const errorRatePercent = Number(
|
const errorRatePercent = Number(
|
||||||
Number(formattedDomainMetricsData.errorRate).toFixed(1),
|
Number(formattedDomainMetricsData.errorRate).toFixed(2),
|
||||||
);
|
);
|
||||||
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
||||||
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
||||||
|
@ -90,12 +90,12 @@ function EndPointMetrics({
|
|||||||
<Tooltip title={metricsData?.errorRate}>
|
<Tooltip title={metricsData?.errorRate}>
|
||||||
<Progress
|
<Progress
|
||||||
status="active"
|
status="active"
|
||||||
percent={Number(Number(metricsData?.errorRate ?? 0).toFixed(1))}
|
percent={Number(Number(metricsData?.errorRate ?? 0).toFixed(2))}
|
||||||
strokeLinecap="butt"
|
strokeLinecap="butt"
|
||||||
size="small"
|
size="small"
|
||||||
strokeColor={((): string => {
|
strokeColor={((): string => {
|
||||||
const errorRatePercent = Number(
|
const errorRatePercent = Number(
|
||||||
Number(metricsData?.errorRate ?? 0).toFixed(1),
|
Number(metricsData?.errorRate ?? 0).toFixed(2),
|
||||||
);
|
);
|
||||||
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
||||||
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
||||||
|
@ -14,6 +14,7 @@ export const VIEW_TYPES = {
|
|||||||
export const SPAN_ATTRIBUTES = {
|
export const SPAN_ATTRIBUTES = {
|
||||||
URL_PATH: 'http.url',
|
URL_PATH: 'http.url',
|
||||||
STATUS_CODE: 'status_code',
|
STATUS_CODE: 'status_code',
|
||||||
|
RESPONSE_STATUS_CODE: 'response_status_code',
|
||||||
SERVER_NAME: 'net.peer.name',
|
SERVER_NAME: 'net.peer.name',
|
||||||
SERVER_PORT: 'net.peer.port',
|
SERVER_PORT: 'net.peer.port',
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
|
||||||
import {
|
import {
|
||||||
getAllEndpointsWidgetData,
|
getAllEndpointsWidgetData,
|
||||||
getGroupByFiltersFromGroupByValues,
|
getGroupByFiltersFromGroupByValues,
|
||||||
@ -129,6 +129,11 @@ describe('AllEndPoints', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add cleanup after each test
|
||||||
|
afterEach(() => {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders component correctly', () => {
|
it('renders component correctly', () => {
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
render(<AllEndPoints {...mockProps} />);
|
render(<AllEndPoints {...mockProps} />);
|
||||||
|
@ -61,7 +61,10 @@ describe('TopErrors', () => {
|
|||||||
startTime: 1000000000,
|
startTime: 1000000000,
|
||||||
endTime: 1000010000,
|
endTime: 1000010000,
|
||||||
},
|
},
|
||||||
handleTimeChange: jest.fn(),
|
initialFilters: {
|
||||||
|
items: [],
|
||||||
|
op: 'AND',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup basic mocks
|
// Setup basic mocks
|
||||||
@ -223,12 +226,6 @@ describe('TopErrors', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls handleTimeChange with 6h on mount', () => {
|
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
||||||
render(<TopErrors {...mockProps} />);
|
|
||||||
expect(mockProps.handleTimeChange).toHaveBeenCalledWith('6h');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders error state when isError is true', () => {
|
it('renders error state when isError is true', () => {
|
||||||
// Mock useQueries to return isError: true
|
// Mock useQueries to return isError: true
|
||||||
(useQueries as jest.Mock).mockImplementationOnce(() => [
|
(useQueries as jest.Mock).mockImplementationOnce(() => [
|
||||||
|
@ -208,17 +208,16 @@ export const columnsConfig: ColumnType<APIDomainsRowData>[] = [
|
|||||||
align: 'right',
|
align: 'right',
|
||||||
className: `column`,
|
className: `column`,
|
||||||
render: (errorRate: number | string): React.ReactNode => {
|
render: (errorRate: number | string): React.ReactNode => {
|
||||||
if (errorRate === 'n/a' || errorRate === '-') {
|
const errorRateValue =
|
||||||
return '-';
|
errorRate === 'n/a' || errorRate === '-' ? 0 : errorRate;
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<Progress
|
<Progress
|
||||||
status="active"
|
status="active"
|
||||||
percent={Number((errorRate as number).toFixed(1))}
|
percent={Number((errorRateValue as number).toFixed(2))}
|
||||||
strokeLinecap="butt"
|
strokeLinecap="butt"
|
||||||
size="small"
|
size="small"
|
||||||
strokeColor={((): string => {
|
strokeColor={((): string => {
|
||||||
const errorRatePercent = Number((errorRate as number).toFixed(1));
|
const errorRatePercent = Number((errorRateValue as number).toFixed(2));
|
||||||
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
||||||
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
||||||
return Color.BG_FOREST_500;
|
return Color.BG_FOREST_500;
|
||||||
@ -941,18 +940,6 @@ export const getTopErrorsQueryPayload = (
|
|||||||
op: '=',
|
op: '=',
|
||||||
value: 'Client',
|
value: 'Client',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: '75d65388',
|
|
||||||
key: {
|
|
||||||
key: 'status_message',
|
|
||||||
dataType: DataTypes.String,
|
|
||||||
type: '',
|
|
||||||
isColumn: true,
|
|
||||||
isJSON: false,
|
|
||||||
},
|
|
||||||
op: 'exists',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'b1af6bdb',
|
id: 'b1af6bdb',
|
||||||
key: {
|
key: {
|
||||||
@ -965,6 +952,18 @@ export const getTopErrorsQueryPayload = (
|
|||||||
op: 'exists',
|
op: 'exists',
|
||||||
value: '',
|
value: '',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: '75d65388',
|
||||||
|
key: {
|
||||||
|
key: 'status_message',
|
||||||
|
dataType: DataTypes.String,
|
||||||
|
type: '',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
},
|
||||||
|
op: 'exists',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: '4872bf91',
|
id: '4872bf91',
|
||||||
key: {
|
key: {
|
||||||
@ -977,6 +976,18 @@ export const getTopErrorsQueryPayload = (
|
|||||||
op: '=',
|
op: '=',
|
||||||
value: domainName,
|
value: domainName,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'ab4c885d',
|
||||||
|
key: {
|
||||||
|
key: 'has_error',
|
||||||
|
dataType: DataTypes.bool,
|
||||||
|
type: '',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
},
|
||||||
|
op: '=',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
...filters.items,
|
...filters.items,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1000,11 +1011,12 @@ export const getTopErrorsQueryPayload = (
|
|||||||
isJSON: false,
|
isJSON: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'status_code',
|
dataType: DataTypes.String,
|
||||||
dataType: DataTypes.Float64,
|
|
||||||
type: '',
|
|
||||||
isColumn: true,
|
isColumn: true,
|
||||||
isJSON: false,
|
isJSON: false,
|
||||||
|
key: 'response_status_code',
|
||||||
|
type: '',
|
||||||
|
id: 'response_status_code--string----true',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'status_message',
|
key: 'status_message',
|
||||||
@ -1327,7 +1339,7 @@ export const formatEndPointsDataForTable = (
|
|||||||
export interface TopErrorsResponseRow {
|
export interface TopErrorsResponseRow {
|
||||||
metric: {
|
metric: {
|
||||||
[SPAN_ATTRIBUTES.URL_PATH]: string;
|
[SPAN_ATTRIBUTES.URL_PATH]: string;
|
||||||
[SPAN_ATTRIBUTES.STATUS_CODE]: string;
|
[SPAN_ATTRIBUTES.RESPONSE_STATUS_CODE]: string;
|
||||||
status_message: string;
|
status_message: string;
|
||||||
};
|
};
|
||||||
values: [number, string][];
|
values: [number, string][];
|
||||||
@ -1356,10 +1368,10 @@ export const formatTopErrorsDataForTable = (
|
|||||||
? '-'
|
? '-'
|
||||||
: row.metric[SPAN_ATTRIBUTES.URL_PATH],
|
: row.metric[SPAN_ATTRIBUTES.URL_PATH],
|
||||||
statusCode:
|
statusCode:
|
||||||
row.metric[SPAN_ATTRIBUTES.STATUS_CODE] === 'n/a' ||
|
row.metric[SPAN_ATTRIBUTES.RESPONSE_STATUS_CODE] === 'n/a' ||
|
||||||
row.metric[SPAN_ATTRIBUTES.STATUS_CODE] === undefined
|
row.metric[SPAN_ATTRIBUTES.RESPONSE_STATUS_CODE] === undefined
|
||||||
? '-'
|
? '-'
|
||||||
: row.metric[SPAN_ATTRIBUTES.STATUS_CODE],
|
: row.metric[SPAN_ATTRIBUTES.RESPONSE_STATUS_CODE],
|
||||||
statusMessage:
|
statusMessage:
|
||||||
row.metric.status_message === 'n/a' ||
|
row.metric.status_message === 'n/a' ||
|
||||||
row.metric.status_message === undefined
|
row.metric.status_message === undefined
|
||||||
@ -2005,7 +2017,7 @@ export const getEndPointDetailsQueryPayload = (
|
|||||||
type: 'tag',
|
type: 'tag',
|
||||||
},
|
},
|
||||||
op: '=',
|
op: '=',
|
||||||
value: 'api.github.com',
|
value: domainName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '212678b9',
|
id: '212678b9',
|
||||||
@ -3057,28 +3069,28 @@ export const dependentServicesColumns: ColumnType<DependentServicesData>[] = [
|
|||||||
render: (
|
render: (
|
||||||
errorPercentage: number | string,
|
errorPercentage: number | string,
|
||||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||||
): React.ReactNode => (
|
): React.ReactNode => {
|
||||||
<Progress
|
const errorPercentageValue =
|
||||||
status="active"
|
errorPercentage === 'n/a' || errorPercentage === '-' ? 0 : errorPercentage;
|
||||||
percent={Number(
|
return (
|
||||||
((errorPercentage === 'n/a' || errorPercentage === '-'
|
<Progress
|
||||||
? 0
|
status="active"
|
||||||
: errorPercentage) as number).toFixed(1),
|
percent={Number((errorPercentageValue as number).toFixed(2))}
|
||||||
)}
|
strokeLinecap="butt"
|
||||||
strokeLinecap="butt"
|
size="small"
|
||||||
size="small"
|
strokeColor={((): // eslint-disable-next-line sonarjs/no-identical-functions
|
||||||
strokeColor={((): // eslint-disable-next-line sonarjs/no-identical-functions
|
string => {
|
||||||
string => {
|
const errorPercentagePercent = Number(
|
||||||
const errorPercentagePercent = Number(
|
(errorPercentageValue as number).toFixed(2),
|
||||||
(errorPercentage as number).toFixed(1),
|
);
|
||||||
);
|
if (errorPercentagePercent >= 90) return Color.BG_SAKURA_500;
|
||||||
if (errorPercentagePercent >= 90) return Color.BG_SAKURA_500;
|
if (errorPercentagePercent >= 60) return Color.BG_AMBER_500;
|
||||||
if (errorPercentagePercent >= 60) return Color.BG_AMBER_500;
|
return Color.BG_FOREST_500;
|
||||||
return Color.BG_FOREST_500;
|
})()}
|
||||||
})()}
|
className="progress-bar error-rate"
|
||||||
className="progress-bar error-rate"
|
/>
|
||||||
/>
|
);
|
||||||
),
|
},
|
||||||
sorter: (a: DependentServicesData, b: DependentServicesData): number => {
|
sorter: (a: DependentServicesData, b: DependentServicesData): number => {
|
||||||
const errorPercentageA =
|
const errorPercentageA =
|
||||||
a.errorPercentage === '-' || a.errorPercentage === 'n/a'
|
a.errorPercentage === '-' || a.errorPercentage === 'n/a'
|
||||||
@ -3658,12 +3670,9 @@ export const getAllEndpointsWidgetData = (
|
|||||||
|
|
||||||
widget.renderColumnCell = {
|
widget.renderColumnCell = {
|
||||||
[SPAN_ATTRIBUTES.URL_PATH]: (url: any): ReactNode => {
|
[SPAN_ATTRIBUTES.URL_PATH]: (url: any): ReactNode => {
|
||||||
const { endpoint, port } = extractPortAndEndpoint(url);
|
const { endpoint } = extractPortAndEndpoint(url);
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>{endpoint === 'n/a' || url === undefined ? '-' : endpoint}</span>
|
||||||
{port !== '-' && port !== 'n/a' ? `:${port}` : ''}
|
|
||||||
{endpoint === 'n/a' || url === undefined ? '-' : endpoint}
|
|
||||||
</span>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
A: (numOfCalls: any): ReactNode => (
|
A: (numOfCalls: any): ReactNode => (
|
||||||
@ -3695,7 +3704,7 @@ export const getAllEndpointsWidgetData = (
|
|||||||
percent={Number(
|
percent={Number(
|
||||||
((errorRate === 'n/a' || errorRate === '-'
|
((errorRate === 'n/a' || errorRate === '-'
|
||||||
? 0
|
? 0
|
||||||
: errorRate) as number).toFixed(1),
|
: errorRate) as number).toFixed(2),
|
||||||
)}
|
)}
|
||||||
strokeLinecap="butt"
|
strokeLinecap="butt"
|
||||||
size="small"
|
size="small"
|
||||||
@ -3704,7 +3713,7 @@ export const getAllEndpointsWidgetData = (
|
|||||||
const errorRatePercent = Number(
|
const errorRatePercent = Number(
|
||||||
((errorRate === 'n/a' || errorRate === '-'
|
((errorRate === 'n/a' || errorRate === '-'
|
||||||
? 0
|
? 0
|
||||||
: errorRate) as number).toFixed(1),
|
: errorRate) as number).toFixed(2),
|
||||||
);
|
);
|
||||||
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
if (errorRatePercent >= 90) return Color.BG_SAKURA_500;
|
||||||
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
if (errorRatePercent >= 60) return Color.BG_AMBER_500;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user