diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx index c822e32ea1fc6..dc8a063b85486 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx @@ -179,8 +179,6 @@ export function ServiceInventory() { canCreateJob && !userHasDismissedCallout; - const isLoading = mainStatisticsStatus === FETCH_STATUS.LOADING; - return ( <> @@ -192,17 +190,10 @@ export function ServiceInventory() { )} - ) - } + noItemsMessage={} /> diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx index a2dc5feec44f8..872359262cf02 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx @@ -5,76 +5,35 @@ * 2.0. */ -import { EuiEmptyPrompt, EuiLink } from '@elastic/eui'; +import { EuiEmptyPrompt } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { ErrorStatePrompt } from '../../shared/ErrorStatePrompt'; -import { useUpgradeAssistantHref } from '../../shared/Links/kibana'; -import { SetupInstructionsLink } from '../../shared/Links/SetupInstructionsLink'; interface Props { - // any data submitted from APM agents found (not just in the given time range) - historicalDataFound: boolean; status: FETCH_STATUS | undefined; } -export function NoServicesMessage({ historicalDataFound, status }: Props) { - const upgradeAssistantHref = useUpgradeAssistantHref(); - - if (status === 'failure') { - return ; +export function NoServicesMessage({ status }: Props) { + if (status === FETCH_STATUS.LOADING) { + return null; } - if (historicalDataFound) { - return ( - - {i18n.translate('xpack.apm.servicesTable.notFoundLabel', { - defaultMessage: 'No services found', - })} - - } - titleSize="s" - /> - ); + if (status === FETCH_STATUS.FAILURE) { + return ; } return ( - {i18n.translate('xpack.apm.servicesTable.noServicesLabel', { - defaultMessage: `Looks like you don't have any APM services installed. Let's add some!`, + {i18n.translate('xpack.apm.servicesTable.notFoundLabel', { + defaultMessage: 'No services found', })} } titleSize="s" - body={ - -

- {i18n.translate('xpack.apm.servicesTable.7xUpgradeServerMessage', { - defaultMessage: `Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM Server instance(s) to at least 7.0.`, - })} -

-

- {i18n.translate('xpack.apm.servicesTable.7xOldDataMessage', { - defaultMessage: - 'You may also have old data that needs to be migrated.', - })}{' '} - - {i18n.translate('xpack.apm.servicesTable.UpgradeAssistantLink', { - defaultMessage: - 'Learn more by visiting the Kibana Upgrade Assistant', - })} - - . -

-
- } - actions={} /> ); } diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx index 4423a53b96a30..56f77c6bfcc63 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx @@ -6,14 +6,15 @@ */ import { EuiPageHeaderProps } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import React from 'react'; import { useKibana, KibanaPageTemplateProps, } from '../../../../../../../src/plugins/kibana_react/public'; +import { useFetcher } from '../../../hooks/use_fetcher'; import { ApmPluginStartDeps } from '../../../plugin'; import { ApmEnvironmentFilter } from '../../shared/EnvironmentFilter'; +import { getNoDataConfig } from './no_data_config'; /* * This template contains: @@ -41,33 +42,16 @@ export function ApmMainTemplate({ const ObservabilityPageTemplate = services.observability.navigation.PageTemplate; - // TODO: NEEDS A DATA CHECK - const hasData = true; - const noDataConfig: KibanaPageTemplateProps['noDataConfig'] = !hasData - ? { - solution: i18n.translate('xpack.apm.noDataConfig.solutionName', { - defaultMessage: 'Observability', - }), - actions: { - beats: { - title: i18n.translate('xpack.apm.noDataConfig.beatsCard.title', { - defaultMessage: 'Add data with APM agents', - }), - description: i18n.translate( - 'xpack.apm.noDataConfig.beatsCard.description', - { - defaultMessage: - 'Use APM agents to collect APM data. We make it easy with agents for many popular languages.', - } - ), - href: basePath + `/app/home#/tutorial/apm`, - }, - }, - docsLink: docLinks!.links.observability.guide, - } - : undefined; + const { data } = useFetcher((callApmApi) => { + return callApmApi({ endpoint: 'GET /api/apm/has_data' }); + }, []); + + const noDataConfig = getNoDataConfig({ + basePath, + docsLink: docLinks!.links.observability.guide, + hasData: data?.hasData, + }); - // TODO: GET A CHECK return ( { const repository = createApmServerRouteRepository() @@ -56,7 +57,8 @@ const getTypedGlobalApmServerRouteRepository = () => { .merge(sourceMapsRouteRepository) .merge(apmFleetRouteRepository) .merge(backendsRouteRepository) - .merge(fallbackToTransactionsRouteRepository); + .merge(fallbackToTransactionsRouteRepository) + .merge(historicalDataRouteRepository); return repository; }; diff --git a/x-pack/plugins/apm/server/routes/historical_data.ts b/x-pack/plugins/apm/server/routes/historical_data.ts new file mode 100644 index 0000000000000..bd36213b06d5c --- /dev/null +++ b/x-pack/plugins/apm/server/routes/historical_data.ts @@ -0,0 +1,25 @@ +/* + * 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 { setupRequest } from '../lib/helpers/setup_request'; +import { hasHistoricalAgentData } from '../lib/services/get_services/has_historical_agent_data'; +import { createApmServerRoute } from './create_apm_server_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; + +const hasDataRoute = createApmServerRoute({ + endpoint: 'GET /api/apm/has_data', + options: { tags: ['access:apm'] }, + handler: async (resources) => { + const setup = await setupRequest(resources); + const hasData = await hasHistoricalAgentData(setup); + return { hasData }; + }, +}); + +export const historicalDataRouteRepository = createApmServerRouteRepository().add( + hasDataRoute +); diff --git a/x-pack/test/apm_api_integration/tests/historical_data/has_data.ts b/x-pack/test/apm_api_integration/tests/historical_data/has_data.ts new file mode 100644 index 0000000000000..ec3f0e5e7f362 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/historical_data/has_data.ts @@ -0,0 +1,41 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const archiveName = 'apm_8.0.0'; + + registry.when( + 'Historical data when data is not loaded', + { config: 'basic', archives: [] }, + () => { + it('handles the empty state', async () => { + const response = await supertest.get(`/api/apm/has_data`); + + expect(response.status).to.be(200); + expect(response.body.hasData).to.be(false); + }); + } + ); + + registry.when( + 'Historical data when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { + it('returns hasData: true', async () => { + const response = await supertest.get(`/api/apm/has_data`); + + expect(response.status).to.be(200); + expect(response.body.hasData).to.be(true); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts index c8a57bc613a92..be3860aebd401 100644 --- a/x-pack/test/apm_api_integration/tests/index.ts +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -221,6 +221,10 @@ export default function apmApiIntegrationTests(providerContext: FtrProviderConte loadTestFile(require.resolve('./csm/web_core_vitals')); }); + describe('historical_data/has_data', function () { + loadTestFile(require.resolve('./historical_data/has_data')); + }); + registry.run(providerContext); }); } diff --git a/x-pack/test/apm_api_integration/tests/services/top_services.ts b/x-pack/test/apm_api_integration/tests/services/top_services.ts index 86d5db591a6ba..bd4152fc8e2f3 100644 --- a/x-pack/test/apm_api_integration/tests/services/top_services.ts +++ b/x-pack/test/apm_api_integration/tests/services/top_services.ts @@ -35,7 +35,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expect(response.body.hasHistoricalData).to.be(false); expect(response.body.hasLegacyData).to.be(false); expect(response.body.items.length).to.be(0); }); @@ -64,10 +63,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.eql(200); }); - it('returns hasHistoricalData: true', () => { - expect(response.body.hasHistoricalData).to.be(true); - }); - it('returns hasLegacyData: false', () => { expect(response.body.hasLegacyData).to.be(false); });