From d56ea8a137d98135c680d421ae8aded27cf9173c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:28:03 +0100 Subject: [PATCH] [APM][ECO] Add log charts to APM service overview (#191183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes https://github.com/elastic/kibana/issues/190526 ### When EEM is enabled (dynamically loads APM and/or Logs overviews): https://github.com/user-attachments/assets/d645940b-f0fe-42c9-9b3e-d8de4ea23d45 ### When EEM is disabled (fallback to standard APM overview page): _In this example `synth-python` simulates an APM service that hasn't been processed by EEM yet and that's why it's not available in the video above._ _`synth_go_logs` is not visible here because it only has logs_ https://github.com/user-attachments/assets/3fc351c6-5ca2-4a07-b00b-5e64bece18d3 ## Acceptance criteria | Status | Name | Description | | ---- | ---- | ---- | |✅| **There must be a single service view template** | The view will adapt based on the available data - there are no 'logs only' or 'APM' service views | |✅| **When a service is instrumented with APM, we will show the log rate and log error % charts at the bottom of the overview** | These will match any logs with a `logs-*` index pattern | |☑️ part of it.| **When a service only has logs, the overview tab will have a dismissible promo visualising a service view with APM** | This will link to APM documentation, have a CTA to 'Add APM' and also a 'Try it!' button which points to https://ela.st/demo-service-view | --------- Co-authored-by: Kate Patticha --- .../entities/charts/log_error_rate_chart.tsx | 2 +- .../app/entities/charts/log_rate_chart.tsx | 3 +- .../entities/logs/logs_service_overview.tsx | 158 -------------- .../error_group_list.stories.tsx | 1 + .../app/service_dashboards/index.tsx | 3 +- .../components/app/service_logs/index.tsx | 2 +- .../service_overview/apm_overview/index.tsx | 194 ++++++++++++++++++ .../components/app/service_overview/index.tsx | 191 +++-------------- .../service_overview/logs_overview/index.tsx | 48 +++++ .../service_overview.stories.tsx | 5 + .../service_overview.test.tsx | 2 +- .../index.tsx} | 20 +- .../get_throughput_screen_context.ts | 6 +- .../index.tsx} | 32 +-- .../components/routing/apm_route_config.tsx | 2 - .../entities/logs_service_details/index.tsx | 145 ------------- ...redirect_to_default_service_route_view.tsx | 11 - .../analyze_data_button.stories.tsx | 1 + .../entities/logs_service_template/index.tsx | 179 ---------------- .../latency_chart/latency_chart.stories.tsx | 1 + .../shared/is_route_with_time_range.ts | 1 - .../shared/links/apm/service_link/index.tsx | 7 +- .../apm_plugin/mock_apm_plugin_storybook.tsx | 7 + .../apm_service/apm_service_context.tsx | 24 ++- .../use_service_entity_summary_fetcher.ts | 40 ++++ .../service_anomaly_timeseries_context.tsx | 6 +- 26 files changed, 375 insertions(+), 716 deletions(-) delete mode 100644 x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx create mode 100644 x-pack/plugins/observability_solution/apm/public/components/app/service_overview/apm_overview/index.tsx create mode 100644 x-pack/plugins/observability_solution/apm/public/components/app/service_overview/logs_overview/index.tsx rename x-pack/plugins/observability_solution/apm/public/components/app/service_overview/{service_overview_instances_chart_and_table.tsx => service_overview_instances_chart_and_table/index.tsx} (88%) rename x-pack/plugins/observability_solution/apm/public/components/app/service_overview/{ => service_overview_throughput_chart}/get_throughput_screen_context.ts (87%) rename x-pack/plugins/observability_solution/apm/public/components/app/service_overview/{service_overview_throughput_chart.tsx => service_overview_throughput_chart/index.tsx} (77%) delete mode 100644 x-pack/plugins/observability_solution/apm/public/components/routing/entities/logs_service_details/index.tsx delete mode 100644 x-pack/plugins/observability_solution/apm/public/components/routing/templates/entities/logs_service_template/index.tsx create mode 100644 x-pack/plugins/observability_solution/apm/public/context/apm_service/use_service_entity_summary_fetcher.ts diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_error_rate_chart.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_error_rate_chart.tsx index 9493d3503a5dd3..68b41a6542a1ad 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_error_rate_chart.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_error_rate_chart.tsx @@ -35,7 +35,7 @@ export function LogErrorRateChart({ height }: { height: number }) { const { query: { rangeFrom, rangeTo, environment, kuery }, path: { serviceName }, - } = useApmParams('/logs-services/{serviceName}'); + } = useApmParams('/services/{serviceName}'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const { data = INITIAL_STATE, status } = useFetcher( diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_rate_chart.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_rate_chart.tsx index 999acfccfc2c3a..5a83349119d0c0 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_rate_chart.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/entities/charts/log_rate_chart.tsx @@ -35,8 +35,7 @@ export function LogRateChart({ height }: { height: number }) { const { query: { rangeFrom, rangeTo, environment, kuery }, path: { serviceName }, - } = useApmParams('/logs-services/{serviceName}'); - + } = useApmParams('/services/{serviceName}'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const { data = INITIAL_STATE, status } = useFetcher( diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx deleted file mode 100644 index c89487b527fbe3..00000000000000 --- a/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - EuiCallOut, - EuiFlexGroup, - EuiFlexGroupProps, - EuiFlexItem, - EuiLink, - EuiLoadingSpinner, - EuiSpacer, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import React from 'react'; -import { AnnotationsContextProvider } from '../../../../context/annotations/annotations_context'; -import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; -import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context'; -import { useApmParams } from '../../../../hooks/use_apm_params'; -import { useBreakpoints } from '../../../../hooks/use_breakpoints'; -import { useTimeRange } from '../../../../hooks/use_time_range'; -import { LogErrorRateChart } from '../charts/log_error_rate_chart'; -import { LogRateChart } from '../charts/log_rate_chart'; -import { AddAPMCallOut } from './add_apm_callout'; -import { useLocalStorage } from '../../../../hooks/use_local_storage'; -import { isPending, useFetcher } from '../../../../hooks/use_fetcher'; -/** - * The height a chart should be if it's next to a table with 5 rows and a title. - * Add the height of the pagination row. - */ - -const chartHeight = 400; - -export function LogsServiceOverview() { - const { serviceName } = useApmServiceContext(); - const [isLogsApmCalloutEnabled, setIsLogsApmCalloutEnabled] = useLocalStorage( - 'apm.isLogsApmCalloutEnabled', - true - ); - - const { - query: { environment, rangeFrom, rangeTo }, - } = useApmParams('/logs-services/{serviceName}/overview'); - - const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - - const { data, status } = useFetcher( - (callAPI) => { - return callAPI('GET /internal/apm/entities/services/{serviceName}/summary', { - params: { path: { serviceName }, query: { end, environment, start } }, - }); - }, - [end, environment, serviceName, start] - ); - - const { isLarge } = useBreakpoints(); - const isSingleColumn = isLarge; - - const rowDirection: EuiFlexGroupProps['direction'] = isSingleColumn ? 'column' : 'row'; - - if (isPending(status)) { - return ( -
- -
- ); - } - - return ( - - - {isLogsApmCalloutEnabled ? ( - <> - { - setIsLogsApmCalloutEnabled(false); - }} - /> - - - ) : null} - {data?.entity?.hasLogMetrics === false ? ( - <> - - - {i18n.translate('xpack.apm.logsServiceOverview.logLevelLink', { - defaultMessage: 'log.level', - })} - - ), - learnMoreLink: ( - - {i18n.translate('xpack.apm.logsServiceOverview.learnMoreLink', { - defaultMessage: 'Learn more', - })} - - ), - }} - /> - - - - ) : null} - - - - - - - - - - - - - - - - ); -} diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx index d1183c91cb3e41..6cdb74ba1535c5 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx @@ -94,6 +94,7 @@ const stories: Meta = { transactionTypeStatus: FETCH_STATUS.SUCCESS, transactionTypes: ['request'], serviceAgentStatus: FETCH_STATUS.SUCCESS, + serviceEntitySummaryStatus: FETCH_STATUS.SUCCESS, }} > diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx index 458a2e647cc2b2..1b299182debab1 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx @@ -51,8 +51,7 @@ export function ServiceDashboards({ checkForEntities = false }: { checkForEntiti query: { environment, kuery, rangeFrom, rangeTo, dashboardId }, } = useAnyOfApmParams( '/services/{serviceName}/dashboards', - '/mobile-services/{serviceName}/dashboards', - '/logs-services/{serviceName}/dashboards' + '/mobile-services/{serviceName}/dashboards' ); const [dashboard, setDashboard] = useState(); const [serviceDashboards, setServiceDashboards] = useState([]); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_logs/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_logs/index.tsx index 90f31e29b5960b..4df52758ceda32 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_logs/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_logs/index.tsx @@ -22,7 +22,7 @@ export function ServiceLogs() { const { query: { environment, kuery, rangeFrom, rangeTo }, - } = useAnyOfApmParams('/services/{serviceName}/logs', '/logs-services/{serviceName}/logs'); + } = useAnyOfApmParams('/services/{serviceName}/logs'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/apm_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/apm_overview/index.tsx new file mode 100644 index 00000000000000..7995402eb29a9d --- /dev/null +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/apm_overview/index.tsx @@ -0,0 +1,194 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + EuiFlexGroup, + EuiFlexGroupProps, + EuiFlexItem, + EuiLink, + EuiPanel, + EuiSpacer, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { chartHeight } from '..'; +import { AgentName } from '../../../../../typings/es_schemas/ui/fields/agent'; +import { + isOpenTelemetryAgentName, + isRumAgentName, + isServerlessAgentName, +} from '../../../../../common/agent_name'; +import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; +import { useApmParams } from '../../../../hooks/use_apm_params'; +import { useApmRouter } from '../../../../hooks/use_apm_router'; +import { useBreakpoints } from '../../../../hooks/use_breakpoints'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { AggregatedTransactionsBadge } from '../../../shared/aggregated_transactions_badge'; +import { FailedTransactionRateChart } from '../../../shared/charts/failed_transaction_rate_chart'; +import { LatencyChart } from '../../../shared/charts/latency_chart'; +import { TransactionBreakdownChart } from '../../../shared/charts/transaction_breakdown_chart'; +import { TransactionColdstartRateChart } from '../../../shared/charts/transaction_coldstart_rate_chart'; +import { TransactionsTable } from '../../../shared/transactions_table'; +import { ServiceOverviewDependenciesTable } from '../service_overview_dependencies_table'; +import { ServiceOverviewErrorsTable } from '../service_overview_errors_table'; +import { ServiceOverviewInstancesChartAndTable } from '../service_overview_instances_chart_and_table'; +import { ServiceOverviewThroughputChart } from '../service_overview_throughput_chart'; +import { SloCallout } from '../../../shared/slo_callout'; +import { useLocalStorage } from '../../../../hooks/use_local_storage'; + +const latencyChartHeight = 200; + +export function ApmOverview() { + const router = useApmRouter(); + const { serviceName, fallbackToTransactions, agentName, serverlessType } = useApmServiceContext(); + const { + query, + query: { kuery, environment, rangeFrom, rangeTo, transactionType }, + } = useApmParams('/services/{serviceName}/overview'); + + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + + const isRumAgent = isRumAgentName(agentName); + const isOpenTelemetryAgent = isOpenTelemetryAgentName(agentName as AgentName); + const isServerless = isServerlessAgentName(serverlessType); + + // The default EuiFlexGroup breaks at 768, but we want to break at 1200, so we + // observe the window width and set the flex directions of rows accordingly + const { isLarge } = useBreakpoints(); + const isSingleColumn = isLarge; + + const nonLatencyChartHeight = isSingleColumn ? latencyChartHeight : chartHeight; + const rowDirection: EuiFlexGroupProps['direction'] = isSingleColumn ? 'column' : 'row'; + + const [sloCalloutDismissed, setSloCalloutDismissed] = useLocalStorage( + 'apm.sloCalloutDismissed', + false + ); + + return ( + <> + {!sloCalloutDismissed && ( + <> + { + setSloCalloutDismissed(true); + }} + serviceName={serviceName} + environment={environment} + transactionType={transactionType} + /> + + + )} + {fallbackToTransactions && ( + + + + )} + + + + + + + + + + + + + + + + + + + + {!isRumAgent && ( + + + + )} + + + + + + + + + + {isServerless ? ( + + + + ) : ( + !isOpenTelemetryAgent && ( + + + + ) + )} + {!isRumAgent && ( + + + + {i18n.translate('xpack.apm.serviceOverview.dependenciesTableTabLink', { + defaultMessage: 'View dependencies', + })} + + } + showSparkPlots={!isSingleColumn} + /> + + + )} + + + {!isRumAgent && !isServerless && ( + + + + + + )} + + ); +} diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx index 1f3005c2be44c8..f7b0920408be22 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/index.tsx @@ -5,43 +5,19 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useEffect } from 'react'; - -import { - EuiFlexGroup, - EuiFlexGroupProps, - EuiFlexItem, - EuiLink, - EuiPanel, - EuiSpacer, -} from '@elastic/eui'; -import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; -import { AgentName } from '../../../../typings/es_schemas/ui/fields/agent'; -import { - isOpenTelemetryAgentName, - isRumAgentName, - isServerlessAgentName, -} from '../../../../common/agent_name'; +import { SignalTypes } from '../../../../common/entities/types'; import { AnnotationsContextProvider } from '../../../context/annotations/annotations_context'; +import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context'; +import { useEntityManagerEnablementContext } from '../../../context/entity_manager_context/use_entity_manager_enablement_context'; import { useApmParams } from '../../../hooks/use_apm_params'; -import { useApmRouter } from '../../../hooks/use_apm_router'; -import { useBreakpoints } from '../../../hooks/use_breakpoints'; import { useTimeRange } from '../../../hooks/use_time_range'; -import { AggregatedTransactionsBadge } from '../../shared/aggregated_transactions_badge'; -import { FailedTransactionRateChart } from '../../shared/charts/failed_transaction_rate_chart'; -import { LatencyChart } from '../../shared/charts/latency_chart'; -import { TransactionBreakdownChart } from '../../shared/charts/transaction_breakdown_chart'; -import { TransactionColdstartRateChart } from '../../shared/charts/transaction_coldstart_rate_chart'; -import { TransactionsTable } from '../../shared/transactions_table'; -import { ServiceOverviewDependenciesTable } from './service_overview_dependencies_table'; -import { ServiceOverviewErrorsTable } from './service_overview_errors_table'; -import { ServiceOverviewInstancesChartAndTable } from './service_overview_instances_chart_and_table'; -import { ServiceOverviewThroughputChart } from './service_overview_throughput_chart'; -import { SloCallout } from '../../shared/slo_callout'; -import { useLocalStorage } from '../../../hooks/use_local_storage'; +import { isApmSignal, isLogsSignal } from '../../../utils/get_signal_type'; +import { ApmOverview } from './apm_overview'; +import { LogsOverview } from './logs_overview'; /** * The height a chart should be if it's next to a table with 5 rows and a title. * Add the height of the pagination row. @@ -49,8 +25,8 @@ import { useLocalStorage } from '../../../hooks/use_local_storage'; export const chartHeight = 288; export function ServiceOverview() { - const router = useApmRouter(); - const { serviceName, fallbackToTransactions, agentName, serverlessType } = useApmServiceContext(); + const { isEntityCentricExperienceViewEnabled } = useEntityManagerEnablementContext(); + const { serviceName, serviceEntitySummary } = useApmServiceContext(); const setScreenContext = useApmPluginContext().observabilityAIAssistant?.service.setScreenContext; @@ -68,35 +44,21 @@ export function ServiceOverview() { }, [setScreenContext, serviceName]); const { - query, - query: { kuery, environment, rangeFrom, rangeTo, transactionType }, + query: { environment, rangeFrom, rangeTo }, } = useApmParams('/services/{serviceName}/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const isRumAgent = isRumAgentName(agentName); - const isOpenTelemetryAgent = isOpenTelemetryAgentName(agentName as AgentName); - const isServerless = isServerlessAgentName(serverlessType); - const dependenciesLink = router.link('/services/{serviceName}/dependencies', { - path: { - serviceName, - }, - query, - }); + const hasLogsSignal = + serviceEntitySummary?.signalTypes && + isLogsSignal(serviceEntitySummary.signalTypes as SignalTypes[]); - // The default EuiFlexGroup breaks at 768, but we want to break at 1200, so we - // observe the window width and set the flex directions of rows accordingly - const { isLarge } = useBreakpoints(); - const isSingleColumn = isLarge; + const hasApmSignal = + serviceEntitySummary?.signalTypes && + isApmSignal(serviceEntitySummary.signalTypes as SignalTypes[]); - const latencyChartHeight = 200; - const nonLatencyChartHeight = isSingleColumn ? latencyChartHeight : chartHeight; - const rowDirection: EuiFlexGroupProps['direction'] = isSingleColumn ? 'column' : 'row'; - - const [sloCalloutDismissed, setSloCalloutDismissed] = useLocalStorage( - 'apm.sloCalloutDismissed', - false - ); + // Shows APM overview when entity has APM signal or when Entity centric is not enabled + const showApmOverview = isEntityCentricExperienceViewEnabled === false || hasApmSignal; return ( - {!sloCalloutDismissed && ( - { - setSloCalloutDismissed(true); - }} - serviceName={serviceName} - environment={environment} - transactionType={transactionType} - /> - )} - - {fallbackToTransactions && ( - - - - )} - - - - - - - - - - - - - - - - - - - - {!isRumAgent && ( - - - - )} - - - - - - - - - - {isServerless ? ( - - - - ) : ( - !isOpenTelemetryAgent && ( - - - - ) - )} - {!isRumAgent && ( - - - - {i18n.translate('xpack.apm.serviceOverview.dependenciesTableTabLink', { - defaultMessage: 'View dependencies', - })} - - } - showSparkPlots={!isSingleColumn} - /> - - - )} - - - {!isRumAgent && !isServerless && ( + {showApmOverview ? : null} + {/* Only shows Logs overview when entity has Logs signal */} + {hasLogsSignal ? ( - - - + - )} + ) : null} diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/logs_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/logs_overview/index.tsx new file mode 100644 index 00000000000000..163b5aa11898af --- /dev/null +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/logs_overview/index.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import React from 'react'; +import { useLocalStorage } from '../../../../hooks/use_local_storage'; +import { AddAPMCallOut } from '../../entities/logs/add_apm_callout'; +import { LogRateChart } from '../../entities/charts/log_rate_chart'; +import { LogErrorRateChart } from '../../entities/charts/log_error_rate_chart'; +import { chartHeight } from '..'; + +interface Props { + hasApmSignal?: boolean; +} + +export function LogsOverview({ hasApmSignal }: Props) { + const [isLogsApmCalloutEnabled, setIsLogsApmCalloutEnabled] = useLocalStorage( + 'apm.isLogsApmCalloutEnabled', + true + ); + + return ( + <> + {!hasApmSignal && isLogsApmCalloutEnabled ? ( + <> + { + setIsLogsApmCalloutEnabled(false); + }} + /> + + + ) : null} + + + + + + + + + + ); +} diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.stories.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.stories.tsx index d35cce84c9d711..4545bed8661198 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.stories.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.stories.tsx @@ -12,6 +12,7 @@ import { MockApmPluginStorybook } from '../../../context/apm_plugin/mock_apm_plu import { APMServiceContextValue } from '../../../context/apm_service/apm_service_context'; import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { mockApmApiCallResponse } from '../../../services/rest/call_apm_api_spy'; +import { SignalTypes } from '../../../../common/entities/types'; const stories: Meta<{}> = { title: 'app/ServiceOverview', @@ -21,6 +22,9 @@ const stories: Meta<{}> = { const serviceName = 'testServiceName'; const transactionType = 'type'; const transactionTypeStatus = FETCH_STATUS.SUCCESS; + const serviceEntitySummary = { + signalTypes: [SignalTypes.METRICS, SignalTypes.LOGS], + }; mockApmApiCallResponse( `GET /api/apm/services/{serviceName}/annotation/search 2023-10-31`, @@ -37,6 +41,7 @@ const stories: Meta<{}> = { serviceName, transactionType, transactionTypeStatus, + serviceEntitySummary, } as unknown as APMServiceContextValue; return ( diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.test.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.test.tsx index a8a9624065b0c7..35a5e48307147f 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview.test.tsx @@ -16,6 +16,6 @@ describe('ServiceOverview', () => { it('renders', async () => { render(); - expect(await screen.findByRole('heading', { name: /Latency/ })).toBeInTheDocument(); + expect(await screen.findByRole('heading', { name: 'Latency' })).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_instances_chart_and_table/index.tsx similarity index 88% rename from x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx rename to x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_instances_chart_and_table/index.tsx index 267a307604d2ab..a60ead6d60682d 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_instances_chart_and_table/index.tsx @@ -8,16 +8,16 @@ import { EuiFlexItem, EuiPanel } from '@elastic/eui'; import React, { useState } from 'react'; import { v4 as uuidv4 } from 'uuid'; -import { isTimeComparison } from '../../shared/time_comparison/get_comparison_options'; -import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; -import { useApmParams } from '../../../hooks/use_apm_params'; -import { FETCH_STATUS, isPending, useFetcher } from '../../../hooks/use_fetcher'; -import { useTimeRange } from '../../../hooks/use_time_range'; -import { APIReturnType } from '../../../services/rest/create_call_apm_api'; -import { InstancesLatencyDistributionChart } from '../../shared/charts/instances_latency_distribution_chart'; -import { ServiceOverviewInstancesTable, TableOptions } from './service_overview_instances_table'; -import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; -import { InstancesSortField } from '../../../../common/instances'; +import { isTimeComparison } from '../../../shared/time_comparison/get_comparison_options'; +import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; +import { useApmParams } from '../../../../hooks/use_apm_params'; +import { FETCH_STATUS, isPending, useFetcher } from '../../../../hooks/use_fetcher'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; +import { InstancesLatencyDistributionChart } from '../../../shared/charts/instances_latency_distribution_chart'; +import { ServiceOverviewInstancesTable, TableOptions } from '../service_overview_instances_table'; +import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types'; +import { InstancesSortField } from '../../../../../common/instances'; interface ServiceOverviewInstancesChartAndTableProps { chartHeight: number; diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/get_throughput_screen_context.ts b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart/get_throughput_screen_context.ts similarity index 87% rename from x-pack/plugins/observability_solution/apm/public/components/app/service_overview/get_throughput_screen_context.ts rename to x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart/get_throughput_screen_context.ts index 9c92e7909ede66..ad60e71a7093d2 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/get_throughput_screen_context.ts +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart/get_throughput_screen_context.ts @@ -6,14 +6,14 @@ */ import { SERVICE_ENVIRONMENT } from '@kbn/observability-shared-plugin/common'; -import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; -import { Environment } from '../../../../common/environment_rt'; +import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; +import { Environment } from '../../../../../common/environment_rt'; import { PROCESSOR_EVENT, SERVICE_NAME, TRANSACTION_NAME, TRANSACTION_TYPE, -} from '../../../../common/es_fields/apm'; +} from '../../../../../common/es_fields/apm'; export function getThroughputScreenContext({ serviceName, diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart/index.tsx similarity index 77% rename from x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx rename to x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart/index.tsx index 9fbdee4bf8502e..331d14d652fedd 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_overview/service_overview_throughput_chart/index.tsx @@ -8,22 +8,22 @@ import { EuiPanel, EuiTitle, EuiIconTip, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect } from 'react'; -import { usePreviousPeriodLabel } from '../../../hooks/use_previous_period_text'; -import { isTimeComparison } from '../../shared/time_comparison/get_comparison_options'; -import { AnomalyDetectorType } from '../../../../common/anomaly_detection/apm_ml_detectors'; -import { asExactTransactionRate } from '../../../../common/utils/formatters'; -import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; -import { useEnvironmentsContext } from '../../../context/environments_context/use_environments_context'; -import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; -import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; -import { usePreferredServiceAnomalyTimeseries } from '../../../hooks/use_preferred_service_anomaly_timeseries'; -import { useTimeRange } from '../../../hooks/use_time_range'; -import { TimeseriesChartWithContext } from '../../shared/charts/timeseries_chart_with_context'; -import { getComparisonChartTheme } from '../../shared/time_comparison/get_comparison_chart_theme'; -import { ChartType, getTimeSeriesColor } from '../../shared/charts/helper/get_timeseries_color'; -import { usePreferredDataSourceAndBucketSize } from '../../../hooks/use_preferred_data_source_and_bucket_size'; -import { ApmDocumentType } from '../../../../common/document_type'; -import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; +import { usePreviousPeriodLabel } from '../../../../hooks/use_previous_period_text'; +import { isTimeComparison } from '../../../shared/time_comparison/get_comparison_options'; +import { AnomalyDetectorType } from '../../../../../common/anomaly_detection/apm_ml_detectors'; +import { asExactTransactionRate } from '../../../../../common/utils/formatters'; +import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; +import { useEnvironmentsContext } from '../../../../context/environments_context/use_environments_context'; +import { useAnyOfApmParams } from '../../../../hooks/use_apm_params'; +import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; +import { usePreferredServiceAnomalyTimeseries } from '../../../../hooks/use_preferred_service_anomaly_timeseries'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { TimeseriesChartWithContext } from '../../../shared/charts/timeseries_chart_with_context'; +import { getComparisonChartTheme } from '../../../shared/time_comparison/get_comparison_chart_theme'; +import { ChartType, getTimeSeriesColor } from '../../../shared/charts/helper/get_timeseries_color'; +import { usePreferredDataSourceAndBucketSize } from '../../../../hooks/use_preferred_data_source_and_bucket_size'; +import { ApmDocumentType } from '../../../../../common/document_type'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { getThroughputScreenContext } from './get_throughput_screen_context'; const INITIAL_STATE = { diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/apm_route_config.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/apm_route_config.tsx index 02c0ceefe059b1..dd82e775d556de 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/routing/apm_route_config.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/routing/apm_route_config.tsx @@ -16,7 +16,6 @@ import { TransactionLink } from '../app/transaction_link'; import { homeRoute } from './home'; import { serviceDetailRoute } from './service_detail'; import { mobileServiceDetailRoute } from './mobile_service_detail'; -import { logsServiceDetailsRoute } from './entities/logs_service_details'; import { settingsRoute } from './settings'; import { onboarding } from './onboarding'; import { tutorialRedirectRoute } from './onboarding/redirect'; @@ -133,7 +132,6 @@ const apmRoutes = { ...settingsRoute, ...serviceDetailRoute, ...mobileServiceDetailRoute, - ...logsServiceDetailsRoute, ...homeRoute, }, }, diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/entities/logs_service_details/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/entities/logs_service_details/index.tsx deleted file mode 100644 index 4971414440aa01..00000000000000 --- a/x-pack/plugins/observability_solution/apm/public/components/routing/entities/logs_service_details/index.tsx +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; -import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils'; -import { Outlet } from '@kbn/typed-react-router-config'; -import * as t from 'io-ts'; -import React from 'react'; -import { LogsServiceTemplate } from '../../templates/entities/logs_service_template'; -import { offsetRt } from '../../../../../common/comparison_rt'; -import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; -import { environmentRt } from '../../../../../common/environment_rt'; -import { ApmTimeRangeMetadataContextProvider } from '../../../../context/time_range_metadata/time_range_metadata_context'; -import { ServiceDashboards } from '../../../app/service_dashboards'; -import { ServiceLogs } from '../../../app/service_logs'; -import { LogsServiceOverview } from '../../../app/entities/logs/logs_service_overview'; -import { RedirectToDefaultLogsServiceRouteView } from '../../service_detail/redirect_to_default_service_route_view'; -import { SearchBar } from '../../../shared/search_bar/search_bar'; - -export function page({ - title, - tabKey, - element, - searchBarOptions, -}: { - title: string; - tabKey: React.ComponentProps['selectedTabKey']; - element: React.ReactElement; - searchBarOptions?: React.ComponentProps; -}): { - element: React.ReactElement; -} { - return { - element: ( - - {element} - - ), - }; -} - -export const logsServiceDetailsRoute = { - '/logs-services/{serviceName}': { - element: ( - - - - ), - params: t.intersection([ - t.type({ - path: t.type({ - serviceName: t.string, - }), - }), - t.type({ - query: t.intersection([ - environmentRt, - t.type({ - rangeFrom: t.string, - rangeTo: t.string, - kuery: t.string, - serviceGroup: t.string, - comparisonEnabled: toBooleanRt, - }), - t.partial({ - transactionType: t.string, - refreshPaused: t.union([t.literal('true'), t.literal('false')]), - refreshInterval: t.string, - }), - offsetRt, - ]), - }), - ]), - defaults: { - query: { - kuery: '', - environment: ENVIRONMENT_ALL.value, - serviceGroup: '', - }, - }, - children: { - '/logs-services/{serviceName}/overview': { - ...page({ - element: , - tabKey: 'overview', - title: i18n.translate('xpack.apm.views.overview.title', { - defaultMessage: 'Overview', - }), - searchBarOptions: { - showUnifiedSearchBar: true, - showQueryInput: false, - }, - }), - params: t.partial({ - query: t.partial({ - page: toNumberRt, - pageSize: toNumberRt, - sortField: t.string, - sortDirection: t.union([t.literal('asc'), t.literal('desc')]), - }), - }), - }, - '/logs-services/{serviceName}/logs': { - ...page({ - tabKey: 'logs', - title: i18n.translate('xpack.apm.views.logs.title', { - defaultMessage: 'Logs', - }), - element: , - searchBarOptions: { - showUnifiedSearchBar: false, - }, - }), - }, - '/logs-services/{serviceName}/dashboards': { - ...page({ - tabKey: 'dashboards', - title: i18n.translate('xpack.apm.views.dashboard.title', { - defaultMessage: 'Dashboards', - }), - element: , - searchBarOptions: { - showUnifiedSearchBar: false, - }, - }), - params: t.partial({ - query: t.partial({ - dashboardId: t.string, - }), - }), - }, - '/logs-services/{serviceName}/': { - element: , - }, - }, - }, -}; diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/redirect_to_default_service_route_view.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/redirect_to_default_service_route_view.tsx index 4a61888b919f35..bcf0fbd435ae94 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/redirect_to_default_service_route_view.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/redirect_to_default_service_route_view.tsx @@ -19,14 +19,3 @@ export function RedirectToDefaultServiceRouteView() { return ; } - -export function RedirectToDefaultLogsServiceRouteView() { - const { - path: { serviceName }, - query, - } = useApmParams('/logs-services/{serviceName}/*'); - - const search = qs.stringify(query); - - return ; -} diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx index a08e575dcd752c..4bfb69810a524a 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx @@ -54,6 +54,7 @@ export default { serviceName, fallbackToTransactions: false, serviceAgentStatus: FETCH_STATUS.SUCCESS, + serviceEntitySummaryStatus: FETCH_STATUS.SUCCESS, }} > diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/entities/logs_service_template/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/entities/logs_service_template/index.tsx deleted file mode 100644 index 5b2b95ef416248..00000000000000 --- a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/entities/logs_service_template/index.tsx +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiFlexGroup, EuiFlexItem, EuiPageHeaderProps, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { omit } from 'lodash'; -import React from 'react'; -import { ApmServiceContextProvider } from '../../../../../context/apm_service/apm_service_context'; -import { useBreadcrumb } from '../../../../../context/breadcrumbs/use_breadcrumb'; -import { ServiceAnomalyTimeseriesContextProvider } from '../../../../../context/service_anomaly_timeseries/service_anomaly_timeseries_context'; -import { useApmParams } from '../../../../../hooks/use_apm_params'; -import { useApmRouter } from '../../../../../hooks/use_apm_router'; -import { useTimeRange } from '../../../../../hooks/use_time_range'; -import { SearchBar } from '../../../../shared/search_bar/search_bar'; -import { ServiceIcons } from '../../../../shared/service_icons'; -import { TechnicalPreviewBadge } from '../../../../shared/technical_preview_badge'; -import { ApmMainTemplate } from '../../apm_main_template'; - -type Tab = NonNullable[0] & { - key: 'overview' | 'logs' | 'dashboards'; - hidden?: boolean; -}; - -interface Props { - title: string; - children: React.ReactChild; - selectedTabKey: Tab['key']; - searchBarOptions?: React.ComponentProps; -} - -export function LogsServiceTemplate(props: Props) { - return ( - - - - ); -} - -function TemplateWithContext({ title, children, selectedTabKey, searchBarOptions }: Props) { - const { - path: { serviceName }, - query, - query: { rangeFrom, rangeTo, environment }, - } = useApmParams('/logs-services/{serviceName}/*'); - - const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - - const router = useApmRouter(); - - const tabs = useTabs({ selectedTabKey }); - const selectedTab = tabs?.find(({ isSelected }) => isSelected); - - const servicesLink = router.link('/services', { - query: { ...query }, - }); - - useBreadcrumb( - () => [ - { - title: i18n.translate('xpack.apm.logServices.breadcrumb.title', { - defaultMessage: 'Services', - }), - href: servicesLink, - }, - ...(selectedTab - ? [ - { - title: serviceName, - href: router.link('/logs-services/{serviceName}', { - path: { serviceName }, - query, - }), - }, - { - title: selectedTab.label, - href: selectedTab.href, - } as { title: string; href: string }, - ] - : []), - ], - [query, router, selectedTab, serviceName, servicesLink], - { - omitRootOnServerless: true, - } - ); - - return ( - - - - - -

- {serviceName} -

-
-
- - - -
-
- - ), - }} - > - - {children} -
- ); -} - -function useTabs({ selectedTabKey }: { selectedTabKey: Tab['key'] }) { - const router = useApmRouter(); - - const { - path: { serviceName }, - query: queryFromUrl, - } = useApmParams(`/logs-services/{serviceName}/${selectedTabKey}` as const); - - const query = omit(queryFromUrl, 'page', 'pageSize', 'sortField', 'sortDirection'); - - const tabs: Tab[] = [ - { - key: 'overview', - href: router.link('/logs-services/{serviceName}/overview', { - path: { serviceName }, - query, - }), - label: i18n.translate('xpack.apm.logsServiceDetails.overviewTabLabel', { - defaultMessage: 'Overview', - }), - }, - { - key: 'logs', - href: router.link('/logs-services/{serviceName}/logs', { - path: { serviceName }, - query, - }), - label: i18n.translate('xpack.apm.logsServiceDetails.logsTabLabel', { - defaultMessage: 'Logs', - }), - }, - { - key: 'dashboards', - href: router.link('/logs-services/{serviceName}/dashboards', { - path: { serviceName }, - query, - }), - append: , - label: i18n.translate('xpack.apm.logsServiceDetails.dashboardsTabLabel', { - defaultMessage: 'Dashboards', - }), - }, - ]; - - return tabs - .filter((t) => !t.hidden) - .map(({ href, key, label, append }) => ({ - href, - label, - append, - isSelected: key === selectedTabKey, - 'data-test-subj': `${key}Tab`, - })); -} diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx index 55a485ddf68e28..f02020c3645ed9 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx @@ -86,6 +86,7 @@ const stories: Meta = { transactionTypes: [], fallbackToTransactions: false, serviceAgentStatus: FETCH_STATUS.SUCCESS, + serviceEntitySummaryStatus: FETCH_STATUS.SUCCESS, }} > diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/is_route_with_time_range.ts b/x-pack/plugins/observability_solution/apm/public/components/shared/is_route_with_time_range.ts index f27b00dfc0c031..f5ec6737459398 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/is_route_with_time_range.ts +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/is_route_with_time_range.ts @@ -25,7 +25,6 @@ export function isRouteWithTimeRange({ route.path === '/dependencies/inventory' || route.path === '/services/{serviceName}' || route.path === '/mobile-services/{serviceName}' || - route.path === '/logs-services/{serviceName}' || route.path === '/service-groups' || route.path === '/storage-explorer' || location.pathname === '/' || diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/links/apm/service_link/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/links/apm/service_link/index.tsx index f32dc38234c74f..4dcf3ac79802cc 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/links/apm/service_link/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/links/apm/service_link/index.tsx @@ -16,12 +16,11 @@ import { SignalTypes } from '../../../../../../common/entities/types'; import { NOT_AVAILABLE_LABEL } from '../../../../../../common/i18n'; import { AgentName } from '../../../../../../typings/es_schemas/ui/fields/agent'; import { useApmRouter } from '../../../../../hooks/use_apm_router'; -import { isApmSignal } from '../../../../../utils/get_signal_type'; import { truncate, unit } from '../../../../../utils/style'; import { ApmRoutes } from '../../../../routing/apm_route_config'; import { PopoverTooltip } from '../../../popover_tooltip'; import { TruncateWithTooltip } from '../../../truncate_with_tooltip'; -import { OTHER_SERVICE_NAME, MaxGroupsMessage } from '../max_groups_message'; +import { MaxGroupsMessage, OTHER_SERVICE_NAME } from '../max_groups_message'; const StyledLink = euiStyled(EuiLink)`${truncate('100%')};`; @@ -46,9 +45,7 @@ export function ServiceLink({ const serviceLink = isMobileAgentName(agentName) ? '/mobile-services/{serviceName}/overview' - : isApmSignal(signalTypes) - ? '/services/{serviceName}/overview' - : '/logs-services/{serviceName}/overview'; + : '/services/{serviceName}/overview'; if (serviceName === OTHER_SERVICE_NAME) { return ( diff --git a/x-pack/plugins/observability_solution/apm/public/context/apm_plugin/mock_apm_plugin_storybook.tsx b/x-pack/plugins/observability_solution/apm/public/context/apm_plugin/mock_apm_plugin_storybook.tsx index f2f6ae0d158546..0c851093a5bb16 100644 --- a/x-pack/plugins/observability_solution/apm/public/context/apm_plugin/mock_apm_plugin_storybook.tsx +++ b/x-pack/plugins/observability_solution/apm/public/context/apm_plugin/mock_apm_plugin_storybook.tsx @@ -128,6 +128,13 @@ const mockApmPluginContext = { observabilityAIAssistant: { service: { setScreenContext: () => noop }, }, + share: { + url: { + locators: { + get: jest.fn(), + }, + }, + }, } as unknown as ApmPluginContextValue; export function MockApmPluginStorybook({ diff --git a/x-pack/plugins/observability_solution/apm/public/context/apm_service/apm_service_context.tsx b/x-pack/plugins/observability_solution/apm/public/context/apm_service/apm_service_context.tsx index 3fe833e6d9c647..9080e641e16fac 100644 --- a/x-pack/plugins/observability_solution/apm/public/context/apm_service/apm_service_context.tsx +++ b/x-pack/plugins/observability_solution/apm/public/context/apm_service/apm_service_context.tsx @@ -19,6 +19,10 @@ import { replace } from '../../components/shared/links/url_helpers'; import { FETCH_STATUS } from '../../hooks/use_fetcher'; import { ServerlessType } from '../../../common/serverless'; import { usePreferredDataSourceAndBucketSize } from '../../hooks/use_preferred_data_source_and_bucket_size'; +import { + type ServiceEntitySummary, + useServiceEntitySummaryFetcher, +} from './use_service_entity_summary_fetcher'; export interface APMServiceContextValue { serviceName: string; @@ -30,6 +34,8 @@ export interface APMServiceContextValue { runtimeName?: string; fallbackToTransactions: boolean; serviceAgentStatus: FETCH_STATUS; + serviceEntitySummary?: ServiceEntitySummary; + serviceEntitySummaryStatus: FETCH_STATUS; } export const APMServiceContext = createContext({ @@ -38,6 +44,7 @@ export const APMServiceContext = createContext({ transactionTypes: [], fallbackToTransactions: false, serviceAgentStatus: FETCH_STATUS.NOT_INITIATED, + serviceEntitySummaryStatus: FETCH_STATUS.NOT_INITIATED, }); export function ApmServiceContextProvider({ children }: { children: ReactNode }) { @@ -46,12 +53,8 @@ export function ApmServiceContextProvider({ children }: { children: ReactNode }) const { path: { serviceName }, query, - query: { kuery, rangeFrom, rangeTo }, - } = useAnyOfApmParams( - '/services/{serviceName}', - '/mobile-services/{serviceName}', - '/logs-services/{serviceName}' - ); + query: { kuery, rangeFrom, rangeTo, environment }, + } = useAnyOfApmParams('/services/{serviceName}', '/mobile-services/{serviceName}'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -82,6 +85,13 @@ export function ApmServiceContextProvider({ children }: { children: ReactNode }) rollupInterval: preferred?.source.rollupInterval, }); + const { serviceEntitySummary, serviceEntitySummaryStatus } = useServiceEntitySummaryFetcher({ + serviceName, + start, + end, + environment, + }); + const currentTransactionType = getOrRedirectToTransactionType({ transactionType: query.transactionType, transactionTypes, @@ -105,6 +115,8 @@ export function ApmServiceContextProvider({ children }: { children: ReactNode }) runtimeName, fallbackToTransactions, serviceAgentStatus, + serviceEntitySummary, + serviceEntitySummaryStatus, }} children={children} /> diff --git a/x-pack/plugins/observability_solution/apm/public/context/apm_service/use_service_entity_summary_fetcher.ts b/x-pack/plugins/observability_solution/apm/public/context/apm_service/use_service_entity_summary_fetcher.ts new file mode 100644 index 00000000000000..c5cb0b698c7b90 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm/public/context/apm_service/use_service_entity_summary_fetcher.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useFetcher } from '../../hooks/use_fetcher'; +import { APIReturnType } from '../../services/rest/create_call_apm_api'; +import { useEntityManagerEnablementContext } from '../entity_manager_context/use_entity_manager_enablement_context'; + +export type ServiceEntitySummary = + APIReturnType<'GET /internal/apm/entities/services/{serviceName}/summary'>; + +export function useServiceEntitySummaryFetcher({ + serviceName, + start, + end, + environment, +}: { + serviceName?: string; + start?: string; + end?: string; + environment?: string; +}) { + const { isEntityCentricExperienceViewEnabled } = useEntityManagerEnablementContext(); + + const { data, status } = useFetcher( + (callAPI) => { + if (isEntityCentricExperienceViewEnabled && serviceName && start && end && environment) { + return callAPI('GET /internal/apm/entities/services/{serviceName}/summary', { + params: { path: { serviceName }, query: { end, environment, start } }, + }); + } + }, + [end, environment, isEntityCentricExperienceViewEnabled, serviceName, start] + ); + + return { serviceEntitySummary: data, serviceEntitySummaryStatus: status }; +} diff --git a/x-pack/plugins/observability_solution/apm/public/context/service_anomaly_timeseries/service_anomaly_timeseries_context.tsx b/x-pack/plugins/observability_solution/apm/public/context/service_anomaly_timeseries/service_anomaly_timeseries_context.tsx index 30e6481b951b92..986730c99691ef 100644 --- a/x-pack/plugins/observability_solution/apm/public/context/service_anomaly_timeseries/service_anomaly_timeseries_context.tsx +++ b/x-pack/plugins/observability_solution/apm/public/context/service_anomaly_timeseries/service_anomaly_timeseries_context.tsx @@ -41,11 +41,7 @@ export function ServiceAnomalyTimeseriesContextProvider({ const { query: { rangeFrom, rangeTo }, - } = useAnyOfApmParams( - '/services/{serviceName}', - '/mobile-services/{serviceName}', - '/logs-services/{serviceName}' - ); + } = useAnyOfApmParams('/services/{serviceName}', '/mobile-services/{serviceName}'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const { preferredEnvironment } = useEnvironmentsContext();