mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
feat(meter): add pre-defined panels for meter breakdown and improvements (#8827)
* feat(meter): add pre-defined panels for meter breakdown * feat(meter): update the routes for future scope * feat(meter): added graphs for total calculation * feat(meter): added graphs for total calculation
This commit is contained in:
parent
8f833fa62c
commit
a4f3be5e46
@ -48,6 +48,6 @@
|
|||||||
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring",
|
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring",
|
||||||
"INFRASTRUCTURE_MONITORING_KUBERNETES": "SigNoz | Infra Monitoring",
|
"INFRASTRUCTURE_MONITORING_KUBERNETES": "SigNoz | Infra Monitoring",
|
||||||
"METER_EXPLORER": "SigNoz | Meter Explorer",
|
"METER_EXPLORER": "SigNoz | Meter Explorer",
|
||||||
"METER_EXPLORER_VIEWS": "SigNoz | Meter Explorer",
|
"METER_EXPLORER_VIEWS": "SigNoz | Meter Explorer Views",
|
||||||
"METER_EXPLORER_BASE": "SigNoz | Meter Explorer"
|
"METER": "SigNoz | Meter"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,6 +71,6 @@
|
|||||||
"METRICS_EXPLORER_VIEWS": "SigNoz | Metrics Explorer",
|
"METRICS_EXPLORER_VIEWS": "SigNoz | Metrics Explorer",
|
||||||
"API_MONITORING": "SigNoz | External APIs",
|
"API_MONITORING": "SigNoz | External APIs",
|
||||||
"METER_EXPLORER": "SigNoz | Meter Explorer",
|
"METER_EXPLORER": "SigNoz | Meter Explorer",
|
||||||
"METER_EXPLORER_VIEWS": "SigNoz | Meter Explorer",
|
"METER_EXPLORER_VIEWS": "SigNoz | Meter Explorer Views",
|
||||||
"METER_EXPLORER_BASE": "SigNoz | Meter Explorer"
|
"METER": "SigNoz | Meter"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -437,10 +437,10 @@ const routes: AppRoutes[] = [
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: ROUTES.METER_EXPLORER_BASE,
|
path: ROUTES.METER,
|
||||||
exact: true,
|
exact: true,
|
||||||
component: MeterExplorer,
|
component: MeterExplorer,
|
||||||
key: 'METER_EXPLORER_BASE',
|
key: 'METER',
|
||||||
isPrivate: true,
|
isPrivate: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,8 +5,11 @@ import { SignalType } from 'components/QuickFilters/types';
|
|||||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||||
import { useGetAggregateKeys } from 'hooks/queryBuilder/useGetAggregateKeys';
|
import { useGetAggregateKeys } from 'hooks/queryBuilder/useGetAggregateKeys';
|
||||||
import { useGetAttributeSuggestions } from 'hooks/queryBuilder/useGetAttributeSuggestions';
|
import { useGetAttributeSuggestions } from 'hooks/queryBuilder/useGetAttributeSuggestions';
|
||||||
|
import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { QueryKeyDataSuggestionsProps } from 'types/api/querySuggestions/types';
|
||||||
import { Filter as FilterType } from 'types/api/quickFilters/getCustomFilters';
|
import { Filter as FilterType } from 'types/api/quickFilters/getCustomFilters';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
@ -40,6 +43,10 @@ function OtherFilters({
|
|||||||
() => SIGNAL_DATA_SOURCE_MAP[signal as SignalType] === DataSource.LOGS,
|
() => SIGNAL_DATA_SOURCE_MAP[signal as SignalType] === DataSource.LOGS,
|
||||||
[signal],
|
[signal],
|
||||||
);
|
);
|
||||||
|
const isMeterDataSource = useMemo(
|
||||||
|
() => signal && signal === SignalType.METER_EXPLORER,
|
||||||
|
[signal],
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: suggestionsData,
|
data: suggestionsData,
|
||||||
@ -69,7 +76,22 @@ function OtherFilters({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
queryKey: [REACT_QUERY_KEY.GET_OTHER_FILTERS, inputValue],
|
queryKey: [REACT_QUERY_KEY.GET_OTHER_FILTERS, inputValue],
|
||||||
enabled: !!signal && !isLogDataSource,
|
enabled: !!signal && !isLogDataSource && !isMeterDataSource,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: fieldKeysData,
|
||||||
|
isLoading: isLoadingFieldKeys,
|
||||||
|
} = useGetQueryKeySuggestions(
|
||||||
|
{
|
||||||
|
searchText: inputValue,
|
||||||
|
signal: SIGNAL_DATA_SOURCE_MAP[signal as SignalType],
|
||||||
|
signalSource: 'meter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
queryKey: [REACT_QUERY_KEY.GET_OTHER_FILTERS, inputValue],
|
||||||
|
enabled: !!signal && isMeterDataSource,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -77,13 +99,33 @@ function OtherFilters({
|
|||||||
let filterAttributes;
|
let filterAttributes;
|
||||||
if (isLogDataSource) {
|
if (isLogDataSource) {
|
||||||
filterAttributes = suggestionsData?.payload?.attributes || [];
|
filterAttributes = suggestionsData?.payload?.attributes || [];
|
||||||
|
} else if (isMeterDataSource) {
|
||||||
|
const fieldKeys: QueryKeyDataSuggestionsProps[] = Object.values(
|
||||||
|
fieldKeysData?.data?.data?.keys || {},
|
||||||
|
)?.flat();
|
||||||
|
filterAttributes = fieldKeys.map(
|
||||||
|
(attr) =>
|
||||||
|
({
|
||||||
|
key: attr.name,
|
||||||
|
dataType: attr.fieldDataType,
|
||||||
|
type: attr.fieldContext,
|
||||||
|
signal: attr.signal,
|
||||||
|
} as BaseAutocompleteData),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
filterAttributes = aggregateKeysData?.payload?.attributeKeys || [];
|
filterAttributes = aggregateKeysData?.payload?.attributeKeys || [];
|
||||||
}
|
}
|
||||||
return filterAttributes?.filter(
|
return filterAttributes?.filter(
|
||||||
(attr) => !addedFilters.some((filter) => filter.key === attr.key),
|
(attr) => !addedFilters.some((filter) => filter.key === attr.key),
|
||||||
);
|
);
|
||||||
}, [suggestionsData, aggregateKeysData, addedFilters, isLogDataSource]);
|
}, [
|
||||||
|
suggestionsData,
|
||||||
|
aggregateKeysData,
|
||||||
|
addedFilters,
|
||||||
|
isLogDataSource,
|
||||||
|
fieldKeysData,
|
||||||
|
isMeterDataSource,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleAddFilter = (filter: FilterType): void => {
|
const handleAddFilter = (filter: FilterType): void => {
|
||||||
setAddedFilters((prev) => [
|
setAddedFilters((prev) => [
|
||||||
@ -99,7 +141,8 @@ function OtherFilters({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderFilters = (): React.ReactNode => {
|
const renderFilters = (): React.ReactNode => {
|
||||||
const isLoading = isFetchingSuggestions || isFetchingAggregateKeys;
|
const isLoading =
|
||||||
|
isFetchingSuggestions || isFetchingAggregateKeys || isLoadingFieldKeys;
|
||||||
if (isLoading) return <OtherFiltersSkeleton />;
|
if (isLoading) return <OtherFiltersSkeleton />;
|
||||||
if (!otherFilters?.length)
|
if (!otherFilters?.length)
|
||||||
return <div className="no-values-found">No values found</div>;
|
return <div className="no-values-found">No values found</div>;
|
||||||
|
|||||||
@ -77,9 +77,9 @@ const ROUTES = {
|
|||||||
API_MONITORING: '/api-monitoring/explorer',
|
API_MONITORING: '/api-monitoring/explorer',
|
||||||
METRICS_EXPLORER_BASE: '/metrics-explorer',
|
METRICS_EXPLORER_BASE: '/metrics-explorer',
|
||||||
WORKSPACE_ACCESS_RESTRICTED: '/workspace-access-restricted',
|
WORKSPACE_ACCESS_RESTRICTED: '/workspace-access-restricted',
|
||||||
METER_EXPLORER_BASE: '/meter-explorer',
|
METER: '/meter',
|
||||||
METER_EXPLORER: '/meter-explorer',
|
METER_EXPLORER: '/meter/explorer',
|
||||||
METER_EXPLORER_VIEWS: '/meter-explorer/views',
|
METER_EXPLORER_VIEWS: '/meter/explorer/views',
|
||||||
HOME_PAGE: '/',
|
HOME_PAGE: '/',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,92 @@
|
|||||||
|
.meter-explorer-breakdown {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.meter-explorer-date-time {
|
||||||
|
display: flex;
|
||||||
|
min-height: 30px;
|
||||||
|
justify-content: end;
|
||||||
|
border-bottom: 1px solid var(--bg-slate-500);
|
||||||
|
padding: 10px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meter-explorer-graphs {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 36px;
|
||||||
|
|
||||||
|
.meter-column-graph {
|
||||||
|
.row-card {
|
||||||
|
background-color: var(--bg-ink-400);
|
||||||
|
padding-left: 10px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
color: var(--bg-vanilla-400);
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: -0.07px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-description {
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meter-page-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
.meter-graph {
|
||||||
|
height: 400px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.total {
|
||||||
|
.meter-column-graph {
|
||||||
|
.meter-page-grid {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
|
||||||
|
.meter-graph {
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightMode {
|
||||||
|
.meter-explorer-breakdown {
|
||||||
|
.meter-explorer-date-time {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meter-explorer-graphs {
|
||||||
|
.meter-column-graph {
|
||||||
|
.row-card {
|
||||||
|
background-color: var(--bg-vanilla-300);
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
color: var(--bg-ink-400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
200
frontend/src/container/MeterExplorer/Breakdown/BreakDown.tsx
Normal file
200
frontend/src/container/MeterExplorer/Breakdown/BreakDown.tsx
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import './BreakDown.styles.scss';
|
||||||
|
|
||||||
|
import { Typography } from 'antd';
|
||||||
|
// import useFilterConfig from 'components/QuickFilters/hooks/useFilterConfig';
|
||||||
|
// import { SignalType } from 'components/QuickFilters/types';
|
||||||
|
import { QueryParams } from 'constants/query';
|
||||||
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
|
import GridCard from 'container/GridCardLayout/GridCard';
|
||||||
|
import { Card, CardContainer } from 'container/GridCardLayout/styles';
|
||||||
|
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
|
||||||
|
// import { useGetQueryKeyValueSuggestions } from 'hooks/querySuggestions/useGetQueryKeyValueSuggestions';
|
||||||
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
|
import { UpdateTimeInterval } from 'store/actions';
|
||||||
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
|
// import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getLogCountWidgetData,
|
||||||
|
getLogSizeWidgetData,
|
||||||
|
getMetricCountWidgetData,
|
||||||
|
getSpanCountWidgetData,
|
||||||
|
getSpanSizeWidgetData,
|
||||||
|
getTotalLogSizeWidgetData,
|
||||||
|
getTotalMetricDatapointCountWidgetData,
|
||||||
|
getTotalTraceSizeWidgetData,
|
||||||
|
} from './graphs';
|
||||||
|
|
||||||
|
type MetricSection = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
graphs: Widgets[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const sections: MetricSection[] = [
|
||||||
|
{
|
||||||
|
id: uuid(),
|
||||||
|
title: 'Total',
|
||||||
|
graphs: [
|
||||||
|
getTotalLogSizeWidgetData(),
|
||||||
|
getTotalTraceSizeWidgetData(),
|
||||||
|
getTotalMetricDatapointCountWidgetData(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: uuid(),
|
||||||
|
title: 'Logs',
|
||||||
|
graphs: [getLogCountWidgetData(), getLogSizeWidgetData()],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: uuid(),
|
||||||
|
title: 'Traces',
|
||||||
|
graphs: [getSpanCountWidgetData(), getSpanSizeWidgetData()],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: uuid(),
|
||||||
|
title: 'Metrics',
|
||||||
|
graphs: [getMetricCountWidgetData()],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function Section(section: MetricSection): JSX.Element {
|
||||||
|
const isDarkMode = useIsDarkMode();
|
||||||
|
const { title, graphs } = section;
|
||||||
|
const history = useHistory();
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const urlQuery = useUrlQuery();
|
||||||
|
|
||||||
|
const onDragSelect = useCallback(
|
||||||
|
(start: number, end: number) => {
|
||||||
|
const startTimestamp = Math.trunc(start);
|
||||||
|
const endTimestamp = Math.trunc(end);
|
||||||
|
|
||||||
|
urlQuery.set(QueryParams.startTime, startTimestamp.toString());
|
||||||
|
urlQuery.set(QueryParams.endTime, endTimestamp.toString());
|
||||||
|
const generatedUrl = `${pathname}?${urlQuery.toString()}`;
|
||||||
|
history.push(generatedUrl);
|
||||||
|
|
||||||
|
if (startTimestamp !== endTimestamp) {
|
||||||
|
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dispatch, history, pathname, urlQuery],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="meter-column-graph">
|
||||||
|
<CardContainer className="row-card" isDarkMode={isDarkMode}>
|
||||||
|
<Typography.Text className="section-title">{title}</Typography.Text>
|
||||||
|
</CardContainer>
|
||||||
|
<div className="meter-page-grid">
|
||||||
|
{graphs.map((widget) => (
|
||||||
|
<Card
|
||||||
|
key={widget?.id}
|
||||||
|
isDarkMode={isDarkMode}
|
||||||
|
$panelType={PANEL_TYPES.BAR}
|
||||||
|
className="meter-graph"
|
||||||
|
>
|
||||||
|
<GridCard widget={widget} onDragSelect={onDragSelect} version="v5" />
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function FilterDropdown({ attrKey }: { attrKey: string }): JSX.Element {
|
||||||
|
// const {
|
||||||
|
// data: keyValueSuggestions,
|
||||||
|
// isLoading: isLoadingKeyValueSuggestions,
|
||||||
|
// } = useGetQueryKeyValueSuggestions({
|
||||||
|
// key: attrKey,
|
||||||
|
// signal: DataSource.METRICS,
|
||||||
|
// signalSource: 'meter',
|
||||||
|
// options: {
|
||||||
|
// keepPreviousData: true,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const responseData = keyValueSuggestions?.data as any;
|
||||||
|
// const values = responseData?.data?.values || {};
|
||||||
|
// const stringValues = values.stringValues || [];
|
||||||
|
// const numberValues = values.numberValues || [];
|
||||||
|
|
||||||
|
// const stringOptions = stringValues.filter(
|
||||||
|
// (value: string | null | undefined): value is string =>
|
||||||
|
// value !== null && value !== undefined && value !== '',
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const numberOptions = numberValues
|
||||||
|
// .filter(
|
||||||
|
// (value: number | null | undefined): value is number =>
|
||||||
|
// value !== null && value !== undefined,
|
||||||
|
// )
|
||||||
|
// .map((value: number) => value.toString());
|
||||||
|
|
||||||
|
// const vals = [...stringOptions, ...numberOptions];
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className="filter-dropdown">
|
||||||
|
// <Typography.Text>{attrKey}</Typography.Text>
|
||||||
|
// <Select
|
||||||
|
// loading={isLoadingKeyValueSuggestions}
|
||||||
|
// options={vals?.map((suggestion: any) => ({
|
||||||
|
// label: suggestion,
|
||||||
|
// value: suggestion,
|
||||||
|
// }))}
|
||||||
|
// placeholder={`Select ${attrKey}`}
|
||||||
|
// />
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
function BreakDown(): JSX.Element {
|
||||||
|
// const { customFilters } = useFilterConfig({
|
||||||
|
// signal: SignalType.METER_EXPLORER,
|
||||||
|
// config: [],
|
||||||
|
// });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="meter-explorer-breakdown">
|
||||||
|
<section className="meter-explorer-date-time">
|
||||||
|
{/* {customFilters.map((filter) => (
|
||||||
|
<FilterDropdown key={filter.key} attrKey={filter.key} />
|
||||||
|
))} */}
|
||||||
|
<DateTimeSelectionV2 showAutoRefresh={false} />
|
||||||
|
</section>
|
||||||
|
<section className="meter-explorer-graphs">
|
||||||
|
<section className="total">
|
||||||
|
<Section
|
||||||
|
id={sections[0].id}
|
||||||
|
title={sections[0].title}
|
||||||
|
graphs={sections[0].graphs}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
{sections.map((section, idx) => {
|
||||||
|
if (idx === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section
|
||||||
|
key={section.id}
|
||||||
|
id={section.id}
|
||||||
|
title={section.title}
|
||||||
|
graphs={section.graphs}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BreakDown;
|
||||||
390
frontend/src/container/MeterExplorer/Breakdown/graphs.ts
Normal file
390
frontend/src/container/MeterExplorer/Breakdown/graphs.ts
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
|
import { GetWidgetQueryBuilderProps } from 'container/MetricsApplication/types';
|
||||||
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
|
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
import {
|
||||||
|
IBuilderFormula,
|
||||||
|
IBuilderQuery,
|
||||||
|
} from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
interface GetWidgetQueryProps {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
queryData: IBuilderQuery[];
|
||||||
|
queryFormulas?: IBuilderFormula[];
|
||||||
|
panelTypes?: PANEL_TYPES;
|
||||||
|
yAxisUnit?: string;
|
||||||
|
columnUnits?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GetWidgetQueryPropsReturn extends GetWidgetQueryBuilderProps {
|
||||||
|
description?: string;
|
||||||
|
nullZeroValues: string;
|
||||||
|
columnUnits?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getWidgetQueryBuilder = ({
|
||||||
|
query,
|
||||||
|
title = '',
|
||||||
|
panelTypes,
|
||||||
|
yAxisUnit = '',
|
||||||
|
fillSpans = false,
|
||||||
|
id,
|
||||||
|
nullZeroValues,
|
||||||
|
description,
|
||||||
|
}: GetWidgetQueryPropsReturn): Widgets => ({
|
||||||
|
description: description || '',
|
||||||
|
id: id || uuid(),
|
||||||
|
isStacked: false,
|
||||||
|
nullZeroValues: nullZeroValues || '',
|
||||||
|
opacity: '1',
|
||||||
|
panelTypes,
|
||||||
|
query,
|
||||||
|
timePreferance: 'GLOBAL_TIME',
|
||||||
|
title,
|
||||||
|
yAxisUnit,
|
||||||
|
softMax: null,
|
||||||
|
softMin: null,
|
||||||
|
selectedLogFields: [],
|
||||||
|
selectedTracesFields: [],
|
||||||
|
fillSpans,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getWidgetQuery(
|
||||||
|
props: GetWidgetQueryProps,
|
||||||
|
): GetWidgetQueryPropsReturn {
|
||||||
|
const { title, description, panelTypes, yAxisUnit, columnUnits } = props;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
yAxisUnit: yAxisUnit || 'none',
|
||||||
|
panelTypes: panelTypes || PANEL_TYPES.TIME_SERIES,
|
||||||
|
fillSpans: false,
|
||||||
|
description,
|
||||||
|
nullZeroValues: 'zero',
|
||||||
|
columnUnits,
|
||||||
|
query: {
|
||||||
|
queryType: EQueryType.QUERY_BUILDER,
|
||||||
|
promql: [],
|
||||||
|
builder: {
|
||||||
|
queryData: props.queryData,
|
||||||
|
queryFormulas: (props.queryFormulas as IBuilderFormula[]) || [],
|
||||||
|
},
|
||||||
|
clickhouse_sql: [],
|
||||||
|
id: uuid(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export const getTotalLogSizeWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.log.size',
|
||||||
|
id: 'signoz.meter.log.size--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'count',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'sum',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Total size of log records ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.VALUE,
|
||||||
|
yAxisUnit: 'bytes',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getTotalTraceSizeWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.span.size',
|
||||||
|
id: 'signoz.meter.span.size--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'count',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'sum',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Total size of spans ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.VALUE,
|
||||||
|
yAxisUnit: 'bytes',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getTotalMetricDatapointCountWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.metric.datapoint.count',
|
||||||
|
id: 'signoz.meter.metric.datapoint.count--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'count',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'sum',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Total metric datapoints ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.VALUE,
|
||||||
|
yAxisUnit: 'short',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getLogCountWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.log.count',
|
||||||
|
id: 'signoz.meter.log.count--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'count',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Count of log records ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.BAR,
|
||||||
|
yAxisUnit: 'short',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getLogSizeWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.log.size',
|
||||||
|
id: 'signoz.meter.log.size--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'size',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Size of log records ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.BAR,
|
||||||
|
yAxisUnit: 'bytes',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getSpanCountWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.span.count',
|
||||||
|
id: 'signoz.meter.span.count--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'count',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Count of spans ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.BAR,
|
||||||
|
yAxisUnit: 'short',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getSpanSizeWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.span.size',
|
||||||
|
id: 'signoz.meter.span.size--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'size',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Size of spans ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.BAR,
|
||||||
|
yAxisUnit: 'bytes',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getMetricCountWidgetData = (): Widgets =>
|
||||||
|
getWidgetQueryBuilder(
|
||||||
|
getWidgetQuery({
|
||||||
|
queryData: [
|
||||||
|
{
|
||||||
|
aggregateAttribute: {
|
||||||
|
dataType: DataTypes.Float64,
|
||||||
|
key: 'signoz.meter.metric.datapoint.count',
|
||||||
|
id: 'signoz.meter.metric.datapoint.count--float64--Sum--true',
|
||||||
|
isColumn: true,
|
||||||
|
isJSON: false,
|
||||||
|
type: 'Sum',
|
||||||
|
},
|
||||||
|
aggregateOperator: 'increase',
|
||||||
|
dataSource: DataSource.METRICS,
|
||||||
|
source: 'meter',
|
||||||
|
disabled: false,
|
||||||
|
expression: 'A',
|
||||||
|
filters: { items: [], op: 'AND' },
|
||||||
|
functions: [],
|
||||||
|
groupBy: [],
|
||||||
|
having: [],
|
||||||
|
legend: 'count',
|
||||||
|
limit: null,
|
||||||
|
orderBy: [],
|
||||||
|
queryName: 'A',
|
||||||
|
reduceTo: 'avg',
|
||||||
|
spaceAggregation: 'sum',
|
||||||
|
stepInterval: 60,
|
||||||
|
timeAggregation: 'increase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: 'Count of metric datapoints ingested',
|
||||||
|
description: '',
|
||||||
|
panelTypes: PANEL_TYPES.BAR,
|
||||||
|
yAxisUnit: 'short',
|
||||||
|
}),
|
||||||
|
);
|
||||||
@ -43,7 +43,7 @@ function Explorer(): JSX.Element {
|
|||||||
() =>
|
() =>
|
||||||
updateAllQueriesOperators(
|
updateAllQueriesOperators(
|
||||||
initialQueryMeterWithType,
|
initialQueryMeterWithType,
|
||||||
PANEL_TYPES.TIME_SERIES,
|
PANEL_TYPES.BAR,
|
||||||
DataSource.METRICS,
|
DataSource.METRICS,
|
||||||
'meter' as 'meter' | '',
|
'meter' as 'meter' | '',
|
||||||
),
|
),
|
||||||
@ -54,7 +54,7 @@ function Explorer(): JSX.Element {
|
|||||||
() =>
|
() =>
|
||||||
updateAllQueriesOperators(
|
updateAllQueriesOperators(
|
||||||
currentQuery || initialQueryMeterWithType,
|
currentQuery || initialQueryMeterWithType,
|
||||||
PANEL_TYPES.TIME_SERIES,
|
PANEL_TYPES.BAR,
|
||||||
DataSource.METRICS,
|
DataSource.METRICS,
|
||||||
'meter' as 'meter' | '',
|
'meter' as 'meter' | '',
|
||||||
),
|
),
|
||||||
@ -75,7 +75,7 @@ function Explorer(): JSX.Element {
|
|||||||
|
|
||||||
const dashboardEditView = generateExportToDashboardLink({
|
const dashboardEditView = generateExportToDashboardLink({
|
||||||
query: queryToExport || exportDefaultQuery,
|
query: queryToExport || exportDefaultQuery,
|
||||||
panelType: PANEL_TYPES.TIME_SERIES,
|
panelType: PANEL_TYPES.BAR,
|
||||||
dashboardId: dashboard.id,
|
dashboardId: dashboard.id,
|
||||||
widgetId,
|
widgetId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -69,7 +69,7 @@ function TimeSeries(): JSX.Element {
|
|||||||
GetMetricQueryRange(
|
GetMetricQueryRange(
|
||||||
{
|
{
|
||||||
query: payload,
|
query: payload,
|
||||||
graphType: PANEL_TYPES.TIME_SERIES,
|
graphType: PANEL_TYPES.BAR,
|
||||||
selectedTime: 'GLOBAL_TIME',
|
selectedTime: 'GLOBAL_TIME',
|
||||||
globalSelectedInterval: globalSelectedTime,
|
globalSelectedInterval: globalSelectedTime,
|
||||||
params: {
|
params: {
|
||||||
@ -131,6 +131,7 @@ function TimeSeries(): JSX.Element {
|
|||||||
data={datapoint}
|
data={datapoint}
|
||||||
dataSource={DataSource.METRICS}
|
dataSource={DataSource.METRICS}
|
||||||
yAxisUnit={yAxisUnit}
|
yAxisUnit={yAxisUnit}
|
||||||
|
panelType={PANEL_TYPES.BAR}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -266,8 +266,8 @@ export const defaultMoreMenuItems: SidebarItem[] = [
|
|||||||
itemKey: 'external-apis',
|
itemKey: 'external-apis',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: ROUTES.METER_EXPLORER,
|
key: ROUTES.METER,
|
||||||
label: 'Meter Explorer',
|
label: 'Cost Meter',
|
||||||
icon: <ChartArea size={16} />,
|
icon: <ChartArea size={16} />,
|
||||||
isNew: false,
|
isNew: false,
|
||||||
isEnabled: false,
|
isEnabled: false,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import logEvent from 'api/common/logEvent';
|
|||||||
import ErrorInPlace from 'components/ErrorInPlace/ErrorInPlace';
|
import ErrorInPlace from 'components/ErrorInPlace/ErrorInPlace';
|
||||||
import Uplot from 'components/Uplot';
|
import Uplot from 'components/Uplot';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import EmptyLogsSearch from 'container/EmptyLogsSearch/EmptyLogsSearch';
|
import EmptyLogsSearch from 'container/EmptyLogsSearch/EmptyLogsSearch';
|
||||||
import { getLocalStorageGraphVisibilityState } from 'container/GridCardLayout/GridCard/utils';
|
import { getLocalStorageGraphVisibilityState } from 'container/GridCardLayout/GridCard/utils';
|
||||||
import { LogsLoading } from 'container/LogsLoading/LogsLoading';
|
import { LogsLoading } from 'container/LogsLoading/LogsLoading';
|
||||||
@ -54,6 +55,7 @@ function TimeSeriesView({
|
|||||||
isFilterApplied,
|
isFilterApplied,
|
||||||
dataSource,
|
dataSource,
|
||||||
setWarning,
|
setWarning,
|
||||||
|
panelType = PANEL_TYPES.TIME_SERIES,
|
||||||
}: TimeSeriesViewProps): JSX.Element {
|
}: TimeSeriesViewProps): JSX.Element {
|
||||||
const graphRef = useRef<HTMLDivElement>(null);
|
const graphRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@ -191,6 +193,7 @@ function TimeSeriesView({
|
|||||||
maxTimeScale,
|
maxTimeScale,
|
||||||
softMax: null,
|
softMax: null,
|
||||||
softMin: null,
|
softMin: null,
|
||||||
|
panelType,
|
||||||
tzDate: (timestamp: number) =>
|
tzDate: (timestamp: number) =>
|
||||||
uPlot.tzDate(new Date(timestamp * 1e3), timezone.value),
|
uPlot.tzDate(new Date(timestamp * 1e3), timezone.value),
|
||||||
timezone: timezone.value,
|
timezone: timezone.value,
|
||||||
@ -259,6 +262,7 @@ interface TimeSeriesViewProps {
|
|||||||
isFilterApplied: boolean;
|
isFilterApplied: boolean;
|
||||||
dataSource: DataSource;
|
dataSource: DataSource;
|
||||||
setWarning?: Dispatch<SetStateAction<Warning | undefined>>;
|
setWarning?: Dispatch<SetStateAction<Warning | undefined>>;
|
||||||
|
panelType?: PANEL_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeSeriesView.defaultProps = {
|
TimeSeriesView.defaultProps = {
|
||||||
@ -266,6 +270,7 @@ TimeSeriesView.defaultProps = {
|
|||||||
yAxisUnit: 'short',
|
yAxisUnit: 'short',
|
||||||
error: undefined,
|
error: undefined,
|
||||||
setWarning: undefined,
|
setWarning: undefined,
|
||||||
|
panelType: PANEL_TYPES.TIME_SERIES,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TimeSeriesView;
|
export default TimeSeriesView;
|
||||||
|
|||||||
@ -234,7 +234,7 @@ export const routesToSkip = [
|
|||||||
ROUTES.UN_AUTHORIZED,
|
ROUTES.UN_AUTHORIZED,
|
||||||
ROUTES.NOT_FOUND,
|
ROUTES.NOT_FOUND,
|
||||||
ROUTES.METER_EXPLORER,
|
ROUTES.METER_EXPLORER,
|
||||||
ROUTES.METER_EXPLORER_BASE,
|
ROUTES.METER,
|
||||||
ROUTES.METER_EXPLORER_VIEWS,
|
ROUTES.METER_EXPLORER_VIEWS,
|
||||||
ROUTES.SOMETHING_WENT_WRONG,
|
ROUTES.SOMETHING_WENT_WRONG,
|
||||||
];
|
];
|
||||||
|
|||||||
@ -25,6 +25,7 @@ export const useGetQueryKeySuggestions: UseGetQueryKeySuggestions = (
|
|||||||
fieldContext,
|
fieldContext,
|
||||||
fieldDataType,
|
fieldDataType,
|
||||||
metricName,
|
metricName,
|
||||||
|
signalSource,
|
||||||
}: QueryKeyRequestProps,
|
}: QueryKeyRequestProps,
|
||||||
options?: UseQueryOptions<
|
options?: UseQueryOptions<
|
||||||
AxiosResponse<QueryKeySuggestionsResponseProps>,
|
AxiosResponse<QueryKeySuggestionsResponseProps>,
|
||||||
@ -42,6 +43,7 @@ export const useGetQueryKeySuggestions: UseGetQueryKeySuggestions = (
|
|||||||
metricName,
|
metricName,
|
||||||
fieldContext,
|
fieldContext,
|
||||||
fieldDataType,
|
fieldDataType,
|
||||||
|
signalSource,
|
||||||
];
|
];
|
||||||
}, [
|
}, [
|
||||||
options?.queryKey,
|
options?.queryKey,
|
||||||
@ -50,6 +52,7 @@ export const useGetQueryKeySuggestions: UseGetQueryKeySuggestions = (
|
|||||||
metricName,
|
metricName,
|
||||||
fieldContext,
|
fieldContext,
|
||||||
fieldDataType,
|
fieldDataType,
|
||||||
|
signalSource,
|
||||||
]);
|
]);
|
||||||
return useQuery<AxiosResponse<QueryKeySuggestionsResponseProps>, AxiosError>({
|
return useQuery<AxiosResponse<QueryKeySuggestionsResponseProps>, AxiosError>({
|
||||||
queryKey,
|
queryKey,
|
||||||
@ -60,6 +63,7 @@ export const useGetQueryKeySuggestions: UseGetQueryKeySuggestions = (
|
|||||||
metricName,
|
metricName,
|
||||||
fieldContext,
|
fieldContext,
|
||||||
fieldDataType,
|
fieldDataType,
|
||||||
|
signalSource,
|
||||||
}),
|
}),
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,19 +2,25 @@ import './MeterExplorer.styles.scss';
|
|||||||
|
|
||||||
import RouteTab from 'components/RouteTab';
|
import RouteTab from 'components/RouteTab';
|
||||||
import { TabRoutes } from 'components/RouteTab/types';
|
import { TabRoutes } from 'components/RouteTab/types';
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { useLocation } from 'react-use';
|
import { useLocation } from 'react-use';
|
||||||
|
|
||||||
import { Explorer, Views } from './constants';
|
import { Explorer, Meter, Views } from './constants';
|
||||||
|
|
||||||
function MeterExplorerPage(): JSX.Element {
|
function MeterExplorerPage(): JSX.Element {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
const routes: TabRoutes[] = [Explorer, Views];
|
const routes: TabRoutes[] = [Meter, Explorer, Views];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="meter-explorer-page">
|
<div className="meter-explorer-page">
|
||||||
<RouteTab routes={routes} activeKey={pathname} history={history} />
|
<RouteTab
|
||||||
|
routes={routes}
|
||||||
|
activeKey={pathname}
|
||||||
|
history={history}
|
||||||
|
defaultActiveKey={ROUTES.METER}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { TabRoutes } from 'components/RouteTab/types';
|
import { TabRoutes } from 'components/RouteTab/types';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
|
import BreakDownPage from 'container/MeterExplorer/Breakdown/BreakDown';
|
||||||
import ExplorerPage from 'container/MeterExplorer/Explorer';
|
import ExplorerPage from 'container/MeterExplorer/Explorer';
|
||||||
import { Compass, TowerControl } from 'lucide-react';
|
import { Compass, TowerControl } from 'lucide-react';
|
||||||
import SaveView from 'pages/SaveView';
|
import SaveView from 'pages/SaveView';
|
||||||
@ -30,3 +31,14 @@ export const Views: TabRoutes = {
|
|||||||
route: ROUTES.METER_EXPLORER_VIEWS,
|
route: ROUTES.METER_EXPLORER_VIEWS,
|
||||||
key: ROUTES.METER_EXPLORER_VIEWS,
|
key: ROUTES.METER_EXPLORER_VIEWS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const Meter: TabRoutes = {
|
||||||
|
Component: BreakDownPage,
|
||||||
|
name: (
|
||||||
|
<div className="tab-item">
|
||||||
|
<TowerControl size={16} /> Meter
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
route: ROUTES.METER,
|
||||||
|
key: ROUTES.METER,
|
||||||
|
};
|
||||||
|
|||||||
@ -124,6 +124,6 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
|
|||||||
API_MONITORING_BASE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
API_MONITORING_BASE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
MESSAGING_QUEUES_BASE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
MESSAGING_QUEUES_BASE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
METER_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
METER_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
METER_EXPLORER_BASE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
METER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
METER_EXPLORER_VIEWS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
METER_EXPLORER_VIEWS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user