Skip to content

Commit

Permalink
[APM] Elastic Entity Enablement (#187593)
Browse files Browse the repository at this point in the history
## Summary
closes 
1. elastic/observability-dev#3724 (text
update)
2. elastic/observability-dev#3722 (link to
survey)
3. #187568

Basic workflow for enabling EEM in service inventory view 

The empty states will be handled in different PR 


- When the user clicks on "try new" we set up the builtin service
entities. There is an open PR
#187021 to update the definition.
[1]





### with the right permissions 


https://github.com/elastic/kibana/assets/3369346/2d76d9ca-dc1d-417b-8f06-f2d86b75a32f




### Without the right permissions 


https://github.com/elastic/kibana/assets/3369346/2f2af57c-a95a-4360-b667-1eceb7229d6c


## NOTE  
[1] if you test this PR locally the metrics will be N/A. you need to
update
https://github.com/elastic/kibana/blob/bf45ddd9f4c48acea5fac61d07012110bd4f0f4b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/built_in/services.ts
. Unless the PR 187021 is merged

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Nathan L Smith <nathan.smith@elastic.co>
  • Loading branch information
3 people authored Jul 10, 2024
1 parent d90d7fe commit b682833
Show file tree
Hide file tree
Showing 19 changed files with 558 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe('Service inventory', () => {
it('with the correct environment when changing the environment', () => {
cy.wait(mainAliasNames);

cy.getByTestSubj('environmentFilter').type('production');
cy.getByTestSubj('environmentFilter').type('{selectall}production');

cy.contains('button', 'production').click();

Expand All @@ -103,6 +103,7 @@ describe('Service inventory', () => {

it('when selecting a different time range and clicking the update button', () => {
cy.wait(mainAliasNames);
cy.getByTestSubj('apmServiceGroupsTourDismissButton').click();

cy.selectAbsoluteTimeRange(
moment(timeRange.rangeFrom).subtract(5, 'm').toISOString(),
Expand Down
12 changes: 3 additions & 9 deletions x-pack/plugins/observability_solution/apm/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"lens",
"maps",
"uiActions",
"logsDataAccess"
"logsDataAccess",
"entityManager"
],
"optionalPlugins": [
"actions",
Expand All @@ -52,13 +53,6 @@
"cases",
"observabilityAIAssistant"
],
"requiredBundles": [
"fleet",
"kibanaReact",
"kibanaUtils",
"ml",
"observability",
"maps"
]
"requiredBundles": ["fleet", "kibanaReact", "kibanaUtils", "ml", "observability", "maps"]
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,39 @@
* 2.0.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiEmptyPrompt, EuiLoadingLogo } from '@elastic/eui';
import { isEmpty } from 'lodash';
import { apmEnableMultiSignal } from '@kbn/observability-plugin/common';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
import { ApmServiceInventory } from './apm_signal_inventory';
import { MultiSignalInventory } from './multi_signal_inventory';
import { useApmParams } from '../../../hooks/use_apm_params';
import { useEntityManagerEnablementContext } from '../../../context/entity_manager_context/use_entity_manager_enablement_context';

export const ServiceInventory = () => {
const { core } = useApmPluginContext();
const isMultiSignalEnabled = core.uiSettings.get<boolean>(apmEnableMultiSignal, false);
export function ServiceInventory() {
const { isEntityManagerEnabled, isEnablementPending } = useEntityManagerEnablementContext();

const {
query: { serviceGroup },
} = useApmParams('/services');

return isMultiSignalEnabled && isEmpty(serviceGroup) ? (
if (isEnablementPending) {
return (
<EuiEmptyPrompt
icon={<EuiLoadingLogo logo="logoObservability" size="xl" />}
title={
<h2>
{i18n.translate('xpack.apm.loadingService', {
defaultMessage: 'Loading services',
})}
</h2>
}
/>
);
}

return isEntityManagerEnabled && isEmpty(serviceGroup) ? (
<MultiSignalInventory />
) : (
<ApmServiceInventory />
);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const apmRoutes = {
environmentFilter={false}
showServiceGroupSaveButton={false}
showServiceGroupsNav
showEnablementCallout
selectedNavButton="serviceGroups"
>
<ServiceGroupsList />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { RedirectWithDefaultEnvironment } from './redirect_with_default_environm
import { RedirectWithOffset } from './redirect_with_offset';
import { ScrollToTopOnPathChange } from './scroll_to_top_on_path_change';
import { UpdateExecutionContextOnRouteChange } from './update_execution_context_on_route_change';
import { EntityManagerEnablementContextProvider } from '../../../context/entity_manager_context/entity_manager_context';

const storage = new Storage(localStorage);

Expand Down Expand Up @@ -83,15 +84,17 @@ export function ApmAppRoot({
<BreadcrumbsContextProvider>
<UrlParamsProvider>
<LicenseProvider>
<AnomalyDetectionJobsContextProvider>
<InspectorContextProvider>
<ApmThemeProvider>
<MountApmHeaderActionMenu />
<Route component={ScrollToTopOnPathChange} />
<RouteRenderer />
</ApmThemeProvider>
</InspectorContextProvider>
</AnomalyDetectionJobsContextProvider>
<EntityManagerEnablementContextProvider>
<AnomalyDetectionJobsContextProvider>
<InspectorContextProvider>
<ApmThemeProvider>
<MountApmHeaderActionMenu />
<Route component={ScrollToTopOnPathChange} />
<RouteRenderer />
</ApmThemeProvider>
</InspectorContextProvider>
</AnomalyDetectionJobsContextProvider>
</EntityManagerEnablementContextProvider>
</LicenseProvider>
</UrlParamsProvider>
</BreadcrumbsContextProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { ServiceGroupsButtonGroup } from '../../app/service_groups/service_group
import { ApmEnvironmentFilter } from '../../shared/environment_filter';
import { getNoDataConfig } from './no_data_config';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
import { EntityEnablement } from '../../shared/entity_enablement';

// Paths that must skip the no data screen
const bypassNoDataScreenPaths = ['/settings', '/diagnostics'];
Expand All @@ -45,6 +46,7 @@ export function ApmMainTemplate({
environmentFilter = true,
showServiceGroupSaveButton = false,
showServiceGroupsNav = false,
showEnablementCallout = false,
environmentFilterInTemplate = true,
selectedNavButton,
...pageTemplateProps
Expand All @@ -55,6 +57,7 @@ export function ApmMainTemplate({
environmentFilter?: boolean;
showServiceGroupSaveButton?: boolean;
showServiceGroupsNav?: boolean;
showEnablementCallout?: boolean;
selectedNavButton?: 'serviceGroups' | 'allServices';
} & KibanaPageTemplateProps &
Pick<ObservabilityPageTemplateProps, 'pageSectionProps'>) {
Expand Down Expand Up @@ -126,6 +129,7 @@ export function ApmMainTemplate({
const pageHeaderTitle = (
<EuiFlexGroup justifyContent="spaceBetween" wrap={true}>
{pageHeader?.pageTitle ?? pageTitle}
<EuiFlexItem grow={false} />
<EuiFlexItem grow={false}>
<EuiFlexGroup justifyContent="center">
<EuiFlexItem grow={false}>
Expand All @@ -152,10 +156,14 @@ export function ApmMainTemplate({
rightSideItems,
...pageHeader,
pageTitle: pageHeaderTitle,
children:
showServiceGroupsNav && selectedNavButton ? (
<ServiceGroupsButtonGroup selectedNavButton={selectedNavButton} />
) : null,
children: (
<EuiFlexGroup direction="column">
{showEnablementCallout && selectedNavButton === 'allServices' && <EntityEnablement />}
{showServiceGroupsNav && selectedNavButton && (
<ServiceGroupsButtonGroup selectedNavButton={selectedNavButton} />
)}
</EuiFlexGroup>
),
}}
{...pageTemplateProps}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export function ServiceGroupTemplate({
environmentFilter={environmentFilter}
showServiceGroupSaveButton={!isAllServices}
showServiceGroupsNav={isAllServices}
showEnablementCallout
selectedNavButton={isAllServices ? 'allServices' : 'serviceGroups'}
{...pageTemplateProps}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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, { useContext } from 'react';
import { i18n } from '@kbn/i18n';
import {
useEuiTheme,
EuiButtonEmpty,
EuiConfirmModal,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiPanel,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { getSurveyFeedbackURL } from '@kbn/observability-shared-plugin/public';
import { KibanaEnvironmentContext } from '../../../context/kibana_environment_context/kibana_environment_context';
import { getPathForFeedback } from '../../../utils/get_path_for_feedback';

export function FeedbackModal({
isFeedbackModalVisible = false,
onClose,
}: {
isFeedbackModalVisible?: boolean;
onClose: () => void;
}) {
const kibanaEnvironment = useContext(KibanaEnvironmentContext);
const { kibanaVersion, isCloudEnv, isServerlessEnv } = kibanaEnvironment;
const sanitizedPath = getPathForFeedback(window.location.pathname);
const { euiTheme } = useEuiTheme();

return (
<>
{isFeedbackModalVisible && (
<EuiConfirmModal
style={{
width: '600px',
}}
onCancel={onClose}
onConfirm={onClose}
confirmButtonText={
<EuiButtonEmpty
css={{
color: euiTheme.colors.emptyShade,
}}
data-test-subj="xpack.apm.eemFeedback.button.open"
iconType="discuss"
target="_blank"
size="s"
href={getSurveyFeedbackURL({
formUrl: 'https://ela.st/new-o11y-experience',
kibanaVersion,
isCloudEnv,
isServerlessEnv,
sanitizedPath,
})}
>
{i18n.translate('xpack.apm.eemFeedback.button.openSurvey', {
defaultMessage: 'Tell us what you think!',
})}
</EuiButtonEmpty>
}
defaultFocusedButton="confirm"
>
<EuiPanel hasShadow={false}>
<EuiFlexGroup
direction="column"
justifyContent="center"
alignItems="center"
gutterSize="s"
>
<EuiFlexItem>
<EuiIcon type="heart" size="l" />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle>
<h2>
{i18n.translate('xpack.apm.eemFeedback.title', {
defaultMessage: 'Let us know what you think!',
})}
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>

<EuiPanel hasShadow={false} paddingSize="s">
<EuiText grow={false} size="s">
<p>
{i18n.translate('xpack.apm.feedbackModal.body.thanks', {
defaultMessage:
"Thank you for trying our new experience. We'll be continuing to improve on this so please come back often.",
})}
</p>
</EuiText>
</EuiPanel>
</EuiConfirmModal>
)}
</>
);
}
Loading

0 comments on commit b682833

Please sign in to comment.