Skip to content

Commit

Permalink
Update custom traces table with filters (#2178) (#2180)
Browse files Browse the repository at this point in the history
* update custom traces table with filters



* use css truncate, resolve comments



* add guards for execution_hint



* update descriptions



---------


(cherry picked from commit 00fd9ac)

Signed-off-by: Shenoy Pratik <[email protected]>
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
1 parent fcf35cb commit e8127d6
Show file tree
Hide file tree
Showing 12 changed files with 495 additions and 250 deletions.
25 changes: 25 additions & 0 deletions common/constants/trace_analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<keyof typeof TRACE_TABLE_TITLES, string> = {
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';
3 changes: 3 additions & 0 deletions common/types/trace_analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -54,3 +56,4 @@ export interface GraphVisEdge {
}

export type TraceAnalyticsMode = 'jaeger' | 'data_prepper' | 'custom_data_prepper';
export type TraceQueryMode = keyof typeof TRACE_TABLE_TITLES;
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ export function Application(props: AppDetailProps) {
setStartTime={setStartTimeForApp}
setEndTime={setEndTimeForApp}
dataSourceMDSId={[{ id: '', label: '' }]}
setCurrentSelectedService={() => {}}
tracesTableMode="traces"
setTracesTableMode={() => {}}
/>
<EuiPanel>
<PanelTitle title="Spans" totalItems={totalSpans} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -907,10 +907,10 @@ exports[`Added Integration View Test Renders added integration view using dummy
</EuiFlexGroup>
</EuiSearchBar>
<EuiSpacer
size="l"
size="m"
>
<div
className="euiSpacer euiSpacer--l"
className="euiSpacer euiSpacer--m"
/>
</EuiSpacer>
<EuiBasicTable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
EuiButtonIcon,
EuiCopy,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
EuiTableFieldDataColumnType,
EuiText,
EuiToolTip,
} from '@elastic/eui';
import { round } from 'lodash';
import moment from 'moment';
import React from 'react';
import { TRACE_ANALYTICS_DATE_FORMAT } from '../../../../../common/constants/trace_analytics';
import { TraceAnalyticsMode, TraceQueryMode } from '../../../../../common/types/trace_analytics';
import { nanoToMilliSec } from '../common/helper_functions';

export const fetchDynamicColumns = (columnItems: string[]) => {
return columnItems
.filter((col) => col.includes('attributes') || col.includes('instrumentation'))
.map((col) => ({
className: 'attributes-column',
field: col,
name: (
<EuiText className="euiTableCellContent">
<EuiToolTip content={col}>
<p className="euiTableCellContent__text attributes-column-header">{col}</p>
</EuiToolTip>
</EuiText>
),
align: 'right',
sortable: true,
truncateText: true,
render: (item) =>
item ? (
<EuiText>
<EuiToolTip content={item}>
<EuiText size="s" className="attributes-column" title={item}>
{item}
</EuiText>
</EuiToolTip>
</EuiText>
) : (
'-'
),
}));
};

export const getTableColumns = (
showAttributes: boolean,
columnItems: string[],
mode: TraceAnalyticsMode,
tracesTableMode: TraceQueryMode,
getTraceViewUri?: (traceId: string) => string,
openTraceFlyout?: (traceId: string) => void
): Array<EuiTableFieldDataColumnType<any>> => {
// Helper functions for rendering table fields
const renderIdField = (item: string) =>
item ? (
<EuiText>
<EuiToolTip content={item}>
<EuiText size="s" className="traces-table traces-table-trace-id" title={item}>
{item}
</EuiText>
</EuiToolTip>
</EuiText>
) : (
'-'
);

const renderTraceLinkField = (item: string) => (
<EuiFlexGroup gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}>
<EuiLink
data-test-subj="trace-link"
{...(getTraceViewUri && { href: getTraceViewUri(item) })}
{...(openTraceFlyout && { onClick: () => openTraceFlyout(item) })}
>
<EuiText size="s" className="traces-table traces-table-trace-id" title={item}>
{item}
</EuiText>
</EuiLink>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiCopy textToCopy={item}>
{(copy) => (
<EuiButtonIcon aria-label="Copy trace id" iconType="copyClipboard" onClick={copy} />
)}
</EuiCopy>
</EuiFlexItem>
</EuiFlexGroup>
);

const renderErrorsField = (item: number) =>
item == null ? (
'-'
) : +item > 0 ? (
<EuiText color="danger" size="s">
Yes
</EuiText>
) : (
'No'
);

const renderDurationField = (item: number) =>
item ? <EuiText size="s">{round(nanoToMilliSec(Math.max(0, item)), 2)}</EuiText> : '-';

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<EuiTableFieldDataColumnType<any>>;
}

// 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<EuiTableFieldDataColumnType<any>>;
}

// 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<EuiTableFieldDataColumnType<any>>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -18,6 +19,8 @@ export interface TracesProps extends TraceAnalyticsComponentDeps {
openTraceFlyout?: (traceId: string) => void;
toasts: Toast[];
dataSourceMDSId: DataSourceOption[];
tracesTableMode: TraceQueryMode;
setTracesTableMode: React.Dispatch<React.SetStateAction<TraceQueryMode>>;
}

export function Traces(props: TracesProps) {
Expand Down
Loading

0 comments on commit e8127d6

Please sign in to comment.