diff --git a/common/constants/shared.ts b/common/constants/shared.ts index 39717adaf..a8e61b4cf 100644 --- a/common/constants/shared.ts +++ b/common/constants/shared.ts @@ -32,7 +32,7 @@ export const SQL_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/search- export const PPL_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/observability/ppl/commands/'; export const UI_DATE_FORMAT = 'MM/DD/YYYY hh:mm A'; -export const PPL_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss'; +export const PPL_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSSSSS'; export const PPL_SPAN_REGEX = /by\s*span/i; export const PPL_STATS_REGEX = /\|\s*stats/i; export const PPL_INDEX_INSERT_POINT_REGEX = /(search source|source|index)\s*=\s*([^\s]+)(.*)/i; diff --git a/public/components/explorer/data_grid.scss b/public/components/explorer/data_grid.scss index 7de013f9b..6de07488a 100644 --- a/public/components/explorer/data_grid.scss +++ b/public/components/explorer/data_grid.scss @@ -329,7 +329,7 @@ discover-app { .dscCollapsibleSidebar { position: relative; - z-index: $euiZLevel1; + z-index: 1; .dscCollapsibleSidebar__collapseButton { position: absolute; diff --git a/public/components/explorer/docTable/__tests__/__snapshots__/docViewer.test.tsx.snap b/public/components/explorer/docTable/__tests__/__snapshots__/docViewer.test.tsx.snap index 4e3fec848..bfb885f38 100644 --- a/public/components/explorer/docTable/__tests__/__snapshots__/docViewer.test.tsx.snap +++ b/public/components/explorer/docTable/__tests__/__snapshots__/docViewer.test.tsx.snap @@ -29,12 +29,13 @@ exports[`Datagrid Doc viewer component Renders Doc viewer component 1`] = ` "avg(FlightDelayMin)": "45.957544288332315", } } + logTraceId="" /> , - "id": "doc_viewer_tab_2", + "id": "doc_viewer_tab_5", "name": "Table", } } @@ -53,12 +54,13 @@ exports[`Datagrid Doc viewer component Renders Doc viewer component 1`] = ` "avg(FlightDelayMin)": "45.957544288332315", } } + logTraceId="" /> , - "id": "doc_viewer_tab_2", + "id": "doc_viewer_tab_5", "name": "Table", }, Object { @@ -74,12 +76,13 @@ exports[`Datagrid Doc viewer component Renders Doc viewer component 1`] = ` "avg(FlightDelayMin)": "45.957544288332315", } } + logTraceId="" /> , - "id": "doc_viewer_tab_3", + "id": "doc_viewer_tab_6", "name": "JSON", }, Object { @@ -95,13 +98,19 @@ exports[`Datagrid Doc viewer component Renders Doc viewer component 1`] = ` "avg(FlightDelayMin)": "45.957544288332315", } } + logTraceId="" /> , - "id": "doc_viewer_tab_4", - "name": "Traces", + "id": "doc_viewer_tab_7", + "name": + + Traces + + + , }, ] } @@ -117,9 +126,9 @@ exports[`Datagrid Doc viewer component Renders Doc viewer component 1`] = ` >
@@ -215,6 +226,7 @@ exports[`Datagrid Doc viewer component Renders Doc viewer component 1`] = ` "avg(FlightDelayMin)": "45.957544288332315", } } + logTraceId="" > diff --git a/public/components/explorer/docTable/docView.scss b/public/components/explorer/docTable/docView.scss index ecdef748f..fbe69b2a6 100644 --- a/public/components/explorer/docTable/docView.scss +++ b/public/components/explorer/docTable/docView.scss @@ -41,3 +41,11 @@ top: 17px; z-index: 3; } + +.vertical-center { + margin-top: auto; +} + +.trace-link { + margin-left: 5px; +} diff --git a/public/components/explorer/docTable/docViewRow.tsx b/public/components/explorer/docTable/docViewRow.tsx index 219909907..ad237c4b6 100644 --- a/public/components/explorer/docTable/docViewRow.tsx +++ b/public/components/explorer/docTable/docViewRow.tsx @@ -11,10 +11,10 @@ import { IExplorerFields, IField } from '../../../../common/types/explorer'; import { DocFlyout } from './doc_flyout'; import { HttpStart } from '../../../../../../src/core/public'; import { OTEL_TRACE_ID } from '../../../../common/constants/explorer'; -import { isValidTraceId } from './trace_block/trace_block'; import { useEffect } from 'react'; import { SurroundingFlyout } from './surrounding_flyout'; import PPLService from '../../../services/requests/ppl'; +import { isValidTraceId } from '../utils'; export interface IDocType { [key: string]: string; @@ -36,6 +36,7 @@ export const DocViewRow = (props: IDocViewRowProps) => { const [detailsOpen, setDetailsOpen] = useState(false); const [surroundingEventsOpen, setSurroundingEventsOpen] = useState(false); const [openTraces, setOpenTraces] = useState(false); + const [flyoutToggleSize, setFlyoutToggleSize] = useState(true); const getTdTmpl = (conf: { clsName: string; content: React.ReactDOM | string }) => { const { clsName, content } = conf; @@ -174,6 +175,9 @@ export const DocViewRow = (props: IDocViewRowProps) => { memorizedTds={getTds(doc, selectedCols, true).slice(1)} explorerFields={explorerFields} openTraces={openTraces} + rawQuery={rawQuery} + toggleSize={flyoutToggleSize} + setToggleSize={setFlyoutToggleSize} setOpenTraces={setOpenTraces} setSurroundingEventsOpen={setSurroundingEventsOpen} > @@ -197,6 +201,8 @@ export const DocViewRow = (props: IDocViewRowProps) => { rawQuery={rawQuery} selectedCols={selectedCols} getTds={getTds} + toggleSize={flyoutToggleSize} + setToggleSize={setFlyoutToggleSize} /> ); } diff --git a/public/components/explorer/docTable/docViewer.tsx b/public/components/explorer/docTable/docViewer.tsx index 97df28af5..87072d5e0 100644 --- a/public/components/explorer/docTable/docViewer.tsx +++ b/public/components/explorer/docTable/docViewer.tsx @@ -8,6 +8,7 @@ import _ from 'lodash'; import { EuiFlexGroup, EuiFlexItem, + EuiLink, EuiPanel, EuiTabbedContent, EuiTabbedContentTab, @@ -17,6 +18,9 @@ import { JsonCodeBlock } from './json_code_block/json_code_block'; import { IDocType } from './docViewRow'; import { HttpSetup } from '../../../../../../src/core/public'; import { TraceBlock } from './trace_block/trace_block'; +import { OTEL_TRACE_ID } from '../../../../common/constants/explorer'; +import { isValidTraceId } from '../utils'; +import { log } from 'util'; interface IDocViewerProps { http: HttpSetup; @@ -26,6 +30,8 @@ interface IDocViewerProps { export function DocViewer(props: IDocViewerProps) { const [curSelectedTab, setCurSelectedTab] = useState(null); + const [logTraceId, setLogTraceId] = useState(''); + const [tracesLink, setTracesLink] = useState(<>); // can be passed in later const getTabList = () => { @@ -51,7 +57,13 @@ export function DocViewer(props: IDocViewerProps) { }, { id: _.uniqueId('doc_viewer_tab_'), - name: 'Traces', + name: ( + <> + Traces + {tracesLink} + + ), + component: (tabProps: any) => , otherProps: {}, }, @@ -64,18 +76,19 @@ export function DocViewer(props: IDocViewerProps) { return { id: tab.id, name: tab.name, + content: ( - {' '} + {' '} ), }; }); - }, [props.hit]); + }, [props.hit, logTraceId, tracesLink]); if (!tabs.length) { // There there's a minimum of 2 tabs active in Discover. @@ -83,6 +96,18 @@ export function DocViewer(props: IDocViewerProps) { return null; } + useEffect(() => { + const traceId = props.hit.hasOwnProperty(OTEL_TRACE_ID) ? props.hit[OTEL_TRACE_ID] : ''; + setLogTraceId(traceId); + setTracesLink( + traceId !== '' && isValidTraceId(traceId) ? ( + + ) : ( + <> + ) + ); + }, []); + return (
>; setOpenTraces: React.Dispatch>; setSurroundingEventsOpen: React.Dispatch>; }; @@ -47,11 +52,12 @@ export const DocFlyout = ({ memorizedTds, explorerFields, openTraces, + rawQuery, + toggleSize, + setToggleSize, setOpenTraces, setSurroundingEventsOpen, }: Props) => { - const [toggleSize, setToggleSize] = useState(true); - const closeFlyout = () => { setDetailsOpen(false); setOpenTraces(false); @@ -67,8 +73,12 @@ export const DocFlyout = ({ -

- Time: {moment(doc[timeStampField]).format(uiSettingsService.get('dateFormat'))} +

+ {doc.hasOwnProperty(timeStampField) + ? `Event: ${moment(doc[timeStampField]).format( + uiSettingsService.get('dateFormat') + )}` + : `Event Details`}

@@ -87,9 +97,26 @@ export const DocFlyout = ({ /> - - View surrounding events - + Cannot view surrounding events with `stats` command in PPL query

+ ) : !doc.hasOwnProperty(timeStampField) ? ( +

Cannot view surrounding events without time field in query response

+ ) : ( +

View surrounding events based on timestamp

+ ) + } + > + + View surrounding events + +
diff --git a/public/components/explorer/docTable/surrounding_flyout.tsx b/public/components/explorer/docTable/surrounding_flyout.tsx index b53041c03..d22b44563 100644 --- a/public/components/explorer/docTable/surrounding_flyout.tsx +++ b/public/components/explorer/docTable/surrounding_flyout.tsx @@ -8,6 +8,7 @@ import { FlyoutContainers } from '../../common/flyout_containers'; import React, { useEffect, useState } from 'react'; import { IDocType } from './docViewRow'; import { + EuiButton, EuiButtonEmpty, EuiButtonIcon, EuiCallOut, @@ -20,6 +21,7 @@ import { EuiSpacer, EuiText, EuiTitle, + EuiToolTip, } from '@elastic/eui'; import { IExplorerFields, IField } from '../../../../common/types/explorer'; import { getHeaders, fetchSurroundingData, rangeNumDocs, populateDataGrid } from '../utils'; @@ -42,6 +44,8 @@ type Props = { rawQuery: string; selectedCols: IField[]; getTds: (doc: IDocType, selectedCols: Array, isFlyout: boolean) => JSX.Element[]; + toggleSize: boolean; + setToggleSize: React.Dispatch>; }; export const SurroundingFlyout = ({ @@ -59,8 +63,9 @@ export const SurroundingFlyout = ({ rawQuery, selectedCols, getTds, + toggleSize, + setToggleSize, }: Props) => { - const [toggleSize, setToggleSize] = useState(true); const [numNewEvents, setNumNewEvents] = useState(5); const [valueOldEvents, setNumOldEvents] = useState(5); const [loadingNewEvents, setLoadingNewEvents] = useState(false); @@ -76,6 +81,12 @@ export const SurroundingFlyout = ({ setSurroundingEventsOpen(false); }; + const openDetailsFlyout = () => { + setDetailsOpen(true); + setOpenTraces(false); + setSurroundingEventsOpen(false); + }; + const loadData = async (typeOfDocs: 'new' | 'old', value: number) => { const numDocs = rangeNumDocs(value); let resultCount = 0; @@ -138,9 +149,11 @@ export const SurroundingFlyout = ({ const flyoutHeader = ( - + -

View surrounding events

+

+ View surrounding events +

@@ -157,6 +170,16 @@ export const SurroundingFlyout = ({ }} /> + + + View event details + +
); diff --git a/public/components/explorer/docTable/trace_block/trace_block.tsx b/public/components/explorer/docTable/trace_block/trace_block.tsx index f9b77b73c..6227666e8 100644 --- a/public/components/explorer/docTable/trace_block/trace_block.tsx +++ b/public/components/explorer/docTable/trace_block/trace_block.tsx @@ -4,7 +4,7 @@ */ import { TraceDetailRender } from '../../../application_analytics/components/flyout_components/trace_detail_render'; -import React from 'react'; +import React, { useEffect } from 'react'; import { HttpSetup } from '../../../../../../../src/core/public'; import { EuiCallOut, EuiLink } from '@elastic/eui'; import { TRACE_ANALYTICS_DOCUMENTATION_LINK } from '../../../../../common/constants/trace_analytics'; @@ -13,20 +13,16 @@ import { OTEL_TRACE_ID, } from '../../../../../common/constants/explorer'; import { IDocType } from '../docViewRow'; +import { isValidTraceId } from '../../utils'; interface props { http: HttpSetup; hit: IDocType; + logTraceId: string; } -export const isValidTraceId = (traceId: string) => { - return new Blob([traceId]).size === 32; -}; - -export const TraceBlock = ({ http, hit }: props) => { - let traceId = hit.hasOwnProperty(OTEL_TRACE_ID) ? hit[OTEL_TRACE_ID] : ''; - - if (traceId == '' || !isValidTraceId(traceId)) { +export const TraceBlock = ({ http, hit, logTraceId }: props) => { + if (logTraceId === '' || !isValidTraceId(logTraceId)) { return ( <> @@ -46,5 +42,6 @@ export const TraceBlock = ({ http, hit }: props) => { ); } - return ; + + return ; }; diff --git a/public/components/explorer/utils/index.tsx b/public/components/explorer/utils/index.tsx index dd58327dd..15ab0f0b1 100644 --- a/public/components/explorer/utils/index.tsx +++ b/public/components/explorer/utils/index.tsx @@ -3,4 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -export { getTrs, getHeaders, fetchSurroundingData, rangeNumDocs, populateDataGrid } from './utils'; +export { + getTrs, + getHeaders, + fetchSurroundingData, + rangeNumDocs, + populateDataGrid, + isValidTraceId, +} from './utils'; diff --git a/public/components/explorer/utils/utils.tsx b/public/components/explorer/utils/utils.tsx index bcb69cd8f..3d09e06b5 100644 --- a/public/components/explorer/utils/utils.tsx +++ b/public/components/explorer/utils/utils.tsx @@ -9,7 +9,12 @@ import React from 'react'; import { DocViewRow, IDocType } from '../docTable'; import { HttpStart } from '../../../../../../src/core/public'; import PPLService from '../../../services/requests/ppl'; -import { PPL_INDEX_REGEX } from '../../../../common/constants/shared'; +import { + PPL_DATE_FORMAT, + PPL_INDEX_REGEX, + PPL_STATS_REGEX, +} from '../../../../common/constants/shared'; +import moment from 'moment'; // Create Individual table rows for events datagrid and flyouts export const getTrs = ( @@ -162,6 +167,7 @@ export const fetchSurroundingData = async ( ) => { let resultCount = 0; let isErred = false; + const pplEventTime = moment(eventTime).format(PPL_DATE_FORMAT); setLoadingData(true); setIsError(''); @@ -196,8 +202,8 @@ export const fetchSurroundingData = async ( if (resultCount !== numDocs && !isErred) { const errorMessage = resultCount !== 0 - ? `Could only find ${resultCount} ${typeOfDocs} events!` - : `Could not find any ${typeOfDocs} events!`; + ? `Could only find ${resultCount} ${typeOfDocs} event${resultCount === 1 ? '' : 's'}!` + : `Could not find any ${typeOfDocs} event!`; setIsError(errorMessage); } @@ -208,3 +214,8 @@ export const fetchSurroundingData = async ( export const rangeNumDocs = (value: number) => { return value > 10000 ? 10000 : value < 0 ? 0 : value; }; + +// check traceId Byte Size +export const isValidTraceId = (traceId: string) => { + return new Blob([traceId]).size === 32; +};