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

Traces/Services - Query optimization / UI setting / Bugfix #2310

Merged
merged 13 commits into from
Jan 17, 2025
Merged
1 change: 1 addition & 0 deletions .cypress/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
cy.get('.euiQuickSelect__applyButton').click();
cy.get('.euiSuperDatePicker__prettyFormatLink').click();
cy.get('.euiTab__content').contains('Absolute').click();
cy.get('input[data-test-subj="superDatePickerAbsoluteDateInput"]')

Check warning on line 73 in .cypress/utils/constants.js

View workflow job for this annotation

GitHub Actions / Lint

Do not use force on click and type calls
.focus()
.type('{selectall}' + startTime, { force: true });
if (setEndTime) {
Expand All @@ -78,7 +78,7 @@
'button.euiDatePopoverButton--end[data-test-subj="superDatePickerendDatePopoverButton"]'
).click();
cy.get('.euiTab__content').contains('Absolute').click();
cy.get('input[data-test-subj="superDatePickerAbsoluteDateInput"]')

Check warning on line 81 in .cypress/utils/constants.js

View workflow job for this annotation

GitHub Actions / Lint

Do not use force on click and type calls
.focus()
.type('{selectall}' + endTime, { force: true });
}
Expand All @@ -87,6 +87,7 @@
};

export const expandServiceView = (rowIndex = 0) => {
cy.get('[data-test-subj="globalLoadingIndicator"]').should('not.exist');//Replaces wait
cy.get('*[data-test-subj^="service-flyout-action-btntrace_service"]').eq(rowIndex).click();
cy.get('[data-test-subj="ActionContextMenu"]').click();
cy.get('[data-test-subj="viewServiceButton"]').click();
Expand Down
1 change: 1 addition & 0 deletions common/constants/trace_analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ 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 const TRACE_CUSTOM_MODE_DEFAULT_SETTING = 'observability:traceAnalyticsCustomModeDefault';

export enum TRACE_TABLE_TITLES {
all_spans = 'All Spans',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Helper functions renders benchmark 1`] = `
exports[`Trace analytics helper functions renders benchmark 1`] = `
<EuiText
size="s"
style={
Expand All @@ -22,7 +22,7 @@ exports[`Helper functions renders benchmark 1`] = `
</EuiText>
`;

exports[`Helper functions renders benchmark 2`] = `
exports[`Trace analytics helper functions renders benchmark 2`] = `
<EuiText
size="s"
style={
Expand All @@ -44,7 +44,7 @@ exports[`Helper functions renders benchmark 2`] = `
</EuiText>
`;

exports[`Helper functions renders benchmark 3`] = `
exports[`Trace analytics helper functions renders benchmark 3`] = `
<EuiText
size="s"
style={
Expand All @@ -66,7 +66,7 @@ exports[`Helper functions renders benchmark 3`] = `
</EuiText>
`;

exports[`Helper functions renders no match and missing configuration messages 1`] = `
exports[`Trace analytics helper functions renders no match and missing configuration messages 1`] = `
<Fragment>
<EuiSpacer
size="s"
Expand All @@ -91,7 +91,7 @@ exports[`Helper functions renders no match and missing configuration messages 1`
</Fragment>
`;

exports[`Helper functions renders no match and missing configuration messages 2`] = `
exports[`Trace analytics helper functions renders no match and missing configuration messages 2`] = `
<Fragment>
<EuiEmptyPrompt
actions={
Expand Down Expand Up @@ -120,7 +120,7 @@ exports[`Helper functions renders no match and missing configuration messages 2`
</Fragment>
`;

exports[`Helper functions renders panel title 1`] = `
exports[`Trace analytics helper functions renders panel title 1`] = `
<EuiText
size="m"
>
Expand All @@ -137,7 +137,7 @@ exports[`Helper functions renders panel title 1`] = `
</EuiText>
`;

exports[`Helper functions renders panel title 2`] = `
exports[`Trace analytics helper functions renders panel title 2`] = `
<EuiText
size="m"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
getPercentileFilter,
getServiceMapGraph,
getServiceMapScaleColor,
getServiceMapTargetResources,
getTimestampPrecision,
milliToNanoSec,
minFixedInterval,
Expand All @@ -33,7 +32,7 @@ import {
renderBenchmark,
} from '../helper_functions';

describe('Helper functions', () => {
describe('Trace analytics helper functions', () => {
configure({ adapter: new Adapter() });

it('renders panel title', () => {
Expand Down Expand Up @@ -83,22 +82,14 @@ describe('Helper functions', () => {
});

it('returns service map graph', () => {
const serviceMapGraph = getServiceMapGraph(TEST_SERVICE_MAP, 'latency', [
0,
50,
100,
150,
200,
250,
]);
const serviceMapGraph = getServiceMapGraph({
map: TEST_SERVICE_MAP,
idSelected: 'latency',
ticks: [0, 50, 100, 150, 200, 250],
});
expect(serviceMapGraph).toEqual(TEST_SERVICE_MAP_GRAPH);
});

it('returns target resources by service name', () => {
const targetResources = getServiceMapTargetResources(TEST_SERVICE_MAP, 'order');
expect(targetResources).toEqual(['clear_order', 'update_order', 'get_order', 'pay_order']);
});

it('calculates ticks', () => {
const ticks = calculateTicks(500, 200);
const ticks2 = calculateTicks(0, 200, 10);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import {
EuiCallOut,
EuiCheckbox,
EuiCompressedFieldText,
EuiDescribedFormGroup,
EuiFlexGroup,
Expand All @@ -23,6 +24,7 @@
import {
TRACE_CUSTOM_SERVICE_INDEX_SETTING,
TRACE_CUSTOM_SPAN_INDEX_SETTING,
TRACE_CUSTOM_MODE_DEFAULT_SETTING,
} from '../../../../../common/constants/trace_analytics';
import { uiSettingsService } from '../../../../../common/utils';
import { useToast } from '../../../common/toast';
Expand All @@ -39,6 +41,7 @@
const { setToast } = useToast();
const [spanIndices, setSpanIndices] = useState('');
const [serviceIndices, setServiceIndices] = useState('');
const [customModeDefault, setCustomModeDefault] = useState(false);
const [isLoading, setIsLoading] = useState(false);

const onChangeSpanIndices = (e: { target: { value: React.SetStateAction<string> } }) => {
Expand All @@ -49,21 +52,27 @@
setServiceIndices(e.target.value);
};

const onToggleCustomModeDefault = (e: { target: { checked: boolean } }) => {
setCustomModeDefault(e.target.checked);
};

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

Check warning on line 63 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 () => {
const onSaveSettings = async () => {
try {
setIsLoading(true);
await uiSettingsService.set(TRACE_CUSTOM_SPAN_INDEX_SETTING, spanIndices);
await uiSettingsService.set(TRACE_CUSTOM_SERVICE_INDEX_SETTING, serviceIndices);
await uiSettingsService.set(TRACE_CUSTOM_MODE_DEFAULT_SETTING, customModeDefault);
setIsLoading(false);
setToast('Updated trace analytics sources successfully', 'success');
setToast('Updated trace analytics settings successfully', 'success');
} catch (error) {
console.error(error);
setToast('Failed to update trace analytics sources', 'danger');
setToast('Failed to update trace analytics settings', 'danger');
}
setIsLoading(false);
};
Expand Down Expand Up @@ -134,6 +143,23 @@
/>
</EuiFormRow>
</EuiDescribedFormGroup>
<EuiDescribedFormGroup
title={<h3>Set default mode</h3>}
description={
<Fragment>
Enable this to set &quot;Custom source&quot; as the default mode for trace analytics
</Fragment>
}
>
<EuiFormRow>
<EuiCheckbox
id="customModeDefault"
label="Enable custom source as default mode"
checked={customModeDefault}
onChange={onToggleCustomModeDefault}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
Expand All @@ -149,7 +175,7 @@
<EuiFlexItem grow={false}>
<EuiSmallButton
onClick={async () => {
await onSaveIndices();
await onSaveSettings();
setIsFlyoutVisible(false);
}}
fill
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,17 +208,22 @@
return { graph: { nodes: connectedNodes, edges: connectedEdges } };
}

// construct vis-js graph from ServiceObject
export function getServiceMapGraph(
map: ServiceObject,
idSelected: 'latency' | 'error_rate' | 'throughput',
ticks: number[],
currService?: string,
relatedServices?: string[],
filterByCurrService?: boolean
) {
if (!relatedServices) relatedServices = Object.keys(map);
interface ServiceMapParams {
map: ServiceObject;
idSelected: 'latency' | 'error_rate' | 'throughput';
ticks: number[];
currService?: string;
filterByCurrService?: boolean;
}

// construct vis-js graph from ServiceObject
export function getServiceMapGraph({
map,
idSelected,
ticks,
currService,
filterByCurrService,
}: ServiceMapParams) {
const nodes = Object.keys(map).map((service) => {
const value = map[service][idSelected];
let styleOptions;
Expand All @@ -229,14 +234,10 @@
borderWidth: 3,
color: {
border: '#4A4A4A',
background:
relatedServices!.indexOf(service) >= 0 ? `rgba(${color}, 1)` : `rgba(${color}, 0.2)`,
background: `rgba(${color}, 1)`,
},
font: {
color:
relatedServices!.indexOf(service) >= 0
? `rgba(72, 122, 180, 1)`
: `rgba(72, 122, 180, 0.2)`,
color: `rgba(72, 122, 180, 1)`,
},
};
} else {
Expand Down Expand Up @@ -285,10 +286,7 @@
edges.push({
from: map[service].id,
to: map[target].id,
color:
relatedServices!.indexOf(service) >= 0 && relatedServices!.indexOf(target) >= 0
? `rgba(${edgeColor}, 1)`
: `rgba(${edgeColor}, 0.2)`,
color: `rgba(${edgeColor}, 1)`,
});
});
});
Expand All @@ -299,14 +297,6 @@
return { graph: { nodes, edges } };
}

// returns flattened targetResource as an array for all traceGroups
export function getServiceMapTargetResources(map: ServiceObject, serviceName: string) {
return ([] as string[]).concat.apply(
[],
[...map[serviceName].traceGroups.map((traceGroup) => [...traceGroup.targetResource])]
);
}

export function calculateTicks(min: number, max: number, numTicks = 5): number[] {
if (min >= max) return calculateTicks(0, Math.max(1, max), numTicks);
min = Math.floor(min);
Expand Down Expand Up @@ -371,7 +361,7 @@
percentileMaps: Array<{ traceGroupName: string; durationFilter: { gte?: number; lte?: number } }>,
conditionString: string // >= 95th, < 95th
): FilterType => {
const DSL: any = {

Check warning on line 364 in public/components/trace_analytics/components/common/helper_functions.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
query: {
bool: {
must: [],
Expand Down Expand Up @@ -416,12 +406,12 @@
mode: TraceAnalyticsMode,
filters: FilterType[],
query: string,
startTime: any,

Check warning on line 409 in public/components/trace_analytics/components/common/helper_functions.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
endTime: any,

Check warning on line 410 in public/components/trace_analytics/components/common/helper_functions.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
page?: string,
appConfigs: FilterType[] = []
) => {
const DSL: any = {

Check warning on line 414 in public/components/trace_analytics/components/common/helper_functions.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
query: {
bool: {
must: [],
Expand Down Expand Up @@ -615,14 +605,22 @@
}
};

export const generateServiceUrl = (service: string, dataSourceId: string) => {
const url = `#/services?serviceId=${encodeURIComponent(service)}`;
export const generateServiceUrl = (
service: string,
dataSourceId: string,
mode?: TraceAnalyticsMode
): string => {
let url = `#/services?serviceId=${encodeURIComponent(service)}`;

if (dataSourceId && dataSourceId !== '') {
return `${url}&datasourceId=${encodeURIComponent(dataSourceId)}`;
url += `&datasourceId=${encodeURIComponent(dataSourceId)}`;
}

if (mode) {
url += `&mode=${encodeURIComponent(mode)}`;
}

return `${url}&datasourceId=`;
return url;
};

interface FullScreenWrapperProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

export interface ServiceObject {
[key: string]: {
average_latency: any;

Check warning on line 39 in public/components/trace_analytics/components/common/plots/service_map.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
serviceName: string;
id: number;
traceGroups: Array<{ traceGroup: string; targetResource: string[] }>;
Expand Down Expand Up @@ -91,7 +91,7 @@
const [invalid, setInvalid] = useState(false);
const [network, setNetwork] = useState(null);
const [ticks, setTicks] = useState<number[]>([]);
const [items, setItems] = useState<any>({});

Check warning on line 94 in public/components/trace_analytics/components/common/plots/service_map.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const [query, setQuery] = useState('');
const [isLoading, setIsLoading] = useState(true);
const [filterChange, setIsFilterChange] = useState(false);
Expand All @@ -113,7 +113,7 @@
];

const [selectedNodeDetails, setSelectedNodeDetails] = useState<ServiceNodeDetails | null>(null);
const [selectableValue, setSelectableValue] = useState<Array<EuiSuperSelectOption<any>>>([]);

Check warning on line 116 in public/components/trace_analytics/components/common/plots/service_map.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const [isPopoverOpen, setPopoverOpen] = useState(false);

// Memoize a boolean to determine if the focus bar should be disabled
Expand Down Expand Up @@ -296,28 +296,25 @@
if (focusedService !== null) {
removeFilter('serviceName', focusedService);
setItems(
getServiceMapGraph(
serviceMap,
getServiceMapGraph({
map: serviceMap,
idSelected,
ticks,
undefined,
undefined,
false // Show the entire graph without filtering
)
filterByCurrService: false,
})
);
setFocusedService(null);
setInvalid(false);
}
} else if (serviceMap[service]) {
if (focusedService !== service) {
const filteredGraph = getServiceMapGraph(
serviceMap,
const filteredGraph = getServiceMapGraph({
map: serviceMap,
idSelected,
ticks,
service,
serviceMap[service]?.relatedServices,
true // Enable filtering to focus on connected nodes
);
currService: service,
filterByCurrService: true,
});
setItems(filteredGraph);
setFocusedService(service);
}
Expand Down Expand Up @@ -369,14 +366,13 @@
// Adjust graph rendering logic to ensure related services are visible
const showRelatedServices = focusedService ? true : filterByCurrService;
setItems(
getServiceMapGraph(
serviceMap,
getServiceMapGraph({
map: serviceMap,
idSelected,
calculatedTicks,
focusedService ?? currService,
serviceMap[currService!]?.relatedServices,
showRelatedServices
)
ticks: calculatedTicks,
currService: focusedService ?? currService,
filterByCurrService: showRelatedServices,
})
);
}, [serviceMap, idSelected, focusedService, filterByCurrService]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ describe('Services table component', () => {

it('redirects to the correct URL when the service link is clicked', () => {
const mockDataSourceId = 'mock-data-source-id';
const mockMode = 'data_prepper';
const tableItems = [
{
name: 'checkoutservice',
Expand Down Expand Up @@ -161,7 +162,7 @@ describe('Services table component', () => {

serviceLink.simulate('click');

const expectedUrl = generateServiceUrl('checkoutservice', mockDataSourceId);
const expectedUrl = generateServiceUrl('checkoutservice', mockDataSourceId, mockMode);
expect(window.location.href).toBe(expectedUrl);

window.location = originalLocation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export function ServiceView(props: ServiceViewProps) {
}, [props.serviceName, props.setDataSourceMenuSelectable]);

const redirectToServicePage = (service: string) => {
window.location.href = generateServiceUrl(service, props.dataSourceMDSId[0].id);
window.location.href = generateServiceUrl(service, props.dataSourceMDSId[0].id, mode);
};

const onClickConnectedService = (service: string) => {
Expand Down
Loading
Loading