diff --git a/frontend/src/api/trace/getFilters.ts b/frontend/src/api/trace/getFilters.ts index 1173fde10c..7eeb9404ba 100644 --- a/frontend/src/api/trace/getFilters.ts +++ b/frontend/src/api/trace/getFilters.ts @@ -32,6 +32,7 @@ const getFilters = async ( maxDuration: String((duration.duration || [])[0] || ''), minDuration: String((duration.duration || [])[1] || ''), exclude, + spanKind: props.spanKind, }); return { diff --git a/frontend/src/api/trace/getSpans.ts b/frontend/src/api/trace/getSpans.ts index 06555d20fe..8b56caa46d 100644 --- a/frontend/src/api/trace/getSpans.ts +++ b/frontend/src/api/trace/getSpans.ts @@ -44,6 +44,7 @@ const getSpans = async ( maxDuration: String((duration.duration || [])[0] || ''), minDuration: String((duration.duration || [])[1] || ''), exclude, + spanKind: props.spanKind, }, ); diff --git a/frontend/src/api/trace/getSpansAggregate.ts b/frontend/src/api/trace/getSpansAggregate.ts index 373e677ab1..cfa1f7e31f 100644 --- a/frontend/src/api/trace/getSpansAggregate.ts +++ b/frontend/src/api/trace/getSpansAggregate.ts @@ -48,6 +48,7 @@ const getSpanAggregate = async ( maxDuration: String((duration.duration || [])[0] || ''), minDuration: String((duration.duration || [])[1] || ''), exclude, + spanKind: props.spanKind, }); return { diff --git a/frontend/src/api/trace/getTagFilter.ts b/frontend/src/api/trace/getTagFilter.ts index e4cadb710c..2f53ab5a6d 100644 --- a/frontend/src/api/trace/getTagFilter.ts +++ b/frontend/src/api/trace/getTagFilter.ts @@ -32,6 +32,7 @@ const getTagFilters = async ( maxDuration: String((duration.duration || [])[0] || ''), minDuration: String((duration.duration || [])[1] || ''), exclude, + spanKind: props.spanKind, }); return { diff --git a/frontend/src/api/trace/getTagValue.ts b/frontend/src/api/trace/getTagValue.ts index a330262049..2519c7a758 100644 --- a/frontend/src/api/trace/getTagValue.ts +++ b/frontend/src/api/trace/getTagValue.ts @@ -15,6 +15,7 @@ const getTagValue = async ( Key: props.tagKey.Key, Type: props.tagKey.Type, }, + spanKind: props.spanKind, }); return { statusCode: 200, diff --git a/frontend/src/container/MetricsApplication/MetricsPageQueries/ExternalQueries.ts b/frontend/src/container/MetricsApplication/MetricsPageQueries/ExternalQueries.ts index d364315ab9..7980619427 100644 --- a/frontend/src/container/MetricsApplication/MetricsPageQueries/ExternalQueries.ts +++ b/frontend/src/container/MetricsApplication/MetricsPageQueries/ExternalQueries.ts @@ -161,7 +161,7 @@ export const externalCallDurationByAddress = ({ }; interface ExternalCallDurationByAddressProps extends ExternalCallProps { - legend: '{{address}}'; + legend: string; } export interface ExternalCallProps { diff --git a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx index bef9779f54..37b77ad81c 100644 --- a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx @@ -79,11 +79,11 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element { type="default" size="small" id="database_call_rps_button" - onClick={onViewTracePopupClick( + onClick={onViewTracePopupClick({ servicename, selectedTraceTags, - selectedTimeStamp, - )} + timestamp: selectedTimeStamp, + })} > View Traces @@ -114,11 +114,11 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element { type="default" size="small" id="database_call_avg_duration_button" - onClick={onViewTracePopupClick( + onClick={onViewTracePopupClick({ servicename, selectedTraceTags, - selectedTimeStamp, - )} + timestamp: selectedTimeStamp, + })} > View Traces diff --git a/frontend/src/container/MetricsApplication/Tabs/External.tsx b/frontend/src/container/MetricsApplication/Tabs/External.tsx index a0bd62bb29..f6d2d31fbb 100644 --- a/frontend/src/container/MetricsApplication/Tabs/External.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/External.tsx @@ -6,8 +6,11 @@ import { externalCallErrorPercent, externalCallRpsByAddress, } from 'container/MetricsApplication/MetricsPageQueries/ExternalQueries'; -import { resourceAttributesToTagFilterItems } from 'lib/resourceAttributes'; -import React, { useMemo } from 'react'; +import { + convertRawQueriesToTraceSelectedTags, + resourceAttributesToTagFilterItems, +} from 'lib/resourceAttributes'; +import React, { useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; import { AppState } from 'store/reducers'; @@ -15,8 +18,13 @@ import { Widgets } from 'types/api/dashboard/getAll'; import MetricReducer from 'types/reducer/metrics'; import { Card, GraphContainer, GraphTitle, Row } from '../styles'; +import { legend } from './constant'; +import { Button } from './styles'; +import { onGraphClickHandler, onViewTracePopupClick } from './util'; function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { + const [selectedTimeStamp, setSelectedTimeStamp] = useState(0); + const { servicename } = useParams<{ servicename?: string }>(); const { resourceAttributeQueries } = useSelector( (state) => state.metrics, @@ -27,8 +35,6 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { [resourceAttributeQueries], ); - const legend = '{{address}}'; - const externalCallErrorWidget = useMemo( () => getWidgetQueryBuilder({ @@ -36,7 +42,7 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { promQL: [], metricsBuilder: externalCallErrorPercent({ servicename, - legend, + legend: legend.address, tagFilterItems, }), clickHouse: [], @@ -44,6 +50,14 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { [getWidgetQueryBuilder, servicename, tagFilterItems], ); + const selectedTraceTags = useMemo( + () => + JSON.stringify( + convertRawQueriesToTraceSelectedTags(resourceAttributeQueries) || [], + ), + [resourceAttributeQueries], + ); + const externalCallDurationWidget = useMemo( () => getWidgetQueryBuilder({ @@ -65,7 +79,7 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { promQL: [], metricsBuilder: externalCallRpsByAddress({ servicename, - legend, + legend: legend.address, tagFilterItems, }), clickHouse: [], @@ -80,7 +94,7 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { promQL: [], metricsBuilder: externalCallDurationByAddress({ servicename, - legend, + legend: legend.address, tagFilterItems, }), clickHouse: [], @@ -92,6 +106,19 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { <> + External Call Error Percentage @@ -100,12 +127,35 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { fullViewOptions={false} widget={externalCallErrorWidget} yAxisUnit="%" + onClickHandler={(ChartEvent, activeElements, chart, data): void => { + onGraphClickHandler(setSelectedTimeStamp)( + ChartEvent, + activeElements, + chart, + data, + 'external_call_error_percentage', + ); + }} /> + + External Call duration @@ -114,6 +164,15 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { fullViewOptions={false} widget={externalCallDurationWidget} yAxisUnit="ms" + onClickHandler={(ChartEvent, activeElements, chart, data): void => { + onGraphClickHandler(setSelectedTimeStamp)( + ChartEvent, + activeElements, + chart, + data, + 'external_call_duration', + ); + }} /> @@ -122,6 +181,19 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { + External Call RPS(by Address) @@ -130,12 +202,35 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { fullViewOptions={false} widget={externalCallRPSWidget} yAxisUnit="reqps" + onClickHandler={(ChartEvent, activeElements, chart, data): void => { + onGraphClickHandler(setSelectedTimeStamp)( + ChartEvent, + activeElements, + chart, + data, + 'external_call_rps_by_address', + ); + }} /> + + External Call duration(by Address) @@ -144,6 +239,15 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element { fullViewOptions={false} widget={externalCallDurationAddressWidget} yAxisUnit="ms" + onClickHandler={(ChartEvent, activeElements, chart, data): void => { + onGraphClickHandler(setSelectedTimeStamp)( + ChartEvent, + activeElements, + chart, + data, + 'external_call_duration_by_address', + ); + }} /> diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx index 8ecd0c9cba..de15029408 100644 --- a/frontend/src/container/MetricsApplication/Tabs/Overview.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/Overview.tsx @@ -181,11 +181,11 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element { type="default" size="small" id="Service_button" - onClick={onViewTracePopupClick( + onClick={onViewTracePopupClick({ servicename, selectedTraceTags, - selectedTimeStamp, - )} + timestamp: selectedTimeStamp, + })} > View Traces @@ -210,11 +210,11 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element { type="default" size="small" id="Rate_button" - onClick={onViewTracePopupClick( + onClick={onViewTracePopupClick({ servicename, selectedTraceTags, - selectedTimeStamp, - )} + timestamp: selectedTimeStamp, + })} > View Traces diff --git a/frontend/src/container/MetricsApplication/Tabs/constant.ts b/frontend/src/container/MetricsApplication/Tabs/constant.ts new file mode 100644 index 0000000000..4931667e6e --- /dev/null +++ b/frontend/src/container/MetricsApplication/Tabs/constant.ts @@ -0,0 +1,3 @@ +export const legend = { + address: '{{address}}', +}; diff --git a/frontend/src/container/MetricsApplication/Tabs/util.ts b/frontend/src/container/MetricsApplication/Tabs/util.ts index c030492aff..beba6da3f3 100644 --- a/frontend/src/container/MetricsApplication/Tabs/util.ts +++ b/frontend/src/container/MetricsApplication/Tabs/util.ts @@ -14,11 +14,18 @@ export const dbSystemTags: Tags[] = [ }, ]; -export function onViewTracePopupClick( - servicename: string | undefined, - selectedTraceTags: string, - timestamp: number, -): VoidFunction { +interface OnViewTracePopupClickProps { + servicename: string | undefined; + selectedTraceTags: string; + timestamp: number; + isExternalCall?: boolean; +} +export function onViewTracePopupClick({ + selectedTraceTags, + servicename, + timestamp, + isExternalCall, +}: OnViewTracePopupClickProps): VoidFunction { return (): void => { const currentTime = timestamp; const tPlusOne = timestamp + 60 * 1000; @@ -30,7 +37,9 @@ export function onViewTracePopupClick( history.replace( `${ ROUTES.TRACE - }?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"]}&spanAggregateCurrentPage=1`, + }?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"]}&spanAggregateCurrentPage=1${ + isExternalCall ? '&spanKind=3' : '' + }`, ); }; } diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx index a413671d18..ee42069fe3 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx @@ -24,6 +24,7 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element { filter, userSelectedFilter, isFilterExclude, + spanKind, } = useSelector((state) => state.traces); const globalTime = useSelector( @@ -91,6 +92,7 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element { start: String(globalTime.minTime), getFilters: filterToFetchData.filter((e) => e !== name), isFilterExclude: preIsFilterExclude, + spanKind, }); if (response.statusCode === 200) { @@ -125,6 +127,7 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element { order: spansAggregate.order, orderParam: spansAggregate.orderParam, pageSize: spansAggregate.pageSize, + spanKind, }, }); diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx index bec1e5260e..6fa6c9ec53 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx @@ -30,6 +30,7 @@ function Duration(): JSX.Element { selectedTags, userSelectedFilter, isFilterExclude, + spanKind, } = useSelector((state) => state.traces); const dispatch = useDispatch>(); @@ -88,6 +89,7 @@ function Duration(): JSX.Element { other: Object.fromEntries(preSelectedFilter), start: String(globalTime.minTime), isFilterExclude, + spanKind, }); if (response.statusCode === 200) { @@ -113,6 +115,7 @@ function Duration(): JSX.Element { order: spansAggregate.order, pageSize: spansAggregate.pageSize, orderParam: spansAggregate.orderParam, + spanKind, }, }); diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/SearchTraceID/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/SearchTraceID/index.tsx index cbd72ebb95..eef14987e1 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/SearchTraceID/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/SearchTraceID/index.tsx @@ -22,6 +22,7 @@ function TraceID(): JSX.Element { selectedTags, userSelectedFilter, isFilterExclude, + spanKind, } = useSelector((state) => state.traces); const dispatch = useDispatch>(); const globalTime = useSelector( @@ -52,6 +53,7 @@ function TraceID(): JSX.Element { start: String(globalTime.minTime), getFilters: filterToFetchData, isFilterExclude, + spanKind, }); if (response.statusCode === 200) { @@ -77,6 +79,7 @@ function TraceID(): JSX.Element { order: spansAggregate.order, pageSize: spansAggregate.pageSize, orderParam: spansAggregate.orderParam, + spanKind, }, }); diff --git a/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx index 310596451c..cf272257f9 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx @@ -37,6 +37,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { filter, isFilterExclude, userSelectedFilter, + spanKind, } = useSelector((state) => state.traces); const { name: PanelName, isOpen: IsPanelOpen } = props; @@ -75,6 +76,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { getFilters: updatedFilterData, other: Object.fromEntries(getprepdatedSelectedFilter), isFilterExclude, + spanKind, }); if (response.statusCode === 200) { @@ -107,6 +109,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { order: spansAggregate.order, pageSize: spansAggregate.pageSize, orderParam: spansAggregate.orderParam, + spanKind, }, }); @@ -160,6 +163,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { order: spansAggregate.order, pageSize: spansAggregate.pageSize, orderParam: spansAggregate.orderParam, + spanKind, }, }); @@ -195,6 +199,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { getFilters: filterToFetchData, other: Object.fromEntries(updatedFilter), isFilterExclude: postIsFilterExclude, + spanKind, }); if (response.statusCode === 200 && response.payload) { @@ -213,6 +218,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { order: spansAggregate.order, pageSize: spansAggregate.pageSize, orderParam: spansAggregate.orderParam, + spanKind, }, }); diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx index 5d241efec0..f14a35e0bd 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx @@ -27,6 +27,7 @@ function TagsKey(props: TagsKeysProps): JSX.Element { globalTime.maxTime, traces.selectedFilter, traces.isFilterExclude, + traces.spanKind, ], { queryFn: () => @@ -35,6 +36,7 @@ function TagsKey(props: TagsKeysProps): JSX.Element { end: globalTime.maxTime, other: Object.fromEntries(traces.selectedFilter), isFilterExclude: traces.isFilterExclude, + spanKind: traces.spanKind, }), cacheTime: 120000, }, diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx index af5b51cfe2..22abbe9df7 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx @@ -30,6 +30,8 @@ function TagValue(props: TagValueProps): JSX.Element { BoolValues: selectedBoolValues, } = tag; + const traces = useSelector((state) => state.traces); + const [localTagValue, setLocalTagValue] = useState( getInitialLocalValue( selectedNumberValues, @@ -45,7 +47,14 @@ function TagValue(props: TagValueProps): JSX.Element { const tagType = useMemo(() => extractTagType(tagKey), [tagKey]); const { isLoading, data } = useQuery( - ['tagKey', globalReducer.minTime, globalReducer.maxTime, tagKey, tagType], + [ + 'tagKey', + globalReducer.minTime, + globalReducer.maxTime, + tagKey, + tagType, + traces.spanKind, + ], { queryFn: () => getTagValue({ @@ -55,6 +64,7 @@ function TagValue(props: TagValueProps): JSX.Element { Key: extractTagKey(tagKey), Type: tagType, }, + spanKind: traces.spanKind, }), }, ); diff --git a/frontend/src/container/Trace/Search/index.tsx b/frontend/src/container/Trace/Search/index.tsx index adcb59f6eb..d9b4741082 100644 --- a/frontend/src/container/Trace/Search/index.tsx +++ b/frontend/src/container/Trace/Search/index.tsx @@ -67,6 +67,7 @@ function Search({ order: traces.spansAggregate.order, pageSize: traces.spansAggregate.pageSize, orderParam: traces.spansAggregate.orderParam, + spanKind: traces.spanKind, }, }); diff --git a/frontend/src/container/Trace/TraceGraphFilter/index.tsx b/frontend/src/container/Trace/TraceGraphFilter/index.tsx index 52811fef6f..48f6666101 100644 --- a/frontend/src/container/Trace/TraceGraphFilter/index.tsx +++ b/frontend/src/container/Trace/TraceGraphFilter/index.tsx @@ -40,6 +40,7 @@ function TraceGraphFilter(): JSX.Element { globalTime.maxTime, traces.selectedFilter, traces.isFilterExclude, + traces.spanKind, ], { queryFn: () => @@ -48,8 +49,10 @@ function TraceGraphFilter(): JSX.Element { end: globalTime.maxTime, other: Object.fromEntries(traces.selectedFilter), isFilterExclude: traces.isFilterExclude, + spanKind: traces.spanKind, }), cacheTime: 120000, + enabled: traces.filter.size > 0, }, ); diff --git a/frontend/src/pages/Trace/index.tsx b/frontend/src/pages/Trace/index.tsx index 2de31ecd53..fba0cb2afc 100644 --- a/frontend/src/pages/Trace/index.tsx +++ b/frontend/src/pages/Trace/index.tsx @@ -52,6 +52,7 @@ function Trace({ selectedFunction, selectedGroupBy, isFilterExclude, + spanKind, } = useSelector((state) => state.traces); const { notifications } = useNotifications(); @@ -71,6 +72,7 @@ function Trace({ selectedTags, order: spansAggregate.order, orderParam: spansAggregate.orderParam, + spanKind, }, notifications, ); @@ -85,6 +87,7 @@ function Trace({ spansAggregate.order, spansAggregate.orderParam, notifications, + spanKind, ]); useEffect(() => { @@ -98,6 +101,7 @@ function Trace({ start: minTime, step: getStep({ start: minTime, end: maxTime, inputFormat: 'ns' }), isFilterExclude, + spanKind, }, notifications, ); @@ -111,6 +115,7 @@ function Trace({ getSpans, isFilterExclude, notifications, + spanKind, ]); useEffect( diff --git a/frontend/src/store/actions/trace/getInitialFilter.ts b/frontend/src/store/actions/trace/getInitialFilter.ts index 7737b3887e..5ff04b1eff 100644 --- a/frontend/src/store/actions/trace/getInitialFilter.ts +++ b/frontend/src/store/actions/trace/getInitialFilter.ts @@ -12,6 +12,7 @@ import { import { GlobalReducer } from 'types/reducer/globalTime'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; +import { parseQueryIntoSpanKind } from './parseFilter/parseSpanKind'; import { isTraceFilterEnum, parseAggregateOrderParams, @@ -55,6 +56,8 @@ export const GetInitialTraceFilter = ( traces.filterToFetchData, ); + const parsedSpanKind = parseQueryIntoSpanKind(query, traces.spanKind); + const getUserSelected = parseSelectedFilter(query, traces.userSelectedFilter); const getIsFilterExcluded = parseFilterExclude(query, traces.isFilterExclude); @@ -102,6 +105,7 @@ export const GetInitialTraceFilter = ( start: String(minTime), other: Object.fromEntries(getSelectedFilter.currentValue), isFilterExclude: getIsFilterExcluded.currentValue, + spanKind: parsedSpanKind.currentValue, }); const preSelectedFilter: Map = new Map( @@ -164,6 +168,7 @@ export const GetInitialTraceFilter = ( order: parsedQueryOrder.currentValue, pageSize: parsedPageSize.currentValue, orderParam: parsedOrderParams.currentValue, + spanKind: parsedSpanKind.currentValue, }, }); } else { diff --git a/frontend/src/store/actions/trace/getInitialSpansAggregate.ts b/frontend/src/store/actions/trace/getInitialSpansAggregate.ts index c8a07b99de..acd7e18d5e 100644 --- a/frontend/src/store/actions/trace/getInitialSpansAggregate.ts +++ b/frontend/src/store/actions/trace/getInitialSpansAggregate.ts @@ -61,6 +61,7 @@ export const GetSpansAggregate = ( isFilterExclude: traces.isFilterExclude, order, orderParam: props.orderParam, + spanKind: props.spanKind, }); if (response.statusCode === 200) { @@ -140,4 +141,5 @@ export interface GetSpansAggregateProps { selectedTags: TraceReducer['selectedTags']; order: GetSpanAggregateProps['order']; orderParam: GetSpanAggregateProps['orderParam']; + spanKind: TraceReducer['spanKind']; } diff --git a/frontend/src/store/actions/trace/getSpans.ts b/frontend/src/store/actions/trace/getSpans.ts index a2336bd91d..4b2787e7a9 100644 --- a/frontend/src/store/actions/trace/getSpans.ts +++ b/frontend/src/store/actions/trace/getSpans.ts @@ -63,6 +63,7 @@ export const GetSpans = ( start, step: props.step, isFilterExclude: props.isFilterExclude, + spanKind: props.spanKind, }); if (response.statusCode === 200) { diff --git a/frontend/src/store/actions/trace/parseFilter/parseSpanKind.ts b/frontend/src/store/actions/trace/parseFilter/parseSpanKind.ts new file mode 100644 index 0000000000..c4626b44f7 --- /dev/null +++ b/frontend/src/store/actions/trace/parseFilter/parseSpanKind.ts @@ -0,0 +1,39 @@ +import { TraceReducer } from 'types/reducer/trace'; + +import { ParsedUrl } from '../util'; + +export const parseQueryIntoSpanKind = ( + query: string, + stateCurrent: TraceReducer['spanKind'], +): ParsedUrl => { + const url = new URLSearchParams(query); + + let current = ''; + + const selected = url.get('spanKind'); + + if (selected) { + try { + const parsedValue = selected; + + if (parsedValue && typeof parsedValue === 'string') { + current = parsedValue; + } + } catch (error) { + console.log(error); + console.log('error while parsing json'); + } + } + + if (selected) { + return { + currentValue: current, + urlValue: current, + }; + } + + return { + currentValue: stateCurrent, + urlValue: current, + }; +}; diff --git a/frontend/src/store/reducers/trace.ts b/frontend/src/store/reducers/trace.ts index ea6b9a7671..5545f25eb8 100644 --- a/frontend/src/store/reducers/trace.ts +++ b/frontend/src/store/reducers/trace.ts @@ -70,6 +70,7 @@ const initialValue: TraceReducer = { ['status', INITIAL_FILTER_VALUE], ['traceID', INITIAL_FILTER_VALUE], ]), + spanKind: undefined, }; const traceReducer = ( @@ -97,6 +98,7 @@ const traceReducer = ( order, pageSize, orderParam, + spanKind, } = payload; return { @@ -114,6 +116,7 @@ const traceReducer = ( order, orderParam, }, + spanKind, }; } diff --git a/frontend/src/types/actions/trace.ts b/frontend/src/types/actions/trace.ts index f043926142..f4336427f4 100644 --- a/frontend/src/types/actions/trace.ts +++ b/frontend/src/types/actions/trace.ts @@ -82,6 +82,7 @@ export interface UpdateAllFilters { order: TraceReducer['spansAggregate']['order']; pageSize: TraceReducer['spansAggregate']['pageSize']; orderParam: TraceReducer['spansAggregate']['orderParam']; + spanKind?: TraceReducer['spanKind']; }; } diff --git a/frontend/src/types/api/trace/getFilters.ts b/frontend/src/types/api/trace/getFilters.ts index 422e360831..3edb9166c0 100644 --- a/frontend/src/types/api/trace/getFilters.ts +++ b/frontend/src/types/api/trace/getFilters.ts @@ -8,6 +8,7 @@ export interface Props { [k: string]: string[]; }; isFilterExclude: TraceReducer['isFilterExclude']; + spanKind?: TraceReducer['spanKind']; } export interface PayloadProps { diff --git a/frontend/src/types/api/trace/getSpanAggregate.ts b/frontend/src/types/api/trace/getSpanAggregate.ts index f5bcbdc6c5..97d813aeeb 100644 --- a/frontend/src/types/api/trace/getSpanAggregate.ts +++ b/frontend/src/types/api/trace/getSpanAggregate.ts @@ -10,6 +10,7 @@ export interface Props { order?: TraceReducer['spansAggregate']['order']; isFilterExclude: TraceReducer['isFilterExclude']; orderParam: TraceReducer['spansAggregate']['orderParam']; + spanKind?: TraceReducer['spanKind']; } export type PayloadProps = { diff --git a/frontend/src/types/api/trace/getSpans.ts b/frontend/src/types/api/trace/getSpans.ts index 9143f2a693..7928908da9 100644 --- a/frontend/src/types/api/trace/getSpans.ts +++ b/frontend/src/types/api/trace/getSpans.ts @@ -9,6 +9,7 @@ export interface Props { selectedFilter: TraceReducer['selectedFilter']; selectedTags: TraceReducer['selectedTags']; isFilterExclude: TraceReducer['isFilterExclude']; + spanKind?: TraceReducer['spanKind']; } export interface PayloadProps { diff --git a/frontend/src/types/api/trace/getTagFilters.ts b/frontend/src/types/api/trace/getTagFilters.ts index eeee055e75..d1029f308f 100644 --- a/frontend/src/types/api/trace/getTagFilters.ts +++ b/frontend/src/types/api/trace/getTagFilters.ts @@ -7,6 +7,7 @@ export interface Props { [k: string]: string[]; }; isFilterExclude: TraceReducer['isFilterExclude']; + spanKind?: TraceReducer['spanKind']; } export interface PayloadProps { diff --git a/frontend/src/types/api/trace/getTagValue.ts b/frontend/src/types/api/trace/getTagValue.ts index ee10041e56..5a6af76fac 100644 --- a/frontend/src/types/api/trace/getTagValue.ts +++ b/frontend/src/types/api/trace/getTagValue.ts @@ -1,4 +1,5 @@ import { GlobalReducer } from 'types/reducer/globalTime'; +import { TraceReducer } from 'types/reducer/trace'; export interface Props { start: GlobalReducer['minTime']; @@ -7,6 +8,7 @@ export interface Props { Key: string; Type: string; }; + spanKind?: TraceReducer['spanKind']; } export interface PayloadProps { diff --git a/frontend/src/types/reducer/trace.ts b/frontend/src/types/reducer/trace.ts index 701f27efa6..cc35cbc44a 100644 --- a/frontend/src/types/reducer/trace.ts +++ b/frontend/src/types/reducer/trace.ts @@ -33,6 +33,7 @@ export interface TraceReducer { }; yAxisUnit: string | undefined; filterDisplayValue: Map; + spanKind?: string; } interface SpansAggregateData { diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index a1b2ceabab..4f3e7043a4 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -1001,6 +1001,11 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode args = append(args, clickhouse.Named("durationNanoMax", queryParams.MaxDuration)) } + if len(queryParams.SpanKind) != 0 { + query = query + " AND kind = @kind" + args = append(args, clickhouse.Named("kind", queryParams.SpanKind)) + } + query = getStatusFilters(query, queryParams.Status, excludeMap) traceFilterReponse := model.SpanFiltersResponse{ @@ -1364,9 +1369,9 @@ func (r *ClickHouseReader) GetFilteredSpans(ctx context.Context, queryParams *mo } query = getStatusFilters(query, queryParams.Status, excludeMap) - if len(queryParams.Kind) != 0 { + if len(queryParams.SpanKind) != 0 { query = query + " AND kind = @kind" - args = append(args, clickhouse.Named("kind", queryParams.Kind)) + args = append(args, clickhouse.Named("kind", queryParams.SpanKind)) } // create TagQuery from TagQueryParams @@ -1666,6 +1671,10 @@ func (r *ClickHouseReader) GetTagFilters(ctx context.Context, queryParams *model query = query + " AND durationNano <= @durationNanoMax" args = append(args, clickhouse.Named("durationNanoMax", queryParams.MaxDuration)) } + if len(queryParams.SpanKind) != 0 { + query = query + " AND kind = @kind" + args = append(args, clickhouse.Named("kind", queryParams.SpanKind)) + } query = getStatusFilters(query, queryParams.Status, excludeMap) @@ -1781,6 +1790,10 @@ func (r *ClickHouseReader) GetTagValues(ctx context.Context, queryParams *model. query = query + " AND durationNano <= @durationNanoMax" args = append(args, clickhouse.Named("durationNanoMax", queryParams.MaxDuration)) } + if len(queryParams.SpanKind) != 0 { + query = query + " AND kind = @kind" + args = append(args, clickhouse.Named("kind", queryParams.SpanKind)) + } query = getStatusFilters(query, queryParams.Status, excludeMap) @@ -2113,9 +2126,9 @@ func (r *ClickHouseReader) GetFilteredSpansAggregates(ctx context.Context, query } query = getStatusFilters(query, queryParams.Status, excludeMap) - if len(queryParams.Kind) != 0 { + if len(queryParams.SpanKind) != 0 { query = query + " AND kind = @kind" - args = append(args, clickhouse.Named("kind", queryParams.Kind)) + args = append(args, clickhouse.Named("kind", queryParams.SpanKind)) } // create TagQuery from TagQueryParams tags := createTagQueryFromTagQueryParams(queryParams.Tags) diff --git a/pkg/query-service/model/queryParams.go b/pkg/query-service/model/queryParams.go index 1f7e2daed8..4730b1fabf 100644 --- a/pkg/query-service/model/queryParams.go +++ b/pkg/query-service/model/queryParams.go @@ -312,7 +312,7 @@ type GetFilteredSpansParams struct { TraceID []string `json:"traceID"` ServiceName []string `json:"serviceName"` Operation []string `json:"operation"` - Kind string `json:"kind"` + SpanKind string `json:"spanKind"` Status []string `json:"status"` HttpRoute []string `json:"httpRoute"` HttpCode []string `json:"httpCode"` @@ -340,7 +340,7 @@ type GetFilteredSpanAggregatesParams struct { TraceID []string `json:"traceID"` ServiceName []string `json:"serviceName"` Operation []string `json:"operation"` - Kind string `json:"kind"` + SpanKind string `json:"spanKind"` Status []string `json:"status"` HttpRoute []string `json:"httpRoute"` HttpCode []string `json:"httpCode"` @@ -369,6 +369,7 @@ type SpanFilterParams struct { TraceID []string `json:"traceID"` Status []string `json:"status"` ServiceName []string `json:"serviceName"` + SpanKind string `json:"spanKind"` HttpRoute []string `json:"httpRoute"` HttpCode []string `json:"httpCode"` HttpUrl []string `json:"httpUrl"` @@ -394,6 +395,7 @@ type TagFilterParams struct { ServiceName []string `json:"serviceName"` HttpRoute []string `json:"httpRoute"` HttpCode []string `json:"httpCode"` + SpanKind string `json:"spanKind"` HttpUrl []string `json:"httpUrl"` HttpHost []string `json:"httpHost"` HttpMethod []string `json:"httpMethod"`