diff --git a/.cypress/utils/constants.js b/.cypress/utils/constants.js index c1e211d441..e790f6378e 100644 --- a/.cypress/utils/constants.js +++ b/.cypress/utils/constants.js @@ -87,6 +87,7 @@ export const setTimeFilter = (setEndTime = false, refresh = true) => { }; 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(); diff --git a/common/constants/trace_analytics.ts b/common/constants/trace_analytics.ts index daf04a6fa2..5574bf2bea 100644 --- a/common/constants/trace_analytics.ts +++ b/common/constants/trace_analytics.ts @@ -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', diff --git a/public/components/trace_analytics/components/common/__tests__/__snapshots__/helper_functions.test.tsx.snap b/public/components/trace_analytics/components/common/__tests__/__snapshots__/helper_functions.test.tsx.snap index ea02ed8c9a..33f8b8d4e2 100644 --- a/public/components/trace_analytics/components/common/__tests__/__snapshots__/helper_functions.test.tsx.snap +++ b/public/components/trace_analytics/components/common/__tests__/__snapshots__/helper_functions.test.tsx.snap @@ -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`] = ` `; -exports[`Helper functions renders benchmark 2`] = ` +exports[`Trace analytics helper functions renders benchmark 2`] = ` `; -exports[`Helper functions renders benchmark 3`] = ` +exports[`Trace analytics helper functions renders benchmark 3`] = ` `; -exports[`Helper functions renders no match and missing configuration messages 1`] = ` +exports[`Trace analytics helper functions renders no match and missing configuration messages 1`] = ` `; -exports[`Helper functions renders no match and missing configuration messages 2`] = ` +exports[`Trace analytics helper functions renders no match and missing configuration messages 2`] = ` `; -exports[`Helper functions renders panel title 1`] = ` +exports[`Trace analytics helper functions renders panel title 1`] = ` @@ -137,7 +137,7 @@ exports[`Helper functions renders panel title 1`] = ` `; -exports[`Helper functions renders panel title 2`] = ` +exports[`Trace analytics helper functions renders panel title 2`] = ` diff --git a/public/components/trace_analytics/components/common/__tests__/helper_functions.test.tsx b/public/components/trace_analytics/components/common/__tests__/helper_functions.test.tsx index 217c3b8f47..5369324852 100644 --- a/public/components/trace_analytics/components/common/__tests__/helper_functions.test.tsx +++ b/public/components/trace_analytics/components/common/__tests__/helper_functions.test.tsx @@ -22,7 +22,6 @@ import { getPercentileFilter, getServiceMapGraph, getServiceMapScaleColor, - getServiceMapTargetResources, getTimestampPrecision, milliToNanoSec, minFixedInterval, @@ -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', () => { @@ -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); diff --git a/public/components/trace_analytics/components/common/custom_index_flyout.tsx b/public/components/trace_analytics/components/common/custom_index_flyout.tsx index b616b9db49..926b0b225a 100644 --- a/public/components/trace_analytics/components/common/custom_index_flyout.tsx +++ b/public/components/trace_analytics/components/common/custom_index_flyout.tsx @@ -5,6 +5,7 @@ import { EuiCallOut, + EuiCheckbox, EuiCompressedFieldText, EuiDescribedFormGroup, EuiFlexGroup, @@ -23,6 +24,7 @@ import React, { Fragment, useEffect, useState } from 'react'; 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'; @@ -39,6 +41,7 @@ export const CustomIndexFlyout = ({ 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 } }) => { @@ -49,21 +52,27 @@ export const CustomIndexFlyout = ({ 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]); - 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); }; @@ -134,6 +143,23 @@ export const CustomIndexFlyout = ({ /> + Set default mode} + description={ + + Enable this to set "Custom source" as the default mode for trace analytics + + } + > + + + + @@ -149,7 +175,7 @@ export const CustomIndexFlyout = ({ { - await onSaveIndices(); + await onSaveSettings(); setIsFlyoutVisible(false); }} fill diff --git a/public/components/trace_analytics/components/common/helper_functions.tsx b/public/components/trace_analytics/components/common/helper_functions.tsx index 74a3676653..8a6c8e99aa 100644 --- a/public/components/trace_analytics/components/common/helper_functions.tsx +++ b/public/components/trace_analytics/components/common/helper_functions.tsx @@ -208,17 +208,22 @@ function filterGraphBySelectedNode( 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; @@ -229,14 +234,10 @@ export function getServiceMapGraph( 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 { @@ -285,10 +286,7 @@ export function getServiceMapGraph( 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)`, }); }); }); @@ -299,14 +297,6 @@ export function getServiceMapGraph( 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); @@ -615,14 +605,22 @@ export const getServiceIndices = (mode: TraceAnalyticsMode) => { } }; -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 { diff --git a/public/components/trace_analytics/components/common/plots/service_map.tsx b/public/components/trace_analytics/components/common/plots/service_map.tsx index f75f1e8403..a70cfd899d 100644 --- a/public/components/trace_analytics/components/common/plots/service_map.tsx +++ b/public/components/trace_analytics/components/common/plots/service_map.tsx @@ -296,28 +296,25 @@ export function ServiceMap({ 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); } @@ -369,14 +366,13 @@ export function ServiceMap({ // 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]); diff --git a/public/components/trace_analytics/components/services/__tests__/services_table.test.tsx b/public/components/trace_analytics/components/services/__tests__/services_table.test.tsx index b35fe81c30..b50d7b07c1 100644 --- a/public/components/trace_analytics/components/services/__tests__/services_table.test.tsx +++ b/public/components/trace_analytics/components/services/__tests__/services_table.test.tsx @@ -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', @@ -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; diff --git a/public/components/trace_analytics/components/services/service_view.tsx b/public/components/trace_analytics/components/services/service_view.tsx index 2ca6d2333b..7769996d87 100644 --- a/public/components/trace_analytics/components/services/service_view.tsx +++ b/public/components/trace_analytics/components/services/service_view.tsx @@ -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) => { diff --git a/public/components/trace_analytics/components/services/services_table.tsx b/public/components/trace_analytics/components/services/services_table.tsx index 71da21de57..b4bc486d4a 100644 --- a/public/components/trace_analytics/components/services/services_table.tsx +++ b/public/components/trace_analytics/components/services/services_table.tsx @@ -81,7 +81,7 @@ export function ServicesTable(props: ServicesTableProps) { if (page === 'app') { setCurrentSelectedService(serviceName); } else { - window.location.href = generateServiceUrl(serviceName, dataSourceMDSId[0].id); + window.location.href = generateServiceUrl(serviceName, dataSourceMDSId[0].id, props.mode); } }; diff --git a/public/components/trace_analytics/components/traces/trace_table_helpers.tsx b/public/components/trace_analytics/components/traces/trace_table_helpers.tsx index 6d506714ed..a4ff97d6ad 100644 --- a/public/components/trace_analytics/components/traces/trace_table_helpers.tsx +++ b/public/components/trace_analytics/components/traces/trace_table_helpers.tsx @@ -115,6 +115,18 @@ export const getTableColumns = ( 'No' ); + const renderStatusCodeErrorsField = (item: number) => + item === undefined || item === null ? ( + '-' + ) : item === 2 ? ( + // 2 means Error, 1 means OK, 0 means Unset + + Yes + + ) : ( + 'No' + ); + const renderDurationField = (item: number) => item ? {round(nanoToMilliSec(Math.max(0, item)), 2)} : '-'; @@ -166,7 +178,7 @@ export const getTableColumns = ( name: 'Errors', align: 'right', sortable: true, - render: renderErrorsField, + render: renderStatusCodeErrorsField, }, { field: 'endTime', diff --git a/public/components/trace_analytics/home.tsx b/public/components/trace_analytics/home.tsx index 3d3e7ed393..3ddf1268bb 100644 --- a/public/components/trace_analytics/home.tsx +++ b/public/components/trace_analytics/home.tsx @@ -23,7 +23,10 @@ import { } from '../../../../../src/plugins/data_source_management/public'; import { DataSourceAttributes } from '../../../../../src/plugins/data_source_management/public/types'; import { observabilityTracesNewNavID } from '../../../common/constants/shared'; -import { TRACE_TABLE_TYPE_KEY } from '../../../common/constants/trace_analytics'; +import { + TRACE_CUSTOM_MODE_DEFAULT_SETTING, + TRACE_TABLE_TYPE_KEY, +} from '../../../common/constants/trace_analytics'; import { TraceAnalyticsMode, TraceQueryMode } from '../../../common/types/trace_analytics'; import { coreRefs } from '../../framework/core_refs'; import { FilterType } from './components/common/filters/filters'; @@ -38,6 +41,7 @@ import { handleJaegerIndicesExistRequest, } from './requests/request_handler'; import { TraceSideBar } from './trace_side_nav'; +import { uiSettingsService } from '../../../common/utils'; const newNavigation = coreRefs.chrome?.navGroup.getNavGroupEnabled(); @@ -259,6 +263,40 @@ export const Home = (props: HomeProps) => { } }, [jaegerIndicesExist, dataPrepperIndicesExist]); + const updateUrlWithMode = (traceMode: string) => { + const urlParts = window.location.href.split('?'); + const queryParams = new URLSearchParams(urlParts[1]?.split('#')[0] || ''); + queryParams.set('mode', traceMode); + return `${urlParts[0]}?${queryParams.toString()}${ + urlParts[1]?.includes('#') ? `#${urlParts[1].split('#')[1]}` : '' + }`; + }; + + useEffect(() => { + const urlParts = window.location.href.split('?'); + const queryParams = + urlParts.length > 1 ? new URLSearchParams(urlParts[1].split('#')[0]) : new URLSearchParams(); + + const urlMode = queryParams.get('mode'); + const isCustomModeEnabled = uiSettingsService.get(TRACE_CUSTOM_MODE_DEFAULT_SETTING) || false; + + if (!urlMode && isCustomModeEnabled) { + const newUrl = updateUrlWithMode('custom_data_prepper'); + if (window.location.href !== newUrl) { + window.history.replaceState(null, '', newUrl); + + setMode('custom_data_prepper'); + sessionStorage.setItem('TraceAnalyticsMode', 'custom_data_prepper'); + } + } else if (isValidTraceAnalyticsMode(urlMode)) { + // Use the existing mode if valid + if (sessionStorage.getItem('TraceAnalyticsMode') !== urlMode) { + setMode(urlMode as TraceAnalyticsMode); + sessionStorage.setItem('TraceAnalyticsMode', urlMode); + } + } + }, []); + useEffect(() => { if (mode === 'data_prepper' || mode === 'custom_data_prepper') fetchAttributesFields(); }, [mode, dataSourceMDSId]); @@ -295,12 +333,20 @@ export const Home = (props: HomeProps) => { const traceColumnAction = () => { const tracesPath = '#/traces'; + const dataSourceId = dataSourceMDSId[0]?.id || ''; + const urlParts = window.location.href.split('?'); + const queryParams = + urlParts.length > 1 ? new URLSearchParams(urlParts[1]) : new URLSearchParams(); + + const modeParam = queryParams.get('mode') || ''; + const modeQuery = modeParam ? `&mode=${encodeURIComponent(modeParam)}` : ''; + if (newNavigation) { coreRefs.application?.navigateToApp(observabilityTracesNewNavID, { - path: tracesPath + '?datasourceId=' + dataSourceMDSId[0].id, + path: `${tracesPath}?datasourceId=${encodeURIComponent(dataSourceId)}${modeQuery}`, }); } else { - location.assign(tracesPath + '?datasourceId=' + dataSourceMDSId[0].id); + location.assign(`${tracesPath}?datasourceId=${encodeURIComponent(dataSourceId)}${modeQuery}`); } setTracesTableMode('traces'); diff --git a/public/components/trace_analytics/requests/queries/services_queries.ts b/public/components/trace_analytics/requests/queries/services_queries.ts index ab118dae74..6507ea2d7b 100644 --- a/public/components/trace_analytics/requests/queries/services_queries.ts +++ b/public/components/trace_analytics/requests/queries/services_queries.ts @@ -8,10 +8,7 @@ import { SERVICE_MAP_MAX_NODES, } from '../../../../../common/constants/trace_analytics'; import { TraceAnalyticsMode } from '../../../../../common/types/trace_analytics'; -import { - getServiceIndices, - getServiceMapTargetResources, -} from '../../components/common/helper_functions'; +import { getServiceIndices } from '../../components/common/helper_functions'; import { ServiceObject } from '../../components/common/plots/service_map'; export const getServicesQuery = ( @@ -111,12 +108,6 @@ export const getRelatedServicesQuery = (serviceName: string) => { size: 10000, }, aggs: { - all_services: { - terms: { - field: 'serviceName', - size: 10000, - }, - }, service: { filter: { bool: { @@ -157,19 +148,11 @@ export const getServiceNodesQuery = (mode: TraceAnalyticsMode) => { size: SERVICE_MAP_MAX_NODES, }, aggs: { - trace_group: { + target_resource: { terms: { - field: 'traceGroupName', + field: 'target.resource', size: SERVICE_MAP_MAX_EDGES, }, - aggs: { - target_resource: { - terms: { - field: 'target.resource', - size: SERVICE_MAP_MAX_EDGES, - }, - }, - }, }, }, }, @@ -225,24 +208,9 @@ export const getServiceMetricsQuery = ( map: ServiceObject, mode: TraceAnalyticsMode ) => { - const traceGroupFilter = new Set( - DSL?.query?.bool.must - .filter((must: any) => must.term?.['traceGroup']) - .map((must: any) => must.term.traceGroup) || [] + const targetResource = [].concat( + ...Object.keys(map).map((service) => map[service].targetResources) ); - - const targetResource = - traceGroupFilter.size > 0 - ? [].concat( - ...[].concat( - ...serviceNames.map((service) => - map[service].traceGroups - .filter((traceGroup) => traceGroupFilter.has(traceGroup.traceGroup)) - .map((traceGroup) => traceGroup.targetResource) - ) - ) - ) - : [].concat(...Object.keys(map).map((service) => getServiceMapTargetResources(map, service))); const jaegerQuery: any = { size: 0, query: { diff --git a/public/components/trace_analytics/requests/services_request_handler.ts b/public/components/trace_analytics/requests/services_request_handler.ts index 0995b7e0b4..7aa8486063 100644 --- a/public/components/trace_analytics/requests/services_request_handler.ts +++ b/public/components/trace_analytics/requests/services_request_handler.ts @@ -112,10 +112,7 @@ export const handleServiceMapRequest = async ( (map[bucket.key] = { serviceName: bucket.key, id: id++, - traceGroups: bucket.trace_group.buckets.map((traceGroup: any) => ({ - traceGroup: traceGroup.key, - targetResource: traceGroup.target_resource.buckets.map((res: any) => res.key), - })), + targetResources: bucket.target_resource.buckets.map((res: any) => res.key), targetServices: [], destServices: [], }) @@ -149,10 +146,6 @@ export const handleServiceMapRequest = async ( ) .catch((error) => { console.error('Error retrieving target edges:', error); - coreRefs.core?.notifications.toasts.addError(error, { - title: 'Failed to retrieve target edges', - toastLifeTimeMs: 10000, - }); }); await handleDslRequest( @@ -181,10 +174,6 @@ export const handleServiceMapRequest = async ( ) .catch((error) => { console.error('Error retrieving destination edges:', error); - coreRefs.core?.notifications.toasts.addError(error, { - title: 'Failed to retrieve destination edges', - toastLifeTimeMs: 10000, - }); }); if (includeMetrics) { @@ -205,10 +194,6 @@ export const handleServiceMapRequest = async ( }); } catch (error) { console.error('Error retrieving service metrics:', error); - coreRefs.core?.notifications.toasts.addError(error, { - title: 'Failed to retrieve service metrics', - toastLifeTimeMs: 10000, - }); } } @@ -217,21 +202,22 @@ export const handleServiceMapRequest = async ( .then((response) => response.aggregations.traces.buckets.filter((bucket: any) => bucket.service.doc_count > 0) ) - .then((traces) => { + .then((filteredBuckets) => { const maxNumServices = Object.keys(map).length; const relatedServices = new Set(); - for (let i = 0; i < traces.length; i++) { - traces[i].all_services.buckets.map((bucket: any) => relatedServices.add(bucket.key)); + + // Iterate through the filtered trace buckets + for (let i = 0; i < filteredBuckets.length; i++) { + // Add the current service name to the related services + relatedServices.add(filteredBuckets[i].key); if (relatedServices.size === maxNumServices) break; } + + // Add the related services to the map for the current service map[currService].relatedServices = [...relatedServices]; }) .catch((error) => { console.error('Error retrieving related services:', error); - coreRefs.core?.notifications.toasts.addError(error, { - title: 'Failed to retrieve related services', - toastLifeTimeMs: 10000, - }); }); } diff --git a/server/plugin_helper/register_settings.ts b/server/plugin_helper/register_settings.ts index 771404b659..d07a6f300e 100644 --- a/server/plugin_helper/register_settings.ts +++ b/server/plugin_helper/register_settings.ts @@ -3,9 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { i18n } from '@osd/i18n'; import { schema } from '@osd/config-schema'; import { UiSettingsServiceSetup } from '../../../../src/core/server/ui_settings'; import { + TRACE_CUSTOM_MODE_DEFAULT_SETTING, TRACE_CUSTOM_SERVICE_INDEX_SETTING, TRACE_CUSTOM_SPAN_INDEX_SETTING, } from '../../common/constants/trace_analytics'; @@ -13,23 +15,46 @@ import { export const registerObservabilityUISettings = (uiSettings: UiSettingsServiceSetup) => { uiSettings.register({ [TRACE_CUSTOM_SPAN_INDEX_SETTING]: { - name: 'Trace analytics custom span indices', + name: i18n.translate('observability.traceAnalyticsCustomSpanIndices.name', { + defaultMessage: 'Trace analytics custom span indices', + }), value: '', category: ['Observability'], - description: - 'Experimental feature: Configure custom span indices that adhere to data prepper schema, to be used by the trace analytics plugin', + description: i18n.translate('observability.traceAnalyticsCustomSpanIndices.description', { + defaultMessage: + 'Experimental feature: Configure custom span indices that adhere to data prepper schema, to be used by the trace analytics plugin', + }), schema: schema.string(), }, }); uiSettings.register({ [TRACE_CUSTOM_SERVICE_INDEX_SETTING]: { - name: 'Trace analytics custom service indices', + name: i18n.translate('observability.traceAnalyticsCustomServiceIndices.name', { + defaultMessage: 'Trace analytics custom service indices', + }), value: '', category: ['Observability'], - description: - 'Experimental feature: Configure custom service indices that adhere to data prepper schema, to be used by the trace analytics plugin', + description: i18n.translate('observability.traceAnalyticsCustomServiceIndices.description', { + defaultMessage: + 'Experimental feature: Configure custom service indices that adhere to data prepper schema, to be used by the trace analytics plugin', + }), schema: schema.string(), }, }); + + uiSettings.register({ + [TRACE_CUSTOM_MODE_DEFAULT_SETTING]: { + name: i18n.translate('observability.traceAnalyticsCustomModeDefault.name', { + defaultMessage: 'Trace analytics custom mode default', + }), + value: false, + category: ['Observability'], + description: i18n.translate('observability.traceAnalyticsCustomModeDefault.description', { + defaultMessage: + 'Experimental feature: Enable this to default to "custom_data_prepper" mode in the trace analytics plugin', + }), + schema: schema.boolean(), + }, + }); };