diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_dependencies.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_dependencies.png
new file mode 100644
index 0000000000000..63377ac85431f
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_dependencies.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_errors.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_errors.png
new file mode 100644
index 0000000000000..0cfea1c544a02
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_errors.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_infrastructure.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_infrastructure.png
new file mode 100644
index 0000000000000..1a8f2cabbc0c1
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_infrastructure.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_metrics.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_metrics.png
new file mode 100644
index 0000000000000..799e41821effb
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_metrics.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_overview.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_overview.png
new file mode 100644
index 0000000000000..7f24ebaefb8c6
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_overview.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_service_map.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_service_map.png
new file mode 100644
index 0000000000000..19ec7072b227c
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_service_map.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_transactions.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_transactions.png
new file mode 100644
index 0000000000000..97de4c3a20ec9
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/dark/service_tab_empty_state_transactions.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_dependencies.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_dependencies.png
new file mode 100644
index 0000000000000..1cf18b76670bf
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_dependencies.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_errors.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_errors.png
new file mode 100644
index 0000000000000..df9a1c61cb6fe
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_errors.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_infrastructure.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_infrastructure.png
new file mode 100644
index 0000000000000..287862fd9c30f
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_infrastructure.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_metrics.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_metrics.png
new file mode 100644
index 0000000000000..7455f5a532a1e
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_metrics.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_overview.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_overview.png
new file mode 100644
index 0000000000000..2fd6807b209e8
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_overview.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_service_map.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_service_map.png
new file mode 100644
index 0000000000000..ae899d735988b
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_service_map.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_transactions.png b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_transactions.png
new file mode 100644
index 0000000000000..bb3183a5584e8
Binary files /dev/null and b/x-pack/plugins/observability_solution/apm/public/assets/service_tab_empty_state/light/service_tab_empty_state_transactions.png differ
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/index.tsx
index 5024bfad1fc99..486af9c64310e 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/error_group_overview/index.tsx
@@ -15,9 +15,12 @@ import { useErrorGroupDistributionFetcher } from '../../../hooks/use_error_group
import { FailedTransactionRateChart } from '../../shared/charts/failed_transaction_rate_chart';
import { ErrorDistribution } from '../error_group_details/distribution';
import { ErrorGroupList } from './error_group_list';
+import { isLogsOnlySignal } from '../../../utils/get_signal_type';
+import { ServiceTabEmptyState } from '../service_tab_empty_state';
export function ErrorGroupOverview() {
const { serviceName } = useApmServiceContext();
+ const { serviceEntitySummary } = useApmServiceContext();
const {
query: { environment, kuery, comparisonEnabled },
@@ -30,6 +33,13 @@ export function ErrorGroupOverview() {
kuery,
});
+ const hasLogsOnlySignal =
+ serviceEntitySummary?.dataStreamTypes && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
+ if (hasLogsOnlySignal) {
+ return ;
+ }
+
return (
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/infra_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/infra_overview/index.tsx
index 2b7f55d0ba690..a7db6bdd09a80 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/infra_overview/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/infra_overview/index.tsx
@@ -6,9 +6,21 @@
*/
import { EuiPanel } from '@elastic/eui';
import React from 'react';
+import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
+import { isLogsOnlySignal } from '../../../utils/get_signal_type';
import { InfraTabs } from './infra_tabs';
+import { ServiceTabEmptyState } from '../service_tab_empty_state';
export function InfraOverview() {
+ const { serviceEntitySummary } = useApmServiceContext();
+
+ const hasLogsOnlySignal =
+ serviceEntitySummary?.dataStreamTypes && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
+ if (hasLogsOnlySignal) {
+ return ;
+ }
+
return (
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/metrics/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/metrics/index.tsx
index b3eaa74ff1d80..e89bffeaf5b5d 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/metrics/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/metrics/index.tsx
@@ -18,11 +18,22 @@ import { JvmMetricsOverview } from './jvm_metrics_overview';
import { JsonMetricsDashboard } from './static_dashboard';
import { hasDashboardFile } from './static_dashboard/helper';
import { useAdHocApmDataView } from '../../../hooks/use_adhoc_apm_data_view';
+import { isLogsOnlySignal } from '../../../utils/get_signal_type';
+import { ServiceTabEmptyState } from '../service_tab_empty_state';
export function Metrics() {
const { agentName, runtimeName, serverlessType } = useApmServiceContext();
const isAWSLambda = isAWSLambdaAgentName(serverlessType);
const { dataView } = useAdHocApmDataView();
+ const { serviceEntitySummary } = useApmServiceContext();
+
+ const hasLogsOnlySignal =
+ serviceEntitySummary?.dataStreamTypes && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
+ if (hasLogsOnlySignal) {
+ return ;
+ }
+
if (isAWSLambda) {
return ;
}
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_dependencies/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_dependencies/index.tsx
index 30df2be2188fa..7aa010c276fcd 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/service_dependencies/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_dependencies/index.tsx
@@ -9,11 +9,23 @@ import { EuiTitle } from '@elastic/eui';
import { EuiPanel } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
+import { isLogsOnlySignal } from '../../../utils/get_signal_type';
import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context';
import { ServiceOverviewDependenciesTable } from '../service_overview/service_overview_dependencies_table';
import { ServiceDependenciesBreakdownChart } from './service_dependencies_breakdown_chart';
+import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
+import { ServiceTabEmptyState } from '../service_tab_empty_state';
export function ServiceDependencies() {
+ const { serviceEntitySummary } = useApmServiceContext();
+
+ const hasLogsOnlySignal =
+ serviceEntitySummary?.dataStreamTypes && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
+ if (hasLogsOnlySignal) {
+ return ;
+ }
+
return (
<>
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_map/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_map/index.tsx
index 14c5167128725..4536406a21bd5 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/service_map/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_map/index.tsx
@@ -29,6 +29,9 @@ import { useApmParams, useAnyOfApmParams } from '../../../hooks/use_apm_params';
import { Environment } from '../../../../common/environment_rt';
import { useTimeRange } from '../../../hooks/use_time_range';
import { DisabledPrompt } from './disabled_prompt';
+import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
+import { isLogsOnlySignal } from '../../../utils/get_signal_type';
+import { ServiceTabEmptyState } from '../service_tab_empty_state';
function PromptContainer({ children }: { children: ReactNode }) {
return (
@@ -76,6 +79,14 @@ export function ServiceMapServiceDetail() {
'/mobile-services/{serviceName}/service-map'
);
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
+ const { serviceEntitySummary } = useApmServiceContext();
+
+ const hasLogsOnlySignal =
+ serviceEntitySummary?.dataStreamTypes && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
+ if (hasLogsOnlySignal) {
+ return ;
+ }
return ;
}
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 e04f90b81798d..e406eba65f678 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
@@ -14,9 +14,12 @@ import { ChartPointerEventContextProvider } from '../../../context/chart_pointer
import { useEntityManagerEnablementContext } from '../../../context/entity_manager_context/use_entity_manager_enablement_context';
import { useApmParams } from '../../../hooks/use_apm_params';
import { useTimeRange } from '../../../hooks/use_time_range';
-import { isApmSignal, isLogsSignal } from '../../../utils/get_signal_type';
+import { isApmSignal, isLogsSignal, isLogsOnlySignal } from '../../../utils/get_signal_type';
import { ApmOverview } from './apm_overview';
import { LogsOverview } from './logs_overview';
+import { ServiceTabEmptyState } from '../service_tab_empty_state';
+import { useLocalStorage } from '../../../hooks/use_local_storage';
+import { SearchBar } from '../../shared/search_bar/search_bar';
import { FETCH_STATUS } from '../../../hooks/use_fetcher';
/**
* The height a chart should be if it's next to a table with 5 rows and a title.
@@ -49,11 +52,19 @@ export function ServiceOverview() {
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
+ const [dismissedLogsOnlyEmptyState, setDismissedLogsOnlyEmptyState] = useLocalStorage(
+ `apm.dismissedLogsOnlyEmptyState.overview`,
+ false
+ );
+
const hasSignal =
serviceEntitySummary?.dataStreamTypes && serviceEntitySummary?.dataStreamTypes?.length > 0;
const hasLogsSignal = hasSignal && isLogsSignal(serviceEntitySummary.dataStreamTypes);
+ const hasLogsOnlySignal = hasSignal && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
+ // Shows APM overview when entity has APM signal or when Entity centric is not enabled
const hasApmSignal = hasSignal && isApmSignal(serviceEntitySummary.dataStreamTypes);
// Shows APM overview when entity has APM signal or when Entity centric is not enabled or when entity has no signal
@@ -69,23 +80,36 @@ export function ServiceOverview() {
}
return (
-
-
-
- {showApmOverview ? : null}
- {/* Only shows Logs overview when entity has Logs signal */}
- {hasLogsSignal ? (
-
-
-
- ) : null}
-
-
-
+ <>
+
+
+
+
+ {showApmOverview ? : null}
+ {/* Only shows Logs overview when entity has Logs signal */}
+ {hasLogsSignal ? (
+ <>
+ {hasLogsOnlySignal && !dismissedLogsOnlyEmptyState && (
+
+ setDismissedLogsOnlyEmptyState(true)}
+ />
+
+ )}
+
+
+
+ >
+ ) : 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
index 163b5aa11898a..b51a95e3ccabc 100644
--- 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
@@ -5,44 +5,21 @@
* 2.0.
*/
-import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem } 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
- );
-
+export function LogsOverview() {
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 bd04f82396b1c..6bbad7a95e114 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
@@ -42,6 +42,7 @@ const stories: Meta<{}> = {
transactionType,
transactionTypeStatus,
serviceEntitySummary,
+ transactionTypes: ['type'],
} 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 35a5e48307147..98cdc1e65c3a2 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
@@ -9,10 +9,28 @@ import { composeStories } from '@storybook/testing-react';
import { render, screen } from '@testing-library/react';
import React from 'react';
import * as stories from './service_overview.stories';
+import * as useAdHocApmDataView from '../../../hooks/use_adhoc_apm_data_view';
const { Example } = composeStories(stories);
describe('ServiceOverview', () => {
+ let useAdHocApmDataViewSpy: jest.SpyInstance;
+
+ beforeAll(() => {
+ useAdHocApmDataViewSpy = jest.spyOn(useAdHocApmDataView, 'useAdHocApmDataView');
+
+ useAdHocApmDataViewSpy.mockImplementation(() => {
+ return {
+ dataView: {
+ id: 'foo-1',
+ },
+ };
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
it('renders', async () => {
render();
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/constants.ts b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/constants.ts
new file mode 100644
index 0000000000000..8165ad991cfe2
--- /dev/null
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/constants.ts
@@ -0,0 +1,95 @@
+/*
+ * 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';
+
+export type EmptyStateKey =
+ | 'serviceOverview'
+ | 'serviceDependencies'
+ | 'infraOverview'
+ | 'serviceMap'
+ | 'transactionOverview'
+ | 'metrics'
+ | 'errorGroupOverview';
+
+interface EmptyStateContent {
+ title: string;
+ content: string;
+ imgName?: string;
+}
+
+export const emptyStateDefinitions: Record = {
+ serviceOverview: {
+ title: i18n.translate('xpack.apm.serviceTabEmptyState.overviewTitle', {
+ defaultMessage: 'Detect and resolve issues faster with deep visibility into your application',
+ }),
+ content: i18n.translate('xpack.apm.serviceTabEmptyState.overviewContent', {
+ defaultMessage:
+ 'Understanding your application performance, relationships and dependencies by instrumenting with APM.',
+ }),
+ },
+ serviceDependencies: {
+ title: i18n.translate('xpack.apm.serviceTabEmptyState.dependenciesTitle', {
+ defaultMessage: 'Understand the dependencies for your service',
+ }),
+ content: i18n.translate('xpack.apm.serviceTabEmptyState.dependenciesContent', {
+ defaultMessage:
+ 'See your services dependencies on both internal and third-party services by instrumenting with APM.',
+ }),
+ imgName: 'service_tab_empty_state_dependencies.png',
+ },
+ infraOverview: {
+ title: i18n.translate('xpack.apm.serviceTabEmptyState.infrastructureTitle', {
+ defaultMessage: 'Understand what your service is running on',
+ }),
+ content: i18n.translate('xpack.apm.serviceTabEmptyState.infrastructureContent', {
+ defaultMessage:
+ 'Troubleshoot service problems by seeing the infrastructure your service is running on.',
+ }),
+ imgName: 'service_tab_empty_state_infrastructure.png',
+ },
+ serviceMap: {
+ title: i18n.translate('xpack.apm.serviceTabEmptyState.serviceMapTitle', {
+ defaultMessage: 'Visualise the dependencies between your services',
+ }),
+ content: i18n.translate('xpack.apm.serviceTabEmptyState.serviceMapContent', {
+ defaultMessage:
+ 'See your services dependencies at a glance to help identify dependencies that may be affecting your service.',
+ }),
+ imgName: 'service_tab_empty_state_service_map.png',
+ },
+ transactionOverview: {
+ title: i18n.translate('xpack.apm.serviceTabEmptyState.transactionsTitle', {
+ defaultMessage: 'Troubleshoot latency, throughput and errors',
+ }),
+ content: i18n.translate('xpack.apm.serviceTabEmptyState.transactionsContent', {
+ defaultMessage:
+ "Troubleshoot your service's performance by analysing latency, throughput and errors down to the specific transaction.",
+ }),
+ imgName: 'service_tab_empty_state_transactions.png',
+ },
+ metrics: {
+ title: i18n.translate('xpack.apm.serviceTabEmptyState.metricsTitle', {
+ defaultMessage: 'View core metrics for your application',
+ }),
+ content: i18n.translate('xpack.apm.serviceTabEmptyState.metricsContent', {
+ defaultMessage:
+ 'View metric trends for the instances of your service to identify performance bottlenecks that could be affecting your users.',
+ }),
+ imgName: 'service_tab_empty_state_metrics.png',
+ },
+ errorGroupOverview: {
+ title: i18n.translate('xpack.apm.serviceTabEmptyState.errorGroupOverviewTitle', {
+ defaultMessage: 'Identify transaction errors with your applications',
+ }),
+ content: i18n.translate('xpack.apm.serviceTabEmptyState.errorGroupOverviewContent', {
+ defaultMessage:
+ 'Analyse errors down to the specific transaction to pin-point specific errors within your service.',
+ }),
+ imgName: 'service_tab_empty_state_errors.png',
+ },
+};
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/index.tsx
new file mode 100644
index 0000000000000..8f4f86e2b92ed
--- /dev/null
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/index.tsx
@@ -0,0 +1,138 @@
+/*
+ * 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 {
+ EuiButton,
+ EuiButtonIcon,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiImage,
+ EuiLink,
+ EuiPanel,
+ EuiSpacer,
+ EuiText,
+ EuiTitle,
+ useEuiTheme,
+} from '@elastic/eui';
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
+import { useKibanaUrl } from '../../../hooks/use_kibana_url';
+import { AddApmData } from '../../shared/add_data_buttons/buttons';
+import { emptyStateDefinitions, EmptyStateKey } from './constants';
+
+export interface ServiceTabEmptyStateProps {
+ id: EmptyStateKey;
+ onDissmiss?: () => void;
+}
+
+const tryItNowButton = {
+ label: i18n.translate('xpack.apm.serviceTabEmptyState.tryItNowButtonLabel', {
+ defaultMessage: 'Try it now in our demo cluster',
+ }),
+ href: 'https://ela.st/demo-apm-try-it',
+};
+
+const learnMoreLink = {
+ label: i18n.translate('xpack.apm.serviceTabEmptyState.learnMoreLinkLabel', {
+ defaultMessage: 'Learn more',
+ }),
+ href: 'https://www.elastic.co/observability/application-performance-monitoring',
+};
+
+const baseImgFolder = '/plugins/apm/assets/service_tab_empty_state';
+
+export function ServiceTabEmptyState({ id, onDissmiss }: ServiceTabEmptyStateProps) {
+ const { euiTheme } = useEuiTheme();
+ const { core } = useApmPluginContext();
+
+ const imgFolder = `${baseImgFolder}/${
+ core.uiSettings.get('theme:darkMode') === 'enabled' ? 'dark' : 'light'
+ }`;
+ const imgName = emptyStateDefinitions[id].imgName;
+ const imgSrc = useKibanaUrl(
+ `${imgFolder}/${imgName ? imgName : 'service_tab_empty_state_overview.png'}`
+ );
+
+ return (
+ <>
+
+
+
+
+ {emptyStateDefinitions[id].title}
+
+
+ {emptyStateDefinitions[id].content}
+
+
+
+
+
+
+
+ {tryItNowButton.label}
+
+
+
+
+ {learnMoreLink.label}
+
+
+
+
+ {!emptyStateDefinitions[id].imgName && (
+
+
+
+ )}
+
+ {onDissmiss && (
+
+ )}
+
+
+ {emptyStateDefinitions[id].imgName && (
+ <>
+
+
+ >
+ )}
+ >
+ );
+}
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/service_tab_empty_state.stories.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/service_tab_empty_state.stories.tsx
new file mode 100644
index 0000000000000..1e85abd2a5b62
--- /dev/null
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_tab_empty_state/service_tab_empty_state.stories.tsx
@@ -0,0 +1,30 @@
+/*
+ * 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 React, { ComponentProps, ComponentType } from 'react';
+import { ServiceTabEmptyState } from '.';
+import { MockApmPluginStorybook } from '../../../context/apm_plugin/mock_apm_plugin_storybook';
+
+export default {
+ title: 'APP/ServiceTabEmptyState',
+ component: ServiceTabEmptyState,
+ decorators: [
+ (Story: ComponentType) => (
+
+
+
+ ),
+ ],
+};
+
+export function Default({ id }: ComponentProps) {
+ return ;
+}
+
+Default.args = {
+ id: 'infraOverview',
+} as ComponentProps;
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/transaction_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/transaction_overview/index.tsx
index 1ff58538b293a..84da9489964c6 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/transaction_overview/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/transaction_overview/index.tsx
@@ -19,6 +19,8 @@ import { TransactionCharts } from '../../shared/charts/transaction_charts';
import { replace } from '../../shared/links/url_helpers';
import { SloCallout } from '../../shared/slo_callout';
import { TransactionsTable } from '../../shared/transactions_table';
+import { isLogsOnlySignal } from '../../../utils/get_signal_type';
+import { ServiceTabEmptyState } from '../service_tab_empty_state';
export function TransactionOverview() {
const {
@@ -60,6 +62,15 @@ export function TransactionOverview() {
});
}, [setScreenContext, serviceName, transactionType]);
+ const { serviceEntitySummary } = useApmServiceContext();
+
+ const hasLogsOnlySignal =
+ serviceEntitySummary?.dataStreamTypes && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
+ if (hasLogsOnlySignal) {
+ return ;
+ }
+
return (
<>
{!sloCalloutDismissed && (
diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/index.tsx
index ea5a94a47ccd0..d746e0464fd40 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/routing/service_detail/index.tsx
@@ -155,8 +155,7 @@ export const serviceDetailRoute = {
defaultMessage: 'Overview',
}),
searchBarOptions: {
- showTransactionTypeSelector: true,
- showTimeComparison: true,
+ hidden: true,
},
}),
params: t.partial({
diff --git a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/index.tsx
index 6c2fdaea96687..0e095694cd538 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/routing/templates/apm_service_template/index.tsx
@@ -8,6 +8,7 @@
import { EuiFlexGroup, EuiFlexItem, EuiLoadingLogo, EuiSpacer, EuiTitle } from '@elastic/eui';
import React from 'react';
import { useHistory, useLocation } from 'react-router-dom';
+import { isLogsOnlySignal } from '../../../../utils/get_signal_type';
import { isMobileAgentName } from '../../../../../common/agent_name';
import { ApmServiceContextProvider } from '../../../../context/apm_service/apm_service_context';
import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context';
@@ -54,7 +55,7 @@ function TemplateWithContext({ title, children, selectedTab, searchBarOptions }:
const tabs = useTabs({ selectedTab });
- const { agentName, serviceAgentStatus } = useApmServiceContext();
+ const { agentName, serviceAgentStatus, serviceEntitySummary } = useApmServiceContext();
const isPendingServiceAgent = !agentName && isPending(serviceAgentStatus);
@@ -75,6 +76,9 @@ function TemplateWithContext({ title, children, selectedTab, searchBarOptions }:
});
}
+ const hasLogsOnlySignal =
+ serviceEntitySummary?.dataStreamTypes && isLogsOnlySignal(serviceEntitySummary.dataStreamTypes);
+
return (
) : (
<>
-
+ {!hasLogsOnlySignal && }
{children}
diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/add_data_buttons/buttons.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/add_data_buttons/buttons.tsx
index db2cb9d41237b..e3fc828b24803 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/shared/add_data_buttons/buttons.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/shared/add_data_buttons/buttons.tsx
@@ -8,7 +8,7 @@
// Disabling it for now until the EUI team fixes it
/* eslint-disable @elastic/eui/href-or-on-click */
-import { EuiButton } from '@elastic/eui';
+import { EuiButton, EuiButtonSize } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
@@ -34,22 +34,24 @@ export const collectServiceLogs = {
link: '/app/observabilityOnboarding/customLogs/?category=logs',
};
-export function AddApmData({
- onClick,
- ...props
-}: {
+interface AddApmDataProps {
onClick?: () => void;
'data-test-subj': string;
-}) {
+ fill?: boolean;
+ size?: EuiButtonSize;
+}
+
+export function AddApmData({ fill = false, size = 's', ...props }: AddApmDataProps) {
const { core } = useApmPluginContext();
const { basePath } = core.http;
return (
{addApmData.name}
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 0c851093a5bb1..a342f84e9c5c3 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
@@ -120,11 +120,44 @@ const mockCore = {
get: (key: string) => uiSettings[key],
get$: (key: string) => of(mockCore.uiSettings.get(key)),
},
+ unifiedSearch: {
+ autocomplete: {
+ hasQuerySuggestions: () => Promise.resolve(false),
+ getQuerySuggestions: () => [],
+ getValueSuggestions: () =>
+ new Promise((resolve) => {
+ setTimeout(() => {
+ resolve([]);
+ }, 300);
+ }),
+ },
+ },
+ data: {
+ query: {
+ queryString: { getQuery: jest.fn(), setQuery: jest.fn(), clearQuery: jest.fn() },
+ timefilter: {
+ timefilter: {
+ setTime: jest.fn(),
+ setRefreshInterval: jest.fn(),
+ },
+ },
+ },
+ },
+ dataViews: {
+ create: jest.fn(),
+ },
+};
+
+const mockUnifiedSearchBar = {
+ ui: {
+ SearchBar: () => ,
+ },
};
const mockApmPluginContext = {
core: mockCore,
plugins: mockPlugin,
+ unifiedSearch: mockUnifiedSearchBar,
observabilityAIAssistant: {
service: { setScreenContext: () => noop },
},
diff --git a/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts b/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts
index 4a73368c00e85..89d5c3ff49114 100644
--- a/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts
+++ b/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts
@@ -16,3 +16,7 @@ export function isApmSignal(dataStreamTypes: EntityDataStreamType[]) {
export function isLogsSignal(dataStreamTypes: EntityDataStreamType[]) {
return dataStreamTypes.includes(EntityDataStreamType.LOGS);
}
+
+export function isLogsOnlySignal(signalTypes: EntityDataStreamType[]) {
+ return !isApmSignal(signalTypes) && isLogsSignal(signalTypes);
+}