@@ -35,41 +106,62 @@ function DomainMetrics({ domainData }: { domainData: any }): JSX.Element {
-
- {domainData.endpointCount}
-
+ {isLoading || isRefetching ? (
+
+ ) : (
+
+
+ {formattedDomainMetricsData.endpointCount}
+
+
+ )}
{/* // update the tooltip as well */}
-
-
- {(domainData.latency / 1000).toFixed(3)}s
-
-
+ {isLoading || isRefetching ? (
+
+ ) : (
+
+
+ {(Number(formattedDomainMetricsData.latency) / 1000).toFixed(3)}s
+
+
+ )}
{/* // update the tooltip as well */}
-
-
+ {isLoading || isRefetching ? (
+
+ ) : (
+
+
+ )}
- {/* // update the tooltip as well */}
-
- {getLastUsedRelativeTime(domainData.lastUsed)}
-
+ {isLoading || isRefetching ? (
+
+ ) : (
+
+ {formattedDomainMetricsData.lastUsed}
+
+ )}
diff --git a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/EndPointsDropDown.tsx b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/EndPointsDropDown.tsx
index a351cf4208..f3583a561d 100644
--- a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/EndPointsDropDown.tsx
+++ b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/EndPointsDropDown.tsx
@@ -52,6 +52,10 @@ function EndPointsDropDown({
: (triggerNode): HTMLElement => triggerNode.parentNode as HTMLElement
}
dropdownStyle={dropdownStyle}
+ allowClear
+ onClear={(): void => {
+ setSelectedEndPointName('');
+ }}
/>
);
}
diff --git a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/ExpandedRow.tsx b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/ExpandedRow.tsx
index 26cb03c09f..c28417688b 100644
--- a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/ExpandedRow.tsx
+++ b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/ExpandedRow.tsx
@@ -118,7 +118,7 @@ function ExpandedRow({
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
setSelectedEndPointName(record.endpointName);
- setSelectedView(VIEW_TYPES.ENDPOINT_DETAILS);
+ setSelectedView(VIEW_TYPES.ENDPOINT_STATS);
logEvent('API Monitoring: Endpoint name row clicked', {});
},
className: 'expanded-clickable-row',
diff --git a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/MetricOverTimeGraph.tsx b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/MetricOverTimeGraph.tsx
index dadf1513c9..65de1e8b7d 100644
--- a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/MetricOverTimeGraph.tsx
+++ b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/components/MetricOverTimeGraph.tsx
@@ -5,9 +5,11 @@ import { Widgets } from 'types/api/dashboard/getAll';
function MetricOverTimeGraph({
widget,
timeRange,
+ onDragSelect,
}: {
widget: Widgets;
timeRange: { startTime: number; endTime: number };
+ onDragSelect: (start: number, end: number) => void;
}): JSX.Element {
return (
@@ -16,10 +18,9 @@ function MetricOverTimeGraph({
{}}
+ onDragSelect={onDragSelect}
customOnDragSelect={(): void => {}}
- start={timeRange.startTime}
- end={timeRange.endTime}
+ customTimeRange={timeRange}
/>
diff --git a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/constants.ts b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/constants.ts
index 1fbaf85bdc..aacb1c18a1 100644
--- a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/constants.ts
+++ b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainDetails/constants.ts
@@ -1,11 +1,11 @@
export enum VIEWS {
ALL_ENDPOINTS = 'all_endpoints',
- ENDPOINT_DETAILS = 'endpoint_details',
+ ENDPOINT_STATS = 'endpoint_stats',
TOP_ERRORS = 'top_errors',
}
export const VIEW_TYPES = {
ALL_ENDPOINTS: VIEWS.ALL_ENDPOINTS,
- ENDPOINT_DETAILS: VIEWS.ENDPOINT_DETAILS,
+ ENDPOINT_STATS: VIEWS.ENDPOINT_STATS,
TOP_ERRORS: VIEWS.TOP_ERRORS,
};
diff --git a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainList.tsx b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainList.tsx
index 192a98f6ed..a37c009282 100644
--- a/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainList.tsx
+++ b/frontend/src/container/ApiMonitoring/Explorer/Domains/DomainList.tsx
@@ -60,7 +60,6 @@ function DomainList({ showIP }: { showIP: boolean }): JSX.Element {
aggregateAttribute: {
...initialQueriesMap.traces.builder.queryData[0].aggregateAttribute,
},
- queryName: '',
},
],
},
diff --git a/frontend/src/container/ApiMonitoring/utils.tsx b/frontend/src/container/ApiMonitoring/utils.tsx
index c9cb2035e3..96b6b1965b 100644
--- a/frontend/src/container/ApiMonitoring/utils.tsx
+++ b/frontend/src/container/ApiMonitoring/utils.tsx
@@ -333,6 +333,278 @@ export const formatDataForTable = (
).toISOString(), // Convert from nanoseconds to milliseconds
}));
+export const getDomainMetricsQueryPayload = (
+ domainName: string,
+ start: number,
+ end: number,
+): GetQueryResultsProps[] => [
+ {
+ selectedTime: 'GLOBAL_TIME',
+ graphType: PANEL_TYPES.TABLE,
+ query: {
+ builder: {
+ queryData: [
+ {
+ dataSource: DataSource.TRACES,
+ queryName: 'A',
+ aggregateOperator: 'count',
+ aggregateAttribute: {
+ dataType: DataTypes.String,
+ id: 'http.url--string--tag--false',
+ isColumn: false,
+ isJSON: false,
+ key: 'http.url',
+ type: 'tag',
+ },
+ timeAggregation: 'rate',
+ spaceAggregation: 'sum',
+ functions: [],
+ filters: {
+ items: [
+ {
+ id: '4c57937c',
+ key: {
+ dataType: DataTypes.String,
+ id: 'net.peer.name--string--tag--false',
+ isColumn: false,
+ isJSON: false,
+ key: 'net.peer.name',
+ type: 'tag',
+ },
+ op: '=',
+ value: domainName,
+ },
+ ],
+ op: 'AND',
+ },
+ expression: 'A',
+ disabled: false,
+ stepInterval: 60,
+ having: [],
+ limit: null,
+ orderBy: [],
+ groupBy: [],
+ legend: '',
+ reduceTo: 'avg',
+ },
+ {
+ dataSource: DataSource.TRACES,
+ queryName: 'B',
+ aggregateOperator: 'p99',
+ aggregateAttribute: {
+ dataType: DataTypes.Float64,
+ id: 'duration_nano--float64----true',
+ isColumn: true,
+ isJSON: false,
+ key: 'duration_nano',
+ type: '',
+ },
+ timeAggregation: 'p99',
+ spaceAggregation: 'sum',
+ functions: [],
+ filters: {
+ items: [
+ {
+ id: '2cf675cd',
+ key: {
+ dataType: DataTypes.String,
+ id: 'net.peer.name--string--tag--false',
+ isColumn: false,
+ isJSON: false,
+ key: 'net.peer.name',
+ type: 'tag',
+ },
+ op: '=',
+ value: domainName,
+ },
+ ],
+ op: 'AND',
+ },
+ expression: 'B',
+ disabled: false,
+ stepInterval: 60,
+ having: [],
+ limit: null,
+ orderBy: [],
+ groupBy: [],
+ legend: '',
+ reduceTo: 'avg',
+ },
+ {
+ dataSource: DataSource.TRACES,
+ queryName: 'C',
+ aggregateOperator: 'count',
+ aggregateAttribute: {
+ dataType: DataTypes.String,
+ id: '------false',
+ isColumn: false,
+ key: '',
+ type: '',
+ },
+ timeAggregation: 'count',
+ spaceAggregation: 'sum',
+ functions: [],
+ filters: {
+ items: [
+ {
+ id: '3db0f605',
+ key: {
+ dataType: DataTypes.String,
+ id: 'net.peer.name--string--tag--false',
+ isColumn: false,
+ isJSON: false,
+ key: 'net.peer.name',
+ type: 'tag',
+ },
+ op: '=',
+ value: domainName,
+ },
+ {
+ id: '6096f745',
+ key: {
+ dataType: DataTypes.bool,
+ id: 'has_error--bool----true',
+ isColumn: true,
+ isJSON: false,
+ key: 'has_error',
+ type: '',
+ },
+ op: '=',
+ value: 'true',
+ },
+ ],
+ op: 'AND',
+ },
+ expression: 'C',
+ disabled: true,
+ stepInterval: 60,
+ having: [],
+ limit: null,
+ orderBy: [],
+ groupBy: [],
+ legend: '',
+ reduceTo: 'avg',
+ },
+ {
+ dataSource: DataSource.TRACES,
+ queryName: 'D',
+ aggregateOperator: 'max',
+ aggregateAttribute: {
+ dataType: DataTypes.String,
+ id: 'timestamp------false',
+ isColumn: false,
+ key: 'timestamp',
+ type: '',
+ },
+ timeAggregation: 'max',
+ spaceAggregation: 'sum',
+ functions: [],
+ filters: {
+ items: [
+ {
+ id: '8ff8dea1',
+ key: {
+ dataType: DataTypes.String,
+ id: 'net.peer.name--string--tag--false',
+ isColumn: false,
+ isJSON: false,
+ key: 'net.peer.name',
+ type: 'tag',
+ },
+ op: '=',
+ value: domainName,
+ },
+ ],
+ op: 'AND',
+ },
+ expression: 'D',
+ disabled: false,
+ stepInterval: 60,
+ having: [],
+ limit: null,
+ orderBy: [],
+ groupBy: [],
+ legend: '',
+ reduceTo: 'avg',
+ },
+ ],
+ queryFormulas: [
+ {
+ queryName: 'F1',
+ expression: '(C/A)*100',
+ disabled: false,
+ legend: '',
+ },
+ ],
+ },
+ clickhouse_sql: [
+ {
+ disabled: false,
+ legend: '',
+ name: 'A',
+ query: '',
+ },
+ ],
+ id: '315b15fa-ff0c-442f-89f8-2bf4fb1af2f2',
+ promql: [
+ {
+ disabled: false,
+ legend: '',
+ name: 'A',
+ query: '',
+ },
+ ],
+ queryType: EQueryType.QUERY_BUILDER,
+ },
+ variables: {},
+ formatForWeb: true,
+ start,
+ end,
+ step: 60,
+ },
+];
+
+export interface DomainMetricsData {
+ endpointCount: number | string;
+ latency: number | string;
+ errorRate: number | string;
+ lastUsed: number | string;
+}
+
+export interface DomainMetricsResponseRow {
+ data: {
+ A: number | string;
+ B: number | string;
+ D: number | string;
+ F1: number | string;
+ };
+}
+
+export const formatDomainMetricsDataForTable = (
+ row: DomainMetricsResponseRow | undefined,
+): DomainMetricsData => {
+ if (!row) {
+ return {
+ endpointCount: '-',
+ latency: '-',
+ errorRate: 0,
+ lastUsed: '-',
+ };
+ }
+ return {
+ endpointCount: row.data.A === 'n/a' || !row.data.A ? '-' : Number(row.data.A),
+ latency:
+ row.data.B === 'n/a' || row.data.B === undefined
+ ? '-'
+ : Math.round(Number(row.data.B) / 1000000),
+ errorRate: row.data.F1 === 'n/a' || !row.data.F1 ? 0 : Number(row.data.F1),
+ lastUsed:
+ row.data.D === 'n/a' || !row.data.D
+ ? '-'
+ : getLastUsedRelativeTime(Math.floor(Number(row.data.D) / 1000000)),
+ };
+};
+
// Rename this to a proper name
const defaultGroupBy = [
{
@@ -637,6 +909,7 @@ export const getTopErrorsQueryPayload = (
domainName: string,
start: number,
end: number,
+ filters: IBuilderQuery['filters'],
): GetQueryResultsProps[] => [
{
selectedTime: 'GLOBAL_TIME',
@@ -714,6 +987,7 @@ export const getTopErrorsQueryPayload = (
op: '=',
value: domainName,
},
+ ...filters.items,
],
},
expression: 'A',
@@ -1192,7 +1466,6 @@ export const createFiltersForSelectedRowData = (
// Sixth query payload for endpoint response status code latency bar chart
export const getEndPointDetailsQueryPayload = (
domainName: string,
- endPointName: string,
start: number,
end: number,
filters: IBuilderQuery['filters'],
@@ -1218,19 +1491,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'A',
filters: {
items: [
- {
- id: '92b8a1c1',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '874562e1',
key: {
@@ -1288,19 +1548,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'B',
filters: {
items: [
- {
- id: 'c0c0f76b',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '0c5564e0',
key: {
@@ -1358,19 +1605,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'C',
filters: {
items: [
- {
- id: '7a3eebed',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '0d656701',
key: {
@@ -1440,19 +1674,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'D',
filters: {
items: [
- {
- id: 'e7f12d52',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '918f5b99',
key: {
@@ -1510,19 +1731,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'E',
filters: {
items: [
- {
- id: '5281578a',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: 'b355d1aa',
key: {
@@ -1634,19 +1842,6 @@ export const getEndPointDetailsQueryPayload = (
op: '=',
value: domainName,
},
- {
- id: 'e1b24204',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '212678b9',
key: {
@@ -1713,19 +1908,6 @@ export const getEndPointDetailsQueryPayload = (
op: '=',
value: domainName,
},
- {
- id: '5dbe3518',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '212678b9',
key: {
@@ -1909,19 +2091,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'A',
filters: {
items: [
- {
- id: 'bdac4904',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: 'b78ff216',
key: {
@@ -1988,19 +2157,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'B',
filters: {
items: [
- {
- id: '74f9d185',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: 'a9024472',
key: {
@@ -2066,19 +2222,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'C',
filters: {
items: [
- {
- id: 'b7e36a72',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '1b6c062d',
key: {
@@ -2145,19 +2288,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'D',
filters: {
items: [
- {
- id: 'ede7cbfe',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: 'd14792a8',
key: {
@@ -2290,19 +2420,6 @@ export const getEndPointDetailsQueryPayload = (
op: '=',
value: domainName,
},
- {
- id: '8b1be6f0',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: '212678b9',
key: {
@@ -2390,19 +2507,6 @@ export const getEndPointDetailsQueryPayload = (
expression: 'A',
filters: {
items: [
- {
- id: '52aca159',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
{
id: 'aae93366',
key: {
@@ -2787,7 +2891,7 @@ export const dependentServicesColumns: ColumnType
[] = [
{serviceData.serviceName}
-
{serviceData.count}
+
{serviceData.count} Calls
{
- const { endpoint, port } = extractPortAndEndpoint(endPointName);
- const legend = `${
- port !== '-' && port !== 'n/a' ? `${port}:` : ''
- }${endpoint}`;
+ let legend = domainName;
+ if (endPointName) {
+ const { endpoint, port } = extractPortAndEndpoint(endPointName);
+ // eslint-disable-next-line sonarjs/no-nested-template-literals
+ legend = `${port !== '-' && port !== 'n/a' ? `${port}:` : ''}${endpoint}`;
+ }
+
return getWidgetQueryBuilder(
getWidgetQuery({
title: 'Rate Over Time',
@@ -3213,34 +3320,12 @@ export const getRateOverTimeWidgetData = (
op: '=',
value: domainName,
},
- {
- id: '30710f04',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
...filters.items,
],
op: 'AND',
},
functions: [],
- groupBy: [
- {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- ],
+ groupBy: [],
having: [],
legend,
limit: null,
@@ -3262,8 +3347,13 @@ export const getLatencyOverTimeWidgetData = (
endPointName: string,
filters: IBuilderQuery['filters'],
): Widgets => {
- const { endpoint, port } = extractPortAndEndpoint(endPointName);
- const legend = `${port}:${endpoint}`;
+ let legend = domainName;
+ if (endPointName) {
+ const { endpoint, port } = extractPortAndEndpoint(endPointName);
+ // eslint-disable-next-line sonarjs/no-nested-template-literals
+ legend = `${port !== '-' && port !== 'n/a' ? `${port}:` : ''}${endpoint}`;
+ }
+
return getWidgetQueryBuilder(
getWidgetQuery({
title: 'Latency Over Time',
@@ -3297,34 +3387,12 @@ export const getLatencyOverTimeWidgetData = (
op: '=',
value: domainName,
},
- {
- id: '50142500',
- key: {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- op: '=',
- value: endPointName,
- },
...filters.items,
],
op: 'AND',
},
functions: [],
- groupBy: [
- {
- dataType: DataTypes.String,
- id: 'http.url--string--tag--false',
- isColumn: false,
- isJSON: false,
- key: 'http.url',
- type: 'tag',
- },
- ],
+ groupBy: [],
having: [],
legend,
limit: null,
diff --git a/frontend/src/container/GridCardLayout/GridCard/index.tsx b/frontend/src/container/GridCardLayout/GridCard/index.tsx
index add29fa1b0..667f5a9594 100644
--- a/frontend/src/container/GridCardLayout/GridCard/index.tsx
+++ b/frontend/src/container/GridCardLayout/GridCard/index.tsx
@@ -47,6 +47,7 @@ function GridCardGraph({
start,
end,
analyticsEvent,
+ customTimeRange,
}: GridCardGraphProps): JSX.Element {
const dispatch = useDispatch();
const [errorMessage, setErrorMessage] = useState();
@@ -130,6 +131,8 @@ function GridCardGraph({
variables: getDashboardVariables(variables),
fillGaps: widget.fillSpans,
formatForWeb: widget.panelTypes === PANEL_TYPES.TABLE,
+ start: customTimeRange?.startTime || start,
+ end: customTimeRange?.endTime || end,
};
}
updatedQuery.builder.queryData[0].pageSize = 10;
@@ -149,6 +152,8 @@ function GridCardGraph({
initialDataSource === DataSource.TRACES && widget.selectedTracesFields,
},
fillGaps: widget.fillSpans,
+ start: customTimeRange?.startTime || start,
+ end: customTimeRange?.endTime || end,
};
});
@@ -187,8 +192,8 @@ function GridCardGraph({
variables: getDashboardVariables(variables),
selectedTime: widget.timePreferance || 'GLOBAL_TIME',
globalSelectedInterval,
- start,
- end,
+ start: customTimeRange?.startTime || start,
+ end: customTimeRange?.endTime || end,
},
version || DEFAULT_ENTITY_VERSION,
{
@@ -202,6 +207,9 @@ function GridCardGraph({
widget.timePreferance,
widget.fillSpans,
requestData,
+ ...(customTimeRange && customTimeRange.startTime && customTimeRange.endTime
+ ? [customTimeRange.startTime, customTimeRange.endTime]
+ : []),
],
retry(failureCount, error): boolean {
if (
diff --git a/frontend/src/container/GridCardLayout/GridCard/types.ts b/frontend/src/container/GridCardLayout/GridCard/types.ts
index c943da6e7a..e1ba7cb918 100644
--- a/frontend/src/container/GridCardLayout/GridCard/types.ts
+++ b/frontend/src/container/GridCardLayout/GridCard/types.ts
@@ -61,6 +61,10 @@ export interface GridCardGraphProps {
start?: number;
end?: number;
analyticsEvent?: string;
+ customTimeRange?: {
+ startTime: number;
+ endTime: number;
+ };
}
export interface GetGraphVisibilityStateOnLegendClickProps {