Skip to content

Commit

Permalink
add support for custom trace indices
Browse files Browse the repository at this point in the history
Signed-off-by: Shenoy Pratik <[email protected]>
  • Loading branch information
ps48 committed Sep 3, 2024
1 parent 38488d6 commit dd421e0
Show file tree
Hide file tree
Showing 29 changed files with 409 additions and 97 deletions.
3 changes: 3 additions & 0 deletions common/constants/trace_analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ export const TRACE_ANALYTICS_JAEGER_INDICES_ROUTE =
export const TRACE_ANALYTICS_DATA_PREPPER_INDICES_ROUTE =
'/api/observability/trace_analytics/data_prepper_indices';
export const TRACE_ANALYTICS_DSL_ROUTE = '/api/observability/trace_analytics/query';

export const TRACE_CUSTOM_SPAN_INDEX_SETTING = 'observability:traceAnalyticsSpanIndices';
export const TRACE_CUSTOM_SERVICE_INDEX_SETTING = 'observability:traceAnalyticsServiceIndices';
2 changes: 2 additions & 0 deletions common/types/trace_analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,5 @@ export interface GraphVisEdge {
to: number;
color: string;
}

export type TraceAnalyticsMode = 'jaeger' | 'data_prepper' | 'custom_data_prepper';
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,32 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiText, EuiSpacer, EuiHorizontalRule, EuiCodeBlock } from '@elastic/eui';
import { EuiCodeBlock, EuiHorizontalRule, EuiSpacer, EuiText } from '@elastic/eui';
import React, { useEffect, useMemo, useState } from 'react';
import { HttpStart } from '../../../../../../../src/core/public';
import { TraceAnalyticsMode } from '../../../../../common/types/trace_analytics';
import { ServiceBreakdownPanel } from '../../../trace_analytics/components/traces/service_breakdown_panel';
import { SpanDetailPanel } from '../../../trace_analytics/components/traces/span_detail_panel';
import {
handleTraceViewRequest,
handleServicesPieChartRequest,
handlePayloadRequest,
handleServicesPieChartRequest,
handleTraceViewRequest,
} from '../../../trace_analytics/requests/traces_request_handler';
import { HttpStart } from '../../../../../../../src/core/public';
import { getListItem } from '../../helpers/utils';
import { TraceAnalyticsMode } from '../../../../../public/components/trace_analytics/home';

interface TraceDetailRenderProps {
traceId: string;
http: HttpStart;
openSpanFlyout: (spanId: string) => void;
mode : TraceAnalyticsMode
mode: TraceAnalyticsMode;
}

export const TraceDetailRender = ({ traceId, http, openSpanFlyout, mode }: TraceDetailRenderProps) => {
export const TraceDetailRender = ({
traceId,
http,
openSpanFlyout,
mode,
}: TraceDetailRenderProps) => {
const [fields, setFields] = useState<any>({});

Check warning on line 32 in public/components/application_analytics/components/flyout_components/trace_detail_render.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const [serviceBreakdownData, setServiceBreakdownData] = useState([]);
const [payloadData, setPayloadData] = useState('');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import { configure, mount, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { TraceAnalyticsMode } from 'public/components/trace_analytics/home';
import React from 'react';
import { TEST_SERVICE_MAP, TEST_SERVICE_MAP_GRAPH } from '../../../../../../test/constants';
import {
Expand Down Expand Up @@ -38,7 +37,9 @@ describe('Helper functions', () => {

it('renders no match and missing configuration messages', () => {
const noMatchMessage = shallow(<NoMatchMessage size="s" />);
const missingConfigurationMessage = shallow(<MissingConfigurationMessage mode='data_prepper'/>)
const missingConfigurationMessage = shallow(
<MissingConfigurationMessage mode="data_prepper" />
);
expect(noMatchMessage).toMatchSnapshot();
expect(missingConfigurationMessage).toMatchSnapshot();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
EuiCallOut,
EuiCompressedFieldText,
EuiDescribedFormGroup,
EuiFlexGroup,
EuiFlexItem,
EuiFlyout,
EuiFlyoutBody,
EuiFlyoutFooter,
EuiFlyoutHeader,
EuiFormRow,
EuiLink,
EuiSmallButton,
EuiSmallButtonEmpty,
EuiTitle,
} from '@elastic/eui';
import React, { Fragment, useEffect, useState } from 'react';
import {
TRACE_CUSTOM_SERVICE_INDEX_SETTING,
TRACE_CUSTOM_SPAN_INDEX_SETTING,
} from '../../../../../common/constants/trace_analytics';
import { uiSettingsService } from '../../../../../common/utils';
import { useToast } from '../../../common/toast';

interface CustomIndexFlyoutProps {
isFlyoutVisible: boolean;
setIsFlyoutVisible: React.Dispatch<React.SetStateAction<boolean>>;
}

export const CustomIndexFlyout = ({
isFlyoutVisible,
setIsFlyoutVisible,
}: CustomIndexFlyoutProps) => {
const { setToast } = useToast();
const [spanIndices, setSpanIndices] = useState('');
const [serviceIndices, setServiceIndices] = useState('');
const [isLoading, setIsLoading] = useState(false);

const onChangeSpanIndices = (e: { target: { value: React.SetStateAction<string> } }) => {
setSpanIndices(e.target.value);
};

const onChangeServiceIndices = (e: { target: { value: React.SetStateAction<string> } }) => {
setServiceIndices(e.target.value);
};

useEffect(() => {
setSpanIndices(uiSettingsService.get(TRACE_CUSTOM_SPAN_INDEX_SETTING));
setServiceIndices(uiSettingsService.get(TRACE_CUSTOM_SERVICE_INDEX_SETTING));
}, [uiSettingsService]);

Check warning on line 55 in public/components/trace_analytics/components/common/custom_index_flyout.tsx

View workflow job for this annotation

GitHub Actions / Lint

React Hook useEffect has an unnecessary dependency: 'uiSettingsService'. Either exclude it or remove the dependency array. Outer scope values like 'uiSettingsService' aren't valid dependencies because mutating them doesn't re-render the component

const onSaveIndices = async () => {
try {
setIsLoading(true);
await uiSettingsService.set(TRACE_CUSTOM_SPAN_INDEX_SETTING, spanIndices);
await uiSettingsService.set(TRACE_CUSTOM_SERVICE_INDEX_SETTING, serviceIndices);
setIsLoading(false);
setToast('Updated trace analytics sources successfully', 'success');
} catch (error) {
console.error(error);
setToast('Failed to update trace analytics sources', 'danger');
}
setIsLoading(false);
};

const callout = (
<EuiCallOut
title="Custom indices in trace analytics is an experimental feature"
color="warning"
iconType="help"
>
<p>
This feature is experimental, all indices added here should adhere to data prepper index
mappings. For more information on mappings, visit{' '}
<EuiLink href="https://github.com/opensearch-project/data-prepper/tree/main/docs/schemas/trace-analytics">
documentation
</EuiLink>
.
</p>
</EuiCallOut>
);
let flyout;

if (isFlyoutVisible) {
flyout = (
<EuiFlyout ownFocus onClose={() => setIsFlyoutVisible(false)} aria-labelledby="flyoutTitle">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h3 id="flyoutTitle">Manage custom trace indices</h3>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody banner={callout}>
<EuiDescribedFormGroup
title={<h3>Custom span indices</h3>}
description={
<Fragment>
Configure custom span indices to be used by the trace analytics plugin
</Fragment>
}
>
<EuiFormRow label="Custom span indices">
<EuiCompressedFieldText
name="spanIndices"
aria-label="spanIndices"
placeholder="index1,cluster1:index2,cluster:index3"
value={spanIndices}
onChange={onChangeSpanIndices}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
<EuiDescribedFormGroup
title={<h3>Custom service indices</h3>}
description={
<Fragment>
Configure custom service indices to be used by the trace analytics plugin
</Fragment>
}
>
<EuiFormRow label="Custom service indices">
<EuiCompressedFieldText
name="serviceIndices"
aria-label="serviceIndices"
placeholder="index1,cluster1:index2,cluster:index3"
value={serviceIndices}
onChange={onChangeServiceIndices}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiSmallButtonEmpty
iconType="cross"
onClick={() => setIsFlyoutVisible(false)}
flush="left"
>
Close
</EuiSmallButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSmallButton
onClick={async () => {
await onSaveIndices();
setIsFlyoutVisible(false);
}}
fill
isLoading={isLoading}
>
Save
</EuiSmallButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlyoutFooter>
</EuiFlyout>
);
}
return <div>{flyout}</div>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
import {
EuiCompressedComboBox,
EuiCompressedFieldText,
EuiFormControlLayoutDelimited,
EuiCompressedFormRow,
EuiFormControlLayoutDelimited,
EuiSpacer,
} from '@elastic/eui';
import get from 'lodash/get';
import { TraceAnalyticsMode } from 'public/components/trace_analytics/home';
import React from 'react';
import { TraceAnalyticsMode } from '../../../../../../common/types/trace_analytics';

const getFields = (
mode: TraceAnalyticsMode,
page: 'dashboard' | 'traces' | 'services' | 'app',
attributesFilterFields: string[]
) =>
mode === 'data_prepper'
mode === 'data_prepper' || mode === 'custom_data_prepper'
? {
dashboard: ['traceGroup', 'serviceName', 'error', 'status.message', 'latency'],
traces: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
import {
EuiBadge,
EuiButtonEmpty,
EuiSmallButtonIcon,
EuiContextMenu,
EuiContextMenuPanelDescriptor,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiPopover,
EuiPopoverTitle,
EuiSmallButtonIcon,
EuiTextColor,
} from '@elastic/eui';
import { TraceAnalyticsMode } from 'public/components/trace_analytics/home';
import React, { useMemo, useState } from 'react';
import { TraceAnalyticsMode } from '../../../../../../common/types/trace_analytics';
import { FilterEditPopover } from './filter_edit_popover';
import { getFilterFields, getValidFilterFields } from './filter_helpers';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/* eslint-disable radix */

import dateMath from '@elastic/datemath';
import { EuiSmallButtonEmpty, EuiEmptyPrompt, EuiSpacer, EuiText } from '@elastic/eui';
import { EuiEmptyPrompt, EuiSmallButtonEmpty, EuiSpacer, EuiText } from '@elastic/eui';
import { SpacerSize } from '@elastic/eui/src/components/spacer/spacer';
import { isEmpty, round } from 'lodash';
import React from 'react';
Expand All @@ -15,10 +15,15 @@ import {
JAEGER_INDEX_NAME,
JAEGER_SERVICE_INDEX_NAME,
TRACE_ANALYTICS_DOCUMENTATION_LINK,
TRACE_CUSTOM_SERVICE_INDEX_SETTING,
TRACE_CUSTOM_SPAN_INDEX_SETTING,
} from '../../../../../common/constants/trace_analytics';
import { GraphVisEdge, GraphVisNode } from '../../../../../common/types/trace_analytics';
import {
GraphVisEdge,
GraphVisNode,
TraceAnalyticsMode,
} from '../../../../../common/types/trace_analytics';
import { uiSettingsService } from '../../../../../common/utils';
import { TraceAnalyticsMode } from '../../home';
import { serviceMapColorPalette } from './color_palette';
import { FilterType } from './filters/filters';
import { ServiceObject } from './plots/service_map';
Expand Down Expand Up @@ -429,13 +434,13 @@ export const filtersToDsl = (
let filterQuery = {};
let field = filter.field;
if (field === 'latency') {
if (mode === 'data_prepper') {
if (mode === 'data_prepper' || mode === 'custom_data_prepper') {
field = 'traceGroupFields.durationInNanos';
} else if (mode === 'jaeger') {
field = 'duration';
}
} else if (field === 'error') {
if (mode === 'data_prepper') {
if (mode === 'data_prepper' || mode === 'custom_data_prepper') {
field = 'traceGroupFields.statusCode';
} else if (mode === 'jaeger') {
field = 'tag.error';
Expand Down Expand Up @@ -569,3 +574,43 @@ export const getAttributes = (jsonMapping: JsonMapping): string[] => {
}
return [];
};

export const getTraceCustomSpanIndex = () => {
return uiSettingsService.get(TRACE_CUSTOM_SPAN_INDEX_SETTING);
};

export const getTraceCustomServiceIndex = () => {
return uiSettingsService.get(TRACE_CUSTOM_SERVICE_INDEX_SETTING);
};

export const setTraceCustomSpanIndex = (value: string) => {
return uiSettingsService.set(TRACE_CUSTOM_SPAN_INDEX_SETTING, value);
};

export const setTraceCustomServiceIndex = (value: string) => {
return uiSettingsService.set(TRACE_CUSTOM_SERVICE_INDEX_SETTING, value);
};

export const getSpanIndices = (mode: TraceAnalyticsMode) => {
switch (mode) {
case 'custom_data_prepper':
return getTraceCustomSpanIndex();
case 'data_prepper':
return DATA_PREPPER_INDEX_NAME;
case 'jaeger':
default:
return JAEGER_INDEX_NAME;
}
};

export const getServiceIndices = (mode: TraceAnalyticsMode) => {
switch (mode) {
case 'custom_data_prepper':
return getTraceCustomServiceIndex();
case 'data_prepper':
return DATA_PREPPER_SERVICE_INDEX_NAME;
case 'jaeger':
default:
return JAEGER_SERVICE_INDEX_NAME;
}
};
Loading

0 comments on commit dd421e0

Please sign in to comment.