From 4e07cf91ae9b6461384899346f7e40f04ebc8897 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Sep 2024 20:48:40 +0000 Subject: [PATCH] Update custom traces table with filters (#2178) * update custom traces table with filters Signed-off-by: Shenoy Pratik * use css truncate, resolve comments Signed-off-by: Shenoy Pratik * add guards for execution_hint Signed-off-by: Shenoy Pratik * update descriptions Signed-off-by: Shenoy Pratik --------- Signed-off-by: Shenoy Pratik (cherry picked from commit 00fd9ac25ccdcae6df2a3897d4cc82f595187f00) Signed-off-by: github-actions[bot] --- common/constants/trace_analytics.ts | 25 ++ common/types/trace_analytics.ts | 3 + .../components/application.tsx | 3 + .../added_integration.test.tsx.snap | 4 +- .../components/traces/trace_table_helpers.tsx | 248 ++++++++++++++ .../components/traces/traces.tsx | 3 + .../components/traces/traces_content.tsx | 49 ++- .../traces/traces_custom_indices_table.tsx | 319 ++++++------------ public/components/trace_analytics/home.tsx | 23 +- public/components/trace_analytics/index.scss | 16 + .../requests/queries/traces_queries.ts | 39 ++- .../requests/traces_request_handler.ts | 13 +- 12 files changed, 495 insertions(+), 250 deletions(-) create mode 100644 public/components/trace_analytics/components/traces/trace_table_helpers.tsx diff --git a/common/constants/trace_analytics.ts b/common/constants/trace_analytics.ts index bbf9a2c7d7..daf04a6fa2 100644 --- a/common/constants/trace_analytics.ts +++ b/common/constants/trace_analytics.ts @@ -24,3 +24,28 @@ export const TRACE_ANALYTICS_DSL_ROUTE = '/api/observability/trace_analytics/que export const TRACE_CUSTOM_SPAN_INDEX_SETTING = 'observability:traceAnalyticsSpanIndices'; export const TRACE_CUSTOM_SERVICE_INDEX_SETTING = 'observability:traceAnalyticsServiceIndices'; + +export enum TRACE_TABLE_TITLES { + all_spans = 'All Spans', + root_spans = 'Root Spans', + entry_spans = 'Service Entry Spans', + traces = 'Traces', +} + +const getDescription = (key: keyof typeof TRACE_TABLE_TITLES): string => { + const descriptions: Record = { + all_spans: 'Spans representing all activities in all traces across the system', + root_spans: 'Spans marking the root or starting point of each trace', + entry_spans: 'Spans that indicate the entry point of service-side processing', + traces: 'Spans grouped by traceId to show a complete trace lifecycle', + }; + return descriptions[key]; +}; + +export const TRACE_TABLE_OPTIONS = Object.entries(TRACE_TABLE_TITLES).map(([key, label]) => ({ + label, + key, + 'aria-describedby': getDescription(key as keyof typeof TRACE_TABLE_TITLES), +})); + +export const TRACE_TABLE_TYPE_KEY = 'TraceAnalyticsTraceTableType'; diff --git a/common/types/trace_analytics.ts b/common/types/trace_analytics.ts index 91fbcac41d..028794be71 100644 --- a/common/types/trace_analytics.ts +++ b/common/types/trace_analytics.ts @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { TRACE_TABLE_TITLES } from '../constants/trace_analytics'; + export type SpanField = | 'SPAN_ID' | 'PARENT_SPAN_ID' @@ -54,3 +56,4 @@ export interface GraphVisEdge { } export type TraceAnalyticsMode = 'jaeger' | 'data_prepper' | 'custom_data_prepper'; +export type TraceQueryMode = keyof typeof TRACE_TABLE_TITLES; diff --git a/public/components/application_analytics/components/application.tsx b/public/components/application_analytics/components/application.tsx index ca40bf50c3..140c156930 100644 --- a/public/components/application_analytics/components/application.tsx +++ b/public/components/application_analytics/components/application.tsx @@ -326,6 +326,9 @@ export function Application(props: AppDetailProps) { setStartTime={setStartTimeForApp} setEndTime={setEndTimeForApp} dataSourceMDSId={[{ id: '', label: '' }]} + setCurrentSelectedService={() => {}} + tracesTableMode="traces" + setTracesTableMode={() => {}} /> diff --git a/public/components/integrations/components/__tests__/__snapshots__/added_integration.test.tsx.snap b/public/components/integrations/components/__tests__/__snapshots__/added_integration.test.tsx.snap index ee51138f0e..bbbaeb6cf3 100644 --- a/public/components/integrations/components/__tests__/__snapshots__/added_integration.test.tsx.snap +++ b/public/components/integrations/components/__tests__/__snapshots__/added_integration.test.tsx.snap @@ -907,10 +907,10 @@ exports[`Added Integration View Test Renders added integration view using dummy
{ + return columnItems + .filter((col) => col.includes('attributes') || col.includes('instrumentation')) + .map((col) => ({ + className: 'attributes-column', + field: col, + name: ( + + +

{col}

+
+
+ ), + align: 'right', + sortable: true, + truncateText: true, + render: (item) => + item ? ( + + + + {item} + + + + ) : ( + '-' + ), + })); +}; + +export const getTableColumns = ( + showAttributes: boolean, + columnItems: string[], + mode: TraceAnalyticsMode, + tracesTableMode: TraceQueryMode, + getTraceViewUri?: (traceId: string) => string, + openTraceFlyout?: (traceId: string) => void +): Array> => { + // Helper functions for rendering table fields + const renderIdField = (item: string) => + item ? ( + + + + {item} + + + + ) : ( + '-' + ); + + const renderTraceLinkField = (item: string) => ( + + + openTraceFlyout(item) })} + > + + {item} + + + + + + {(copy) => ( + + )} + + + + ); + + const renderErrorsField = (item: number) => + item == null ? ( + '-' + ) : +item > 0 ? ( + + Yes + + ) : ( + 'No' + ); + + const renderDurationField = (item: number) => + item ? {round(nanoToMilliSec(Math.max(0, item)), 2)} : '-'; + + const renderDateField = (item: number) => + item === 0 || item ? moment(item).format(TRACE_ANALYTICS_DATE_FORMAT) : '-'; + + // Columns for custom_data_prepper mode + if (mode === 'custom_data_prepper' && tracesTableMode !== 'traces') { + return [ + { + field: 'spanId', + name: 'Span Id', + align: 'left', + sortable: true, + render: renderIdField, + className: 'span-group-column', + }, + { + field: 'traceId', + name: 'Trace Id', + align: 'left', + sortable: true, + render: renderTraceLinkField, + }, + { + field: 'parentSpanId', + name: 'Parent Span Id', + align: 'left', + sortable: true, + render: renderIdField, + className: 'span-group-column', + }, + { + field: 'traceGroup', + name: 'Trace group', + align: 'left', + sortable: true, + truncateText: true, + }, + { + field: 'durationInNanos', + name: 'Duration (ms)', + align: 'right', + sortable: true, + render: renderDurationField, + }, + { + field: 'status.code', + name: 'Errors', + align: 'right', + sortable: true, + render: renderErrorsField, + }, + { + field: 'endTime', + name: 'Last updated', + align: 'right', + sortable: true, + render: renderDateField, + className: 'span-group-column', + }, + ...(showAttributes ? fetchDynamicColumns(columnItems) : []), + ] as Array>; + } + + // Columns for non-jaeger traces mode + if (mode !== 'jaeger' && tracesTableMode === 'traces') { + return [ + { + field: 'trace_id', + name: 'Trace ID', + align: 'left', + sortable: true, + render: renderTraceLinkField, + }, + { + field: 'trace_group', + name: 'Trace group', + align: 'left', + sortable: true, + truncateText: true, + }, + { + field: 'latency', + name: 'Duration (ms)', + align: 'right', + sortable: true, + truncateText: true, + }, + { + field: 'percentile_in_trace_group', + name: 'Percentile in trace group', + align: 'right', + sortable: true, + render: (item) => (item ? `${round(item, 2)}th` : '-'), + }, + { + field: 'error_count', + name: 'Errors', + align: 'right', + sortable: true, + render: renderErrorsField, + }, + { + field: 'last_updated', + name: 'Last updated', + align: 'left', + sortable: true, + className: 'span-group-column', + }, + ] as Array>; + } + + // Default columns for other modes + return [ + { + field: 'trace_id', + name: 'Trace ID', + align: 'left', + sortable: true, + render: renderTraceLinkField, + }, + { field: 'latency', name: 'Latency (ms)', align: 'right', sortable: true }, + { + field: 'error_count', + name: 'Errors', + align: 'right', + sortable: true, + render: renderErrorsField, + }, + { + field: 'last_updated', + name: 'Last updated', + align: 'left', + sortable: true, + className: 'span-group-column', + }, + ] as Array>; +}; diff --git a/public/components/trace_analytics/components/traces/traces.tsx b/public/components/trace_analytics/components/traces/traces.tsx index eacfb050f0..baa725f8b9 100644 --- a/public/components/trace_analytics/components/traces/traces.tsx +++ b/public/components/trace_analytics/components/traces/traces.tsx @@ -7,6 +7,7 @@ import { EuiBreadcrumb } from '@elastic/eui'; import { Toast } from '@elastic/eui/src/components/toast/global_toast_list'; import React from 'react'; import { DataSourceOption } from '../../../../../../../src/plugins/data_source_management/public/components/data_source_menu/types'; +import { TraceQueryMode } from '../../../../../common/types/trace_analytics'; import { TraceAnalyticsComponentDeps } from '../../home'; import { TracesContent } from './traces_content'; @@ -18,6 +19,8 @@ export interface TracesProps extends TraceAnalyticsComponentDeps { openTraceFlyout?: (traceId: string) => void; toasts: Toast[]; dataSourceMDSId: DataSourceOption[]; + tracesTableMode: TraceQueryMode; + setTracesTableMode: React.Dispatch>; } export function Traces(props: TracesProps) { diff --git a/public/components/trace_analytics/components/traces/traces_content.tsx b/public/components/trace_analytics/components/traces/traces_content.tsx index 4ed479870e..828c700580 100644 --- a/public/components/trace_analytics/components/traces/traces_content.tsx +++ b/public/components/trace_analytics/components/traces/traces_content.tsx @@ -4,6 +4,7 @@ */ /* eslint-disable react-hooks/exhaustive-deps */ +import datemath from '@elastic/datemath'; import { EuiAccordion, EuiFlexGroup, @@ -56,6 +57,8 @@ export function TracesContent(props: TracesProps) { jaegerIndicesExist, attributesFilterFields, setCurrentSelectedService, + tracesTableMode, + setTracesTableMode, } = props; const [tableItems, setTableItems] = useState([]); const [columns, setColumns] = useState([]); @@ -109,6 +112,7 @@ export function TracesContent(props: TracesProps) { jaegerIndicesExist, dataPrepperIndicesExist, includeMetrics, + tracesTableMode, ]); const onToggle = (isOpen: boolean) => { @@ -151,6 +155,7 @@ export function TracesContent(props: TracesProps) { processTimeStamp(endTime, mode), page ); + const isUnderOneHour = datemath.parse(endTime)?.diff(datemath.parse(startTime), 'hours')! < 1; if (mode === 'custom_data_prepper') { // service map should not be filtered by service name @@ -159,16 +164,32 @@ export function TracesContent(props: TracesProps) { (must: any) => must?.term?.serviceName == null ); - await handleCustomIndicesTracesRequest( - http, - DSL, - tableItems, - setTableItems, - setColumns, - mode, - props.dataSourceMDSId[0].id, - sort - ); + if (tracesTableMode !== 'traces') + await handleCustomIndicesTracesRequest( + http, + DSL, + tableItems, + setTableItems, + setColumns, + mode, + props.dataSourceMDSId[0].id, + sort, + tracesTableMode, + isUnderOneHour + ); + else { + await handleTracesRequest( + http, + DSL, + timeFilterDSL, + tableItems, + setTableItems, + mode, + props.dataSourceMDSId[0].id, + sort, + isUnderOneHour + ); + } await handleServiceMapRequest( http, serviceMapDSL, @@ -187,7 +208,8 @@ export function TracesContent(props: TracesProps) { setTableItems, mode, props.dataSourceMDSId[0].id, - sort + sort, + isUnderOneHour ); } @@ -237,6 +259,8 @@ export function TracesContent(props: TracesProps) { attributesFilterFields={attributesFilterFields} /> + + {/* Switch between custom data prepper and regular table */} {mode === 'custom_data_prepper' ? ( ) : ( )} + {/* Show services list and graph when mode is custom data prepper */} {mode === 'custom_data_prepper' && ( <> diff --git a/public/components/trace_analytics/components/traces/traces_custom_indices_table.tsx b/public/components/trace_analytics/components/traces/traces_custom_indices_table.tsx index 5674b6f903..ae03b24c8b 100644 --- a/public/components/trace_analytics/components/traces/traces_custom_indices_table.tsx +++ b/public/components/trace_analytics/components/traces/traces_custom_indices_table.tsx @@ -2,40 +2,38 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ -/* eslint-disable react-hooks/exhaustive-deps */ import { - EuiButtonEmpty, - EuiButtonIcon, - EuiCopy, + CriteriaWithPagination, EuiFlexGroup, EuiFlexItem, + EuiHighlight, EuiHorizontalRule, EuiInMemoryTable, - EuiLink, EuiPanel, + EuiPopover, + EuiPopoverTitle, + EuiSelectable, + EuiSelectableOption, + EuiSmallButtonEmpty, EuiSpacer, - EuiTableFieldDataColumnType, - EuiText, - EuiToolTip, + EuiTextColor, PropertySort, } from '@elastic/eui'; -import { CriteriaWithPagination } from '@opensearch-project/oui/src/eui_components/basic_table'; -import round from 'lodash/round'; -import truncate from 'lodash/truncate'; -import moment from 'moment'; -import React, { useMemo, useState } from 'react'; +import React, { Fragment, useMemo, useState } from 'react'; import { - TRACE_ANALYTICS_DATE_FORMAT, + TRACE_TABLE_OPTIONS, + TRACE_TABLE_TITLES, + TRACE_TABLE_TYPE_KEY, TRACES_MAX_NUM, } from '../../../../../common/constants/trace_analytics'; -import { TraceAnalyticsMode } from '../../../../../common/types/trace_analytics'; +import { TraceAnalyticsMode, TraceQueryMode } from '../../../../../common/types/trace_analytics'; import { MissingConfigurationMessage, - nanoToMilliSec, NoMatchMessage, PanelTitle, } from '../common/helper_functions'; +import { getTableColumns } from './trace_table_helpers'; interface TracesLandingTableProps { columnItems: string[]; @@ -47,218 +45,117 @@ interface TracesLandingTableProps { openTraceFlyout?: (traceId: string) => void; jaegerIndicesExist: boolean; dataPrepperIndicesExist: boolean; + tracesTableMode: TraceQueryMode; + setTracesTableMode: React.Dispatch>; } export function TracesCustomIndicesTable(props: TracesLandingTableProps) { const { columnItems, items, refresh, mode, loading, getTraceViewUri, openTraceFlyout } = props; const [showAttributes, setShowAttributes] = useState(false); + const [isTitlePopoverOpen, setIsTitlePopoverOpen] = useState(false); + const [tableOptions, setTableOptions] = useState(() => + TRACE_TABLE_OPTIONS.map((obj) => + obj.key === props.tracesTableMode ? { ...obj, checked: 'on' } : obj + ) + ); + + const titlePopoverButton = (totalItems?: number) => ( + setIsTitlePopoverOpen(!isTitlePopoverOpen)} + iconType="arrowDown" + iconSide="right" + > + + + ); + + const renderTableOptions = (option: EuiSelectableOption, searchValue: string) => { + return ( + <> + {TRACE_TABLE_TITLES[option.key]} +
+ + {option['aria-describedby']} + + + ); + }; const renderTitleBar = (totalItems?: number) => { return ( - - - - setShowAttributes(!showAttributes)}> - {showAttributes ? 'Hide Attributes' : 'Show Attributes'} - + setIsTitlePopoverOpen(false)} + > + + Select trace table filter + + { + setTableOptions(newOptions); + const tableMode = newOptions.filter((option) => option.checked === 'on')[0] + .key as TraceQueryMode; + props.setTracesTableMode(tableMode); + sessionStorage.setItem(TRACE_TABLE_TYPE_KEY, tableMode); + setIsTitlePopoverOpen(false); + }} + > + {(list, search) => ( + + {search} + {list} + + )} + + + {props.tracesTableMode !== 'traces' && ( + + setShowAttributes(!showAttributes)}> + {showAttributes ? 'Hide Attributes' : 'Show Attributes'} + + + )} ); }; - const dynamicColumns = columnItems - .filter((col) => col.includes('attributes') || col.includes('instrumentation')) - .map((col) => ({ - className: 'attributes-column', - field: col, - name: ( - - -

{col}

-
-
- ), - align: 'right', - sortable: true, - truncateText: true, - render: (item) => - item ? ( - - - - {item.length < 36 ? item :
{truncate(item, { length: 36 })}
} -
-
-
- ) : ( - '-' - ), - })); - const columns = useMemo(() => { - if (mode === 'custom_data_prepper' || mode === 'data_prepper') { - return [ - { - field: 'traceId', - name: 'Trace ID', - align: 'left', - sortable: true, - truncateText: false, - render: (item) => ( - - - openTraceFlyout(item) })} - > - - {item} - - - - - - {(copy) => ( - - Click to copy - - )} - - - - ), - }, - { - field: 'traceGroup', - name: 'Trace group', - align: 'left', - sortable: true, - truncateText: true, - className: 'trace-group-column', - render: (item) => - item ? ( - - {item.length < 36 ? item :
{truncate(item, { length: 36 })}
} -
- ) : ( - '-' - ), - }, - { - field: 'durationInNanos', - name: 'Duration (ms)', - align: 'right', - sortable: true, - truncateText: true, - render: (item) => - item ? {round(nanoToMilliSec(Math.max(0, item)), 2)} : '-', - }, - { - field: 'status.code', - name: 'Errors', - align: 'right', - sortable: true, - render: (item) => - item == null ? ( - '-' - ) : +item === 2 ? ( - - Yes - - ) : ( - 'No' - ), - }, - { - field: 'endTime', - name: 'Last updated', - align: 'right', - sortable: true, - className: 'trace-group-column', - render: (item) => - item === 0 || item ? moment(item).format(TRACE_ANALYTICS_DATE_FORMAT) : '-', - }, - ...(showAttributes ? dynamicColumns : []), - ] as Array>; - } else { - return [ - { - field: 'trace_id', - name: 'Trace ID', - align: 'left', - sortable: true, - truncateText: true, - render: (item) => ( - - - openTraceFlyout(item) })} - > - - {item} - - - - - - {(copy) => ( - - Click to copy - - )} - - - - ), - }, - { - field: 'latency', - name: 'Latency (ms)', - align: 'right', - sortable: true, - truncateText: true, - }, - { - field: 'error_count', - name: 'Errors', - align: 'right', - sortable: true, - render: (item) => - item == null ? ( - '-' - ) : item > 0 ? ( - - Yes - - ) : ( - 'No' - ), - }, - { - field: 'last_updated', - name: 'Last updated', - align: 'left', - sortable: true, - render: (item) => (item === 0 || item ? item : '-'), - }, - ] as Array>; - } - }, [showAttributes, items]); + return getTableColumns( + showAttributes, + columnItems, + mode, + props.tracesTableMode, + getTraceViewUri, + openTraceFlyout + ); + }, [ + showAttributes, + columnItems, + mode, + props.tracesTableMode, + getTraceViewUri, + openTraceFlyout, + items, + ]); - const titleBar = useMemo(() => renderTitleBar(items?.length), [showAttributes, items]); + const titleBar = useMemo(() => renderTitleBar(items?.length), [ + showAttributes, + items, + isTitlePopoverOpen, + ]); const [sorting, setSorting] = useState<{ sort: PropertySort }>({ sort: { diff --git a/public/components/trace_analytics/home.tsx b/public/components/trace_analytics/home.tsx index 0420640205..268881c042 100644 --- a/public/components/trace_analytics/home.tsx +++ b/public/components/trace_analytics/home.tsx @@ -5,7 +5,7 @@ import { EuiGlobalToastList } from '@elastic/eui'; import { Toast } from '@elastic/eui/src/components/toast/global_toast_list'; -import React, { ReactChild, useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { HashRouter, Redirect, Route, RouteComponentProps } from 'react-router-dom'; import { ChromeBreadcrumb, @@ -19,7 +19,8 @@ import { DataSourceManagementPluginSetup, DataSourceSelectableConfig, } from '../../../../../src/plugins/data_source_management/public'; -import { TraceAnalyticsMode } from '../../../common/types/trace_analytics'; +import { TRACE_TABLE_TYPE_KEY } from '../../../common/constants/trace_analytics'; +import { TraceAnalyticsMode, TraceQueryMode } from '../../../common/types/trace_analytics'; import { dataSourceFilterFn } from '../../../common/utils/shared'; import { coreRefs } from '../../framework/core_refs'; import { FilterType } from './components/common/filters/filters'; @@ -111,11 +112,9 @@ export const Home = (props: HomeProps) => { }; const [toasts, setToasts] = useState([]); - const _setToast = (title: string, color = 'success', text?: ReactChild, _side?: string) => { - if (!text) text = ''; - setToasts([...toasts, { id: new Date().toISOString(), title, text, color } as Toast]); - }; - + const [tracesTableMode, setTracesTableMode] = useState( + (sessionStorage.getItem(TRACE_TABLE_TYPE_KEY) as TraceQueryMode) || 'all_spans' + ); const [dataSourceMDSId, setDataSourceMDSId] = useState([{ id: '', label: '' }]); const [currentSelectedService, setCurrentSelectedService] = useState(''); @@ -230,7 +229,11 @@ export const Home = (props: HomeProps) => { }, ]; - const traceColumnAction = () => location.assign('#/traces'); + const traceColumnAction = () => { + location.assign('#/traces'); + setTracesTableMode('traces'); + sessionStorage.setItem(TRACE_TABLE_TYPE_KEY, 'traces'); + }; const getTraceViewUri = (traceId: string) => `#/traces/${encodeURIComponent(traceId)}`; @@ -329,6 +332,8 @@ export const Home = (props: HomeProps) => { setCurrentSelectedService={setCurrentSelectedService} toasts={toasts} dataSourceMDSId={dataSourceMDSId} + tracesTableMode={tracesTableMode} + setTracesTableMode={setTracesTableMode} {...commonProps} /> @@ -343,6 +348,8 @@ export const Home = (props: HomeProps) => { setCurrentSelectedService={setCurrentSelectedService} toasts={toasts} dataSourceMDSId={dataSourceMDSId} + tracesTableMode={tracesTableMode} + setTracesTableMode={setTracesTableMode} {...commonProps} /> diff --git a/public/components/trace_analytics/index.scss b/public/components/trace_analytics/index.scss index 9940f59dfb..779a472596 100644 --- a/public/components/trace_analytics/index.scss +++ b/public/components/trace_analytics/index.scss @@ -97,12 +97,28 @@ th[data-test-subj^='tableHeaderCell_dashboard_latency_variance'] { .attributes-column-header, .attributes-column { max-width: 200px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding-left: 8px; } .trace-group-column { min-width: 200px; } +.span-group-column { + min-width: 150px; +} + .attributes-column-header { display: table-cell; } + +.tableModePopover { + width: 300px; +} + +.popOverSelectableItem { + white-space: initial !important; +} diff --git a/public/components/trace_analytics/requests/queries/traces_queries.ts b/public/components/trace_analytics/requests/queries/traces_queries.ts index 9969954418..84571a9f2d 100644 --- a/public/components/trace_analytics/requests/queries/traces_queries.ts +++ b/public/components/trace_analytics/requests/queries/traces_queries.ts @@ -5,7 +5,7 @@ import { PropertySort } from '@elastic/eui'; import { TRACES_MAX_NUM } from '../../../../../common/constants/trace_analytics'; -import { TraceAnalyticsMode } from '../../../../../common/types/trace_analytics'; +import { TraceAnalyticsMode, TraceQueryMode } from '../../../../../common/types/trace_analytics'; import { SpanSearchParams } from '../../components/traces/span_detail_table'; export const getTraceGroupPercentilesQuery = () => { @@ -50,7 +50,8 @@ export const getTraceGroupPercentilesQuery = () => { export const getTracesQuery = ( mode: TraceAnalyticsMode, traceId: string = '', - sort?: PropertySort + sort?: PropertySort, + isUnderOneHour?: boolean ) => { const field = sort?.field || '_key'; const direction = sort?.direction || 'asc'; @@ -72,7 +73,7 @@ export const getTracesQuery = ( order: { [field]: direction, }, - execution_hint: 'map', + ...(isUnderOneHour && { execution_hint: 'map' }), }, aggs: { latency: { @@ -139,7 +140,7 @@ export const getTracesQuery = ( order: { [field]: direction, }, - execution_hint: 'map', + ...(isUnderOneHour && { execution_hint: 'map' }), }, aggs: { latency: { @@ -471,7 +472,9 @@ export const getSpansQuery = (spanSearchParams: SpanSearchParams) => { export const getCustomIndicesTracesQuery = ( mode: TraceAnalyticsMode, traceId: string = '', - sort?: PropertySort + sort?: PropertySort, + queryMode?: TraceQueryMode, + isUnderOneHour?: boolean ) => { const jaegerQuery: any = { size: 0, @@ -491,7 +494,7 @@ export const getCustomIndicesTracesQuery = ( order: { [sort?.field || '_key']: sort?.direction || 'asc', }, - execution_hint: 'map', + ...(isUnderOneHour && { execution_hint: 'map' }), }, aggs: { latency: { @@ -545,7 +548,9 @@ export const getCustomIndicesTracesQuery = ( size: TRACES_MAX_NUM, _source: { includes: [ + 'spanId', 'traceId', + 'parentSpanId', 'traceGroup', 'durationInNanos', 'status.code', @@ -557,13 +562,7 @@ export const getCustomIndicesTracesQuery = ( query: { bool: { must: [], - filter: [ - { - term: { - parentSpanId: '', // Data prepper root span doesn't have any parent. - }, - }, - ], + filter: [], should: [], must_not: [], }, @@ -571,6 +570,20 @@ export const getCustomIndicesTracesQuery = ( ...(sort && { sort: [{ [sort.field]: { order: sort.direction } }] }), track_total_hits: false, }; + + if (queryMode === 'root_spans') { + dataPrepperQuery.query.bool.filter.push({ + term: { + parentSpanId: '', // Data prepper root span doesn't have any parent. + }, + }); + } else if (queryMode === 'entry_spans') { + dataPrepperQuery.query.bool.filter.push({ + term: { + kind: 'SPAN_KIND_SERVER', + }, + }); + } if (traceId) { jaegerQuery.query.bool.filter.push({ term: { diff --git a/public/components/trace_analytics/requests/traces_request_handler.ts b/public/components/trace_analytics/requests/traces_request_handler.ts index 44af86d587..883014afbc 100644 --- a/public/components/trace_analytics/requests/traces_request_handler.ts +++ b/public/components/trace_analytics/requests/traces_request_handler.ts @@ -13,7 +13,7 @@ import { v1 as uuid } from 'uuid'; import { HttpSetup } from '../../../../../../src/core/public'; import { BarOrientation } from '../../../../common/constants/shared'; import { TRACE_ANALYTICS_DATE_FORMAT } from '../../../../common/constants/trace_analytics'; -import { TraceAnalyticsMode } from '../../../../common/types/trace_analytics'; +import { TraceAnalyticsMode, TraceQueryMode } from '../../../../common/types/trace_analytics'; import { microToMilliSec, nanoToMilliSec } from '../components/common/helper_functions'; import { SpanSearchParams } from '../components/traces/span_detail_table'; import { @@ -36,12 +36,14 @@ export const handleCustomIndicesTracesRequest = async ( setColumns: (items: any) => void, mode: TraceAnalyticsMode, dataSourceMDSId?: string, - sort?: PropertySort + sort?: PropertySort, + queryMode?: TraceQueryMode, + isUnderOneHour?: boolean ) => { const responsePromise = handleDslRequest( http, DSL, - getCustomIndicesTracesQuery(mode, undefined, sort), + getCustomIndicesTracesQuery(mode, undefined, sort, queryMode, isUnderOneHour), mode, dataSourceMDSId ); @@ -89,7 +91,8 @@ export const handleTracesRequest = async ( setItems: (items: any) => void, mode: TraceAnalyticsMode, dataSourceMDSId?: string, - sort?: PropertySort + sort?: PropertySort, + isUnderOneHour?: boolean ) => { const binarySearch = (arr: number[], target: number) => { if (!arr) return Number.NaN; @@ -107,7 +110,7 @@ export const handleTracesRequest = async ( const responsePromise = handleDslRequest( http, DSL, - getTracesQuery(mode, undefined, sort), + getTracesQuery(mode, undefined, sort, isUnderOneHour), mode, dataSourceMDSId );