Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update custom traces table with filters #2178

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions common/constants/trace_analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,35 @@ 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 = 'Spans',
trace_root_spans = 'Trace root spans',
service_entry_spans = 'Service entry spans',
traces = 'Traces',
}

export const TRACE_TABLE_OPTIONS = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users might ask for caching selected option.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, for now I've added the selection in the session storage similar to how we store filters. So the table type selection is persisted in the session lifecycle.

{
label: TRACE_TABLE_TITLES.all_spans,
key: 'all_spans',
'aria-describedby': 'All spans from all traces',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Span from all traces.
??

},
{
label: TRACE_TABLE_TITLES.trace_root_spans,
key: 'trace_root_spans',
'aria-describedby': 'The root spans which represent the starting point of a trace',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Root spans representing the starting point of each trace

},
{
label: TRACE_TABLE_TITLES.service_entry_spans,
key: 'service_entry_spans',
'aria-describedby': 'The spans that mark start of server-side processing (SPAN_KIND_SERVER)',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel SPAN_KIND_SERVER is not needed. If required, bring in the exact description of SPAN_KIND_SERVER from open telemetry.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spans marking the start of server-side processing
??

},
{
label: TRACE_TABLE_TITLES.traces,
key: 'traces',
'aria-describedby': 'Aggregates all spans by traceId to show all traces',
Copy link
Member

@vamsi-amazon vamsi-amazon Sep 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spans aggregated by traceId to show all traces
Maintaining consistency where we start all the descriptions by Spans.

Do we need to show all traces?

How is this different from first option?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This table is the old way of showing just traces using the aggregation query. Kept this option if users still want aggregation and are not concerned about the wait time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only table where we shows traces and not spans

},
];

export const TRACE_TABLE_TYPE_KEY = 'TraceAnalyticsTraceTableType';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally the constants are in common only if they are shared between client (public) and server. if they are only used on one side they can go directly there

Copy link
Member Author

@ps48 ps48 Sep 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Will keep this one here for now. Will sort out this and others in common/constants during a mini refactor.

1 change: 1 addition & 0 deletions common/types/trace_analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ export interface GraphVisEdge {
}

export type TraceAnalyticsMode = 'jaeger' | 'data_prepper' | 'custom_data_prepper';
export type TraceQueryMode = 'trace_root_spans' | 'all_spans' | 'traces' | 'service_entry_spans';
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
const [serviceFlyoutName, setServiceFlyoutName] = useState<string>('');
const [traceFlyoutId, setTraceFlyoutId] = useState<string>('');
const [spanFlyoutId, setSpanFlyoutId] = useState<string>('');
const [spanDSL, setSpanDSL] = useState<any>({});

Check warning on line 136 in public/components/application_analytics/components/application.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const [totalSpans, setTotalSpans] = useState<number>(0);
const [editVizId, setEditVizId] = useState<string>('');
const [visWithAvailability, setVisWithAvailability] = useState<EuiSelectOption[]>([]);
Expand All @@ -156,7 +156,7 @@
sessionStorage.setItem(`${application.name}EndTime`, newEndTime);
};

const addSpanFilter = (field: string, value: any) => {

Check warning on line 159 in public/components/application_analytics/components/application.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const newFilters = [...filters];
const index = newFilters.findIndex(({ field: filterField }) => field === filterField);
if (index === -1) {
Expand Down Expand Up @@ -285,7 +285,7 @@
},
];

const nameColumnAction = (item: any) => openServiceFlyout(item);

Check warning on line 288 in public/components/application_analytics/components/application.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const traceColumnAction = () => switchToTrace();

const getService = () => {
Expand Down Expand Up @@ -326,6 +326,9 @@
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>> => {

Check warning on line 61 in public/components/trace_analytics/components/traces/trace_table_helpers.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
// 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>>;

Check warning on line 172 in public/components/trace_analytics/components/traces/trace_table_helpers.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
}

// 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>>;

Check warning on line 220 in public/components/trace_analytics/components/traces/trace_table_helpers.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
}

// 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>>;

Check warning on line 247 in public/components/trace_analytics/components/traces/trace_table_helpers.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
};
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
Loading