From f1c7d72fc51d1b06d3f210df3aef063e8679636c Mon Sep 17 00:00:00 2001 From: Priyanka Chakraborty Date: Tue, 24 Jan 2023 09:30:26 +0530 Subject: [PATCH] 1375 overview querybuilder (#1983) --- .../MetricsApplication.factory.ts | 20 ++++ .../MetricsPageQueries/OverviewQueries.ts | 112 ++++++++++++++++++ .../MetricsApplication/Tabs/Overview.tsx | 73 ++++++++---- .../container/MetricsApplication/index.tsx | 47 +------- 4 files changed, 183 insertions(+), 69 deletions(-) create mode 100644 frontend/src/container/MetricsApplication/MetricsApplication.factory.ts create mode 100644 frontend/src/container/MetricsApplication/MetricsPageQueries/OverviewQueries.ts diff --git a/frontend/src/container/MetricsApplication/MetricsApplication.factory.ts b/frontend/src/container/MetricsApplication/MetricsApplication.factory.ts new file mode 100644 index 0000000000..0175aafac8 --- /dev/null +++ b/frontend/src/container/MetricsApplication/MetricsApplication.factory.ts @@ -0,0 +1,20 @@ +import { Widgets } from 'types/api/dashboard/getAll'; +import { v4 } from 'uuid'; + +export const getWidgetQueryBuilder = (query: Widgets['query']): Widgets => ({ + description: '', + id: v4(), + isStacked: false, + nullZeroValues: '', + opacity: '0', + panelTypes: 'TIME_SERIES', + query, + queryData: { + data: { queryData: [] }, + error: false, + errorMessage: '', + loading: false, + }, + timePreferance: 'GLOBAL_TIME', + title: '', +}); diff --git a/frontend/src/container/MetricsApplication/MetricsPageQueries/OverviewQueries.ts b/frontend/src/container/MetricsApplication/MetricsPageQueries/OverviewQueries.ts new file mode 100644 index 0000000000..77182c789c --- /dev/null +++ b/frontend/src/container/MetricsApplication/MetricsPageQueries/OverviewQueries.ts @@ -0,0 +1,112 @@ +import { + IMetricsBuilderFormula, + IMetricsBuilderQuery, + IQueryBuilderTagFilterItems, +} from 'types/api/dashboard/getAll'; + +import { + getQueryBuilderQueries, + getQueryBuilderQuerieswithFormula, +} from './MetricsPageQueriesFactory'; + +export const operationPerSec = ({ + servicename, + tagFilterItems, + topLevelOperations, +}: OperationPerSecProps): IOverviewQueries => { + const metricName = 'signoz_latency_count'; + const legend = 'Operations'; + const itemsA = [ + { + id: '', + key: 'service_name', + op: 'IN', + value: [`${servicename}`], + }, + { + id: '', + key: 'operation', + op: 'MATCH', + value: topLevelOperations, + }, + ...tagFilterItems, + ]; + + return getQueryBuilderQueries({ + metricName, + legend, + itemsA, + }); +}; + +export const errorPercentage = ({ + servicename, + tagFilterItems, + topLevelOperations, +}: OperationPerSecProps): IOverviewQueries => { + const metricNameA = 'signoz_calls_total'; + const metricNameB = 'signoz_calls_total'; + const additionalItemsA = [ + { + id: '', + key: 'service_name', + op: 'IN', + value: [`${servicename}`], + }, + { + id: '', + key: 'operation', + op: 'MATCH', + value: topLevelOperations, + }, + { + id: '', + key: 'status_code', + op: 'IN', + value: ['STATUS_CODE_ERROR'], + }, + ...tagFilterItems, + ]; + + const additionalItemsB = [ + { + id: '', + key: 'service_name', + op: 'IN', + value: [`${servicename}`], + }, + { + id: '', + key: 'operation', + op: 'MATCH', + value: topLevelOperations, + }, + ...tagFilterItems, + ]; + + const legendFormula = 'Error Percentage'; + const legend = legendFormula; + const expression = 'A*100/B'; + const disabled = true; + return getQueryBuilderQuerieswithFormula({ + metricNameA, + metricNameB, + additionalItemsA, + additionalItemsB, + legend, + disabled, + expression, + legendFormula, + }); +}; + +export interface OperationPerSecProps { + servicename: string | undefined; + tagFilterItems: IQueryBuilderTagFilterItems[]; + topLevelOperations: string[]; +} + +interface IOverviewQueries { + formulas: IMetricsBuilderFormula[]; + queryBuilder: IMetricsBuilderQuery[]; +} diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx index 308181b180..7137658177 100644 --- a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx @@ -2,25 +2,31 @@ import { ActiveElement, Chart, ChartData, ChartEvent } from 'chart.js'; import Graph from 'components/Graph'; import { METRICS_PAGE_QUERY_PARAM } from 'constants/query'; import ROUTES from 'constants/routes'; -import FullView from 'container/GridGraphLayout/Graph/FullView'; +import FullView from 'container/GridGraphLayout/Graph/FullView/index.metricsBuilder'; import convertToNanoSecondsToSecond from 'lib/convertToNanoSecondsToSecond'; import { colors } from 'lib/getRandomColor'; import history from 'lib/history'; -import { convertRawQueriesToTraceSelectedTags } from 'lib/resourceAttributes'; -import { escapeRegExp } from 'lodash-es'; +import { + convertRawQueriesToTraceSelectedTags, + resourceAttributesToTagFilterItems, +} from 'lib/resourceAttributes'; import React, { useCallback, useMemo, useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; import { UpdateTimeInterval } from 'store/actions'; import { AppState } from 'store/reducers'; -import { PromQLWidgets } from 'types/api/dashboard/getAll'; +import { Widgets } from 'types/api/dashboard/getAll'; import MetricReducer from 'types/reducer/metrics'; +import { + errorPercentage, + operationPerSec, +} from '../MetricsPageQueries/OverviewQueries'; import { Card, Col, GraphContainer, GraphTitle, Row } from '../styles'; import TopOperationsTable from '../TopOperationsTable'; import { Button } from './styles'; -function Application({ getWidget }: DashboardProps): JSX.Element { +function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element { const { servicename } = useParams<{ servicename?: string }>(); const selectedTimeStamp = useRef(0); const dispatch = useDispatch(); @@ -28,20 +34,49 @@ function Application({ getWidget }: DashboardProps): JSX.Element { const { topOperations, serviceOverview, - resourceAttributePromQLQuery, resourceAttributeQueries, topLevelOperations, } = useSelector((state) => state.metrics); - const operationsRegex = useMemo(() => { - return encodeURIComponent( - topLevelOperations.map((e) => escapeRegExp(e)).join('|'), - ); - }, [topLevelOperations]); const selectedTraceTags: string = JSON.stringify( convertRawQueriesToTraceSelectedTags(resourceAttributeQueries, 'array') || [], ); + const tagFilterItems = useMemo( + () => resourceAttributesToTagFilterItems(resourceAttributeQueries) || [], + [resourceAttributeQueries], + ); + + const operationPerSecWidget = useMemo( + () => + getWidgetQueryBuilder({ + queryType: 1, + promQL: [], + metricsBuilder: operationPerSec({ + servicename, + tagFilterItems, + topLevelOperations, + }), + clickHouse: [], + }), + [getWidgetQueryBuilder, servicename, topLevelOperations, tagFilterItems], + ); + + const errorPercentageWidget = useMemo( + () => + getWidgetQueryBuilder({ + queryType: 1, + promQL: [], + metricsBuilder: errorPercentage({ + servicename, + tagFilterItems, + topLevelOperations, + }), + clickHouse: [], + }), + [servicename, topLevelOperations, tagFilterItems, getWidgetQueryBuilder], + ); + const onTracePopupClick = (timestamp: number): void => { const currentTime = timestamp; const tPlusOne = timestamp + 1 * 60 * 1000; @@ -211,12 +246,7 @@ function Application({ getWidget }: DashboardProps): JSX.Element { onClickHandler={(event, element, chart, data): void => { onClickHandler(event, element, chart, data, 'Rate'); }} - widget={getWidget([ - { - query: `sum(rate(signoz_latency_count{service_name="${servicename}", operation=~\`${operationsRegex}\`${resourceAttributePromQLQuery}}[5m]))`, - legend: 'Operations', - }, - ])} + widget={operationPerSecWidget} yAxisUnit="ops" onDragSelect={onDragSelect} /> @@ -246,12 +276,7 @@ function Application({ getWidget }: DashboardProps): JSX.Element { onClickHandler={(ChartEvent, activeElements, chart, data): void => { onClickHandler(ChartEvent, activeElements, chart, data, 'Error'); }} - widget={getWidget([ - { - query: `max(sum(rate(signoz_calls_total{service_name="${servicename}", operation=~\`${operationsRegex}\`, status_code="STATUS_CODE_ERROR"${resourceAttributePromQLQuery}}[5m]) OR rate(signoz_calls_total{service_name="${servicename}", operation=~\`${operationsRegex}\`, http_status_code=~"5.."${resourceAttributePromQLQuery}}[5m]))*100/sum(rate(signoz_calls_total{service_name="${servicename}", operation=~\`${operationsRegex}\`${resourceAttributePromQLQuery}}[5m]))) < 1000 OR vector(0)`, - legend: 'Error Percentage', - }, - ])} + widget={errorPercentageWidget} yAxisUnit="%" onDragSelect={onDragSelect} /> @@ -270,7 +295,7 @@ function Application({ getWidget }: DashboardProps): JSX.Element { } interface DashboardProps { - getWidget: (query: PromQLWidgets['query']) => PromQLWidgets; + getWidgetQueryBuilder: (query: Widgets['query']) => Widgets; } export default Application; diff --git a/frontend/src/container/MetricsApplication/index.tsx b/frontend/src/container/MetricsApplication/index.tsx index 3aa6271cb4..1465103dc0 100644 --- a/frontend/src/container/MetricsApplication/index.tsx +++ b/frontend/src/container/MetricsApplication/index.tsx @@ -3,58 +3,15 @@ import ROUTES from 'constants/routes'; import React from 'react'; import { generatePath, useParams } from 'react-router-dom'; import { useLocation } from 'react-use'; -import { PromQLWidgets, Widgets } from 'types/api/dashboard/getAll'; -import { v4 } from 'uuid'; +import { getWidgetQueryBuilder } from './MetricsApplication.factory'; import ResourceAttributesFilter from './ResourceAttributesFilter'; import DBCall from './Tabs/DBCall'; import External from './Tabs/External'; import Overview from './Tabs/Overview'; -const getWidget = (query: PromQLWidgets['query']): PromQLWidgets => { - return { - description: '', - id: '', - isStacked: false, - nullZeroValues: '', - opacity: '0', - panelTypes: 'TIME_SERIES', - query, - queryData: { - data: { queryData: [] }, - error: false, - errorMessage: '', - loading: false, - }, - timePreferance: 'GLOBAL_TIME', - title: '', - stepSize: 60, - }; -}; - -const getWidgetQueryBuilder = (query: Widgets['query']): Widgets => { - return { - description: '', - id: v4(), - isStacked: false, - nullZeroValues: '', - opacity: '0', - panelTypes: 'TIME_SERIES', - query, - queryData: { - data: { queryData: [] }, - error: false, - errorMessage: '', - loading: false, - }, - timePreferance: 'GLOBAL_TIME', - title: '', - stepSize: 60, - }; -}; - function OverViewTab(): JSX.Element { - return ; + return ; } function DbCallTab(): JSX.Element {