diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/deep_links.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/deep_links.cy.ts index 00b842f3265c7..513d9afeccf9d 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/deep_links.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/deep_links.cy.ts @@ -14,6 +14,7 @@ describe('APM deep links', () => { cy.getByTestSubj('nav-search-input').type('APM'); cy.contains('APM'); cy.contains('APM / Services'); + cy.contains('APM / Service groups'); cy.contains('APM / Traces'); cy.contains('APM / Service Map'); @@ -28,6 +29,11 @@ describe('APM deep links', () => { cy.contains('APM / Services').click({ force: true }); cy.url().should('include', '/apm/services'); + cy.getByTestSubj('nav-search-input').type('APM'); + // navigates to service groups page + cy.contains('APM / Service groups').click({ force: true }); + cy.url().should('include', '/apm/service-groups'); + cy.getByTestSubj('nav-search-input').type('APM'); // navigates to traces page cy.contains('APM / Traces').click({ force: true }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/header_filters.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/header_filters.cy.ts index 4f72e968d81f8..e689e126d4bfd 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/header_filters.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/header_filters.cy.ts @@ -28,6 +28,7 @@ describe('Service inventory - header filters', () => { specialServiceName, }) ); + cy.dismissServiceGroupsTour(); }); after(() => { diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts index 013296d815a58..e0af1e1a84729 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts @@ -125,6 +125,16 @@ Cypress.Commands.add( } ); +Cypress.Commands.add('dismissServiceGroupsTour', () => { + window.localStorage.setItem( + 'apm.serviceGroupsTour', + JSON.stringify({ + createGroup: false, + editGroup: false, + }) + ); +}); + // A11y configuration const axeConfig = { diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/support/types.d.ts b/x-pack/plugins/apm/ftr_e2e/cypress/support/types.d.ts index 5d59d4691820a..d9675f2536315 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/support/types.d.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/support/types.d.ts @@ -23,5 +23,6 @@ declare namespace Cypress { }): void; updateAdvancedSettings(settings: Record): void; getByTestSubj(selector: string): Chainable>; + dismissServiceGroupsTour(): void; } } diff --git a/x-pack/plugins/apm/public/components/app/service_groups/service_group_save/create_button.tsx b/x-pack/plugins/apm/public/components/app/service_groups/service_group_save/create_button.tsx index cd1b819ce114e..6c872423d577a 100644 --- a/x-pack/plugins/apm/public/components/app/service_groups/service_group_save/create_button.tsx +++ b/x-pack/plugins/apm/public/components/app/service_groups/service_group_save/create_button.tsx @@ -7,42 +7,42 @@ import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { ServiceGroupsTour } from '../service_groups_tour'; -import { useServiceGroupsTour } from '../use_service_groups_tour'; +// import { ServiceGroupsTour } from '../service_groups_tour'; +// import { useServiceGroupsTour } from '../use_service_groups_tour'; interface Props { onClick: () => void; } export function CreateButton({ onClick }: Props) { - const { tourEnabled, dismissTour } = useServiceGroupsTour('createGroup'); + // const { tourEnabled, dismissTour } = useServiceGroupsTour('createGroup'); return ( - + { + // dismissTour(); + onClick(); + }} > - { - dismissTour(); - onClick(); - }} - > - {i18n.translate('xpack.apm.serviceGroups.createGroupLabel', { - defaultMessage: 'Create group', - })} - - + {i18n.translate('xpack.apm.serviceGroups.createGroupLabel', { + defaultMessage: 'Create group', + })} + + // ); } diff --git a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_button_group.tsx b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_button_group.tsx new file mode 100644 index 0000000000000..09a26dd150116 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_button_group.tsx @@ -0,0 +1,78 @@ +/* + * 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 { EuiButtonGroup } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { ServiceGroupsTour } from './service_groups_tour'; +import { useServiceGroupsTour } from './use_service_groups_tour'; + +const buttonGroupOptions = { + allServices: { + option: { + id: 'allServices', + label: i18n.translate('xpack.apm.serviceGroups.buttonGroup.allServices', { + defaultMessage: 'All services', + }), + }, + pathname: '/services', + }, + serviceGroups: { + option: { + id: 'serviceGroups', + label: i18n.translate( + 'xpack.apm.serviceGroups.buttonGroup.serviceGroups', + { defaultMessage: 'Service groups' } + ), + }, + pathname: '/service-groups', + }, +}; + +type SelectedNavButton = keyof typeof buttonGroupOptions; + +export function ServiceGroupsButtonGroup({ + selectedNavButton, +}: { + selectedNavButton: SelectedNavButton; +}) { + const history = useHistory(); + const { tourEnabled, dismissTour } = useServiceGroupsTour('createGroup'); + return ( + + { + const { pathname } = buttonGroupOptions[id as SelectedNavButton]; + history.push({ pathname }); + }} + legend={i18n.translate('xpack.apm.servicesGroups.buttonGroup.legend', { + defaultMessage: 'View all services or service groups', + })} + /> + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/index.tsx b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/index.tsx index 734298dabe9eb..2ee0224acda13 100644 --- a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/index.tsx @@ -12,6 +12,7 @@ import { EuiFlexItem, EuiFormControlLayout, EuiText, + EuiLink, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { isEmpty, sortBy } from 'lodash'; @@ -21,6 +22,8 @@ import { ServiceGroupsListItems } from './service_groups_list'; import { Sort } from './sort'; import { RefreshServiceGroupsSubscriber } from '../refresh_service_groups_subscriber'; import { getDateRange } from '../../../../context/url_params_context/helpers'; +import { ServiceGroupSaveButton } from '../service_group_save'; +import { BetaBadge } from '../../../shared/beta_badge'; export type ServiceGroupsSortType = 'recently_added' | 'alphabetical'; @@ -39,33 +42,24 @@ export function ServiceGroupsList() { [] ); + const { serviceGroups } = data; + const { start, end } = useMemo( - () => - getDateRange({ - rangeFrom: 'now-24h', - rangeTo: 'now', - }), + () => getDateRange({ rangeFrom: 'now-24h', rangeTo: 'now' }), [] ); const { data: servicesCountData = { servicesCounts: {} } } = useFetcher( (callApmApi) => { - if (start && end) { + if (start && end && serviceGroups.length) { return callApmApi('GET /internal/apm/service_groups/services_count', { - params: { - query: { - start, - end, - }, - }, + params: { query: { start, end } }, }); } }, - [start, end] + [start, end, serviceGroups.length] ); - const { serviceGroups } = data; - const isLoading = status === FETCH_STATUS.NOT_INITIATED || status === FETCH_STATUS.LOADING; @@ -91,7 +85,6 @@ export function ServiceGroupsList() { }, []); if (isLoading) { - // return null; return ( } @@ -127,9 +120,7 @@ export function ServiceGroupsList() { onChange={(e) => setFilter(e.target.value)} placeholder={i18n.translate( 'xpack.apm.servicesGroups.filter', - { - defaultMessage: 'Filter groups', - } + { defaultMessage: 'Filter groups' } )} /> @@ -145,51 +136,118 @@ export function ServiceGroupsList() { - + + {serviceGroups.length ? ( + <> + + + + + {i18n.translate( + 'xpack.apm.serviceGroups.groupsCount', + { + defaultMessage: + '{servicesCount} {servicesCount, plural, =0 {groups} one {group} other {groups}}', + values: { servicesCount: filteredItems.length }, + } + )} + + + + + {i18n.translate( + 'xpack.apm.serviceGroups.listDescription', + { + defaultMessage: + 'Displayed service counts reflect the last 24 hours.', + } + )} + + + + + + + ) : null} + + + + + +
+ +
+
- - {i18n.translate('xpack.apm.serviceGroups.groupsCount', { - defaultMessage: - '{servicesCount} {servicesCount, plural, =0 {group} one {group} other {groups}}', - values: { servicesCount: filteredItems.length + 1 }, - })} - + + {i18n.translate( + 'xpack.apm.serviceGroups.beta.feedback.link', + { defaultMessage: 'Send feedback' } + )} +
- - {i18n.translate('xpack.apm.serviceGroups.listDescription', { - defaultMessage: - 'Displayed service counts reflect the last 24 hours.', - })} -
- {items.length ? ( - + {serviceGroups.length ? ( + items.length ? ( + + ) : ( + + {i18n.translate( + 'xpack.apm.serviceGroups.filtered.emptyPrompt.serviceGroups', + { defaultMessage: 'Service groups' } + )} + + } + body={ +

+ {i18n.translate( + 'xpack.apm.serviceGroups.filtered.emptyPrompt.message', + { defaultMessage: 'No groups found for this filter' } + )} +

+ } + /> + ) ) : ( {i18n.translate( - 'xpack.apm.serviceGroups.emptyPrompt.serviceGroups', - { defaultMessage: 'Service groups' } + 'xpack.apm.serviceGroups.data.emptyPrompt.noServiceGroups', + { defaultMessage: 'No service groups' } )} } body={

{i18n.translate( - 'xpack.apm.serviceGroups.emptyPrompt.message', - { defaultMessage: 'No groups found for this filter' } + 'xpack.apm.serviceGroups.data.emptyPrompt.message', + { + defaultMessage: + 'Start grouping and organising your services and your application. Learn more about Service groups or create a group.', + } )}

} + actions={} /> )}
diff --git a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx index 96d6f381ebe14..bc8a424c922b9 100644 --- a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx +++ b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx @@ -18,15 +18,12 @@ import { ServiceGroup, SERVICE_GROUP_COLOR_DEFAULT, } from '../../../../../common/service_groups'; -import { ServiceGroupsTour } from '../service_groups_tour'; -import { useServiceGroupsTour } from '../use_service_groups_tour'; interface Props { serviceGroup: ServiceGroup; hideServiceCount?: boolean; onClick?: () => void; href?: string; - withTour?: boolean; servicesCount?: number; } @@ -35,11 +32,8 @@ export function ServiceGroupsCard({ hideServiceCount = false, onClick, href, - withTour, servicesCount, }: Props) { - const { tourEnabled, dismissTour } = useServiceGroupsTour('serviceGroupCard'); - const cardProps: EuiCardProps = { style: { width: 286 }, icon: ( @@ -81,45 +75,10 @@ export function ServiceGroupsCard({ )}
), - onClick: () => { - dismissTour(); - if (onClick) { - onClick(); - } - }, + onClick, href, }; - if (withTour) { - return ( - - - <>{cardProps.description} - - } - /> - - ); - } - return ( diff --git a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_groups_list.tsx b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_groups_list.tsx index 000759cc92021..64935927b9363 100644 --- a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_groups_list.tsx +++ b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_groups_list.tsx @@ -5,11 +5,9 @@ * 2.0. */ import { EuiFlexGrid } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import React from 'react'; import { SavedServiceGroup } from '../../../../../common/service_groups'; import { ServiceGroupsCard } from './service_group_card'; -import { SERVICE_GROUP_COLOR_DEFAULT } from '../../../../../common/service_groups'; import { useApmRouter } from '../../../../hooks/use_apm_router'; import { useApmParams } from '../../../../hooks/use_apm_params'; import { useDefaultEnvironment } from '../../../../hooks/use_default_environment'; @@ -42,30 +40,6 @@ export function ServiceGroupsListItems({ items, servicesCounts }: Props) { })} /> ))} - ); } diff --git a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_tour.tsx b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_tour.tsx index 0d4f825caefe3..4f7a457be49b4 100644 --- a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_tour.tsx +++ b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_tour.tsx @@ -5,19 +5,26 @@ * 2.0. */ -import { EuiButtonEmpty, EuiSpacer, EuiText, EuiTourStep } from '@elastic/eui'; +import { + EuiButtonEmpty, + EuiSpacer, + EuiText, + EuiTourStep, + PopoverAnchorPosition, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import { ElasticDocsLink } from '../../shared/links/elastic_docs_link'; -export type TourType = 'createGroup' | 'editGroup' | 'serviceGroupCard'; +export type TourType = 'createGroup' | 'editGroup'; interface Props { title: string; content: string; tourEnabled: boolean; dismissTour: () => void; + anchorPosition?: PopoverAnchorPosition; children: React.ReactElement; } @@ -26,6 +33,7 @@ export function ServiceGroupsTour({ dismissTour, title, content, + anchorPosition, children, }: Props) { return ( @@ -46,9 +54,7 @@ export function ServiceGroupsTour({ > {i18n.translate( 'xpack.apm.serviceGroups.tour.content.link.docs', - { - defaultMessage: 'docs', - } + { defaultMessage: 'docs' } )} ), @@ -63,7 +69,7 @@ export function ServiceGroupsTour({ step={1} stepsTotal={1} title={title} - anchorPosition="leftUp" + anchorPosition={anchorPosition} footerAction={ {i18n.translate('xpack.apm.serviceGroups.tour.dismiss', { diff --git a/x-pack/plugins/apm/public/components/app/service_groups/use_service_groups_tour.tsx b/x-pack/plugins/apm/public/components/app/service_groups/use_service_groups_tour.tsx index ba27b0e2640e8..400a88a026e01 100644 --- a/x-pack/plugins/apm/public/components/app/service_groups/use_service_groups_tour.tsx +++ b/x-pack/plugins/apm/public/components/app/service_groups/use_service_groups_tour.tsx @@ -11,7 +11,6 @@ import { TourType } from './service_groups_tour'; const INITIAL_STATE: Record = { createGroup: true, editGroup: true, - serviceGroupCard: true, }; export function useServiceGroupsTour(type: TourType) { diff --git a/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx index 53fab0ed5694c..4624c29376fa5 100644 --- a/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx +++ b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx @@ -18,7 +18,6 @@ import { serviceDetail } from './service_detail'; import { settings } from './settings'; import { ApmMainTemplate } from './templates/apm_main_template'; import { ServiceGroupsList } from '../app/service_groups'; -import { ServiceGroupsRedirect } from './service_groups_redirect'; import { offsetRt } from '../../../common/comparison_rt'; const ServiceGroupsTitle = i18n.translate( @@ -78,11 +77,11 @@ const apmRoutes = { - - - + ), diff --git a/x-pack/plugins/apm/public/components/routing/home/index.tsx b/x-pack/plugins/apm/public/components/routing/home/index.tsx index 36ead4f7b36c7..555d42ddb6f98 100644 --- a/x-pack/plugins/apm/public/components/routing/home/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/home/index.tsx @@ -22,7 +22,6 @@ import { TraceExplorer } from '../../app/trace_explorer'; import { TraceOverview } from '../../app/trace_overview'; import { TransactionTab } from '../../app/transaction_details/waterfall_with_summary/transaction_tabs'; import { RedirectTo } from '../redirect_to'; -import { ServiceGroupsRedirect } from '../service_groups_redirect'; import { ApmMainTemplate } from '../templates/apm_main_template'; import { ServiceGroupTemplate } from '../templates/service_group_template'; import { dependencies } from './dependencies'; @@ -236,13 +235,7 @@ export const home = { ...dependencies, ...legacyBackends, ...storageExplorer, - '/': { - element: ( - - - - ), - }, + '/': { element: }, }, }, }; diff --git a/x-pack/plugins/apm/public/components/routing/service_groups_redirect.tsx b/x-pack/plugins/apm/public/components/routing/service_groups_redirect.tsx deleted file mode 100644 index f309c69932903..0000000000000 --- a/x-pack/plugins/apm/public/components/routing/service_groups_redirect.tsx +++ /dev/null @@ -1,37 +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 React from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { enableServiceGroups } from '@kbn/observability-plugin/public'; -import { RedirectTo } from './redirect_to'; -import { useFetcher, FETCH_STATUS } from '../../hooks/use_fetcher'; - -export function ServiceGroupsRedirect({ - children, -}: { - children?: React.ReactNode; -}) { - const { data = { serviceGroups: [] }, status } = useFetcher( - (callApmApi) => callApmApi('GET /internal/apm/service-groups'), - [] - ); - const { serviceGroups } = data; - const isLoading = - status === FETCH_STATUS.NOT_INITIATED || status === FETCH_STATUS.LOADING; - const { - services: { uiSettings }, - } = useKibana(); - const isServiceGroupsEnabled = uiSettings?.get(enableServiceGroups); - - if (isLoading) { - return null; - } - if (!isServiceGroupsEnabled || serviceGroups.length === 0) { - return ; - } - return <>{children}; -} 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 4eb7d8140fdf3..60f06ddaef8fc 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 @@ -10,13 +10,13 @@ import React from 'react'; import { useLocation } from 'react-router-dom'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { KibanaPageTemplateProps } from '@kbn/shared-ux-page-kibana-template'; -import { enableServiceGroups } from '@kbn/observability-plugin/public'; import { EnvironmentsContextProvider } from '../../../context/environments_context/environments_context'; import { useFetcher, FETCH_STATUS } from '../../../hooks/use_fetcher'; import { ApmPluginStartDeps } from '../../../plugin'; import { ApmEnvironmentFilter } from '../../shared/environment_filter'; import { getNoDataConfig } from './no_data_config'; import { ServiceGroupSaveButton } from '../../app/service_groups'; +import { ServiceGroupsButtonGroup } from '../../app/service_groups/service_groups_button_group'; // Paths that must skip the no data screen const bypassNoDataScreenPaths = ['/settings']; @@ -37,6 +37,8 @@ export function ApmMainTemplate({ children, environmentFilter = true, showServiceGroupSaveButton = false, + showServiceGroupsNav = false, + selectedNavButton, ...pageTemplateProps }: { pageTitle?: React.ReactNode; @@ -44,6 +46,8 @@ export function ApmMainTemplate({ children: React.ReactNode; environmentFilter?: boolean; showServiceGroupSaveButton?: boolean; + showServiceGroupsNav?: boolean; + selectedNavButton?: 'serviceGroups' | 'allServices'; } & KibanaPageTemplateProps) { const location = useLocation(); @@ -97,14 +101,8 @@ export function ApmMainTemplate({ loading: isLoading, }); - const { - services: { uiSettings }, - } = useKibana(); - const isServiceGroupsEnabled = uiSettings?.get(enableServiceGroups); - const renderServiceGroupSaveButton = - showServiceGroupSaveButton && isServiceGroupsEnabled; const rightSideItems = [ - ...(renderServiceGroupSaveButton ? [] : []), + ...(showServiceGroupSaveButton ? [] : []), ...(environmentFilter ? [] : []), ]; @@ -116,6 +114,10 @@ export function ApmMainTemplate({ pageTitle, rightSideItems, ...pageHeader, + children: + showServiceGroupsNav && selectedNavButton ? ( + + ) : null, }} {...pageTemplateProps} > diff --git a/x-pack/plugins/apm/public/components/routing/templates/service_group_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/service_group_template.tsx index 1eece05eb8843..149188243ea35 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/service_group_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/service_group_template.tsx @@ -9,17 +9,13 @@ import { EuiPageHeaderProps, EuiFlexGroup, EuiFlexItem, - EuiButtonIcon, EuiLoadingContent, - EuiLoadingSpinner, + EuiIcon, } from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { KibanaPageTemplateProps } from '@kbn/shared-ux-page-kibana-template'; -import { enableServiceGroups } from '@kbn/observability-plugin/public'; -import { useFetcher, FETCH_STATUS } from '../../../hooks/use_fetcher'; -import { ApmPluginStartDeps } from '../../../plugin'; +import { useFetcher } from '../../../hooks/use_fetcher'; import { useApmRouter } from '../../../hooks/use_apm_router'; import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; import { ApmMainTemplate } from './apm_main_template'; @@ -39,11 +35,6 @@ export function ServiceGroupTemplate({ environmentFilter?: boolean; serviceGroupContextTab: ServiceGroupContextTab['key']; } & KibanaPageTemplateProps) { - const { - services: { uiSettings }, - } = useKibana(); - const isServiceGroupsEnabled = uiSettings?.get(enableServiceGroups); - const router = useApmRouter(); const { query, @@ -61,18 +52,9 @@ export function ServiceGroupTemplate({ [serviceGroupId] ); - const { data: serviceGroupsData, status: serviceGroupsStatus } = useFetcher( - (callApmApi) => { - if (!serviceGroupId && isServiceGroupsEnabled) { - return callApmApi('GET /internal/apm/service-groups'); - } - }, - [serviceGroupId, isServiceGroupsEnabled] - ); - const serviceGroupName = data?.serviceGroup.groupName; const loadingServiceGroupName = !!serviceGroupId && !serviceGroupName; - const hasServiceGroups = !!serviceGroupsData?.serviceGroups.length; + const isAllServices = !serviceGroupId; const serviceGroupsLink = router.link('/service-groups', { query: { ...query, serviceGroup: '' }, }); @@ -85,29 +67,13 @@ export function ServiceGroupTemplate({ justifyContent="flexStart" responsive={false} > - {serviceGroupsStatus === FETCH_STATUS.LOADING && ( - - - - )} - {(serviceGroupId || hasServiceGroups) && ( - - - - )} {loadingServiceGroupName ? ( ) : ( serviceGroupName || i18n.translate('xpack.apm.serviceGroup.allServices.title', { - defaultMessage: 'All services', + defaultMessage: 'Services', }) )} @@ -145,13 +111,33 @@ export function ServiceGroupTemplate({ ); return ( + {' '} + {i18n.translate( + 'xpack.apm.serviceGroups.breadcrumb.return', + { defaultMessage: 'Return' } + )} + + ), + color: 'primary', + 'aria-current': false, + href: serviceGroupsLink, + }, + ] + : undefined, ...pageHeader, }} environmentFilter={environmentFilter} - showServiceGroupSaveButton={true} + showServiceGroupSaveButton={!isAllServices} + showServiceGroupsNav={isAllServices} + selectedNavButton={isAllServices ? 'allServices' : 'serviceGroups'} {...pageTemplateProps} > {children} diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index 18dcba1468780..0b3137ee6ad99 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -48,7 +48,6 @@ import type { } from '@kbn/triggers-actions-ui-plugin/public'; import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import { SpacesPluginStart } from '@kbn/spaces-plugin/public'; -import { enableServiceGroups } from '@kbn/observability-plugin/public'; import { InfraClientStartExports } from '@kbn/infra-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { registerApmRuleTypes } from './components/alerting/rule_types/register_apm_rule_types'; @@ -104,10 +103,10 @@ const servicesTitle = i18n.translate('xpack.apm.navigation.servicesTitle', { defaultMessage: 'Services', }); -const allServicesTitle = i18n.translate( - 'xpack.apm.navigation.allServicesTitle', +const serviceGroupsTitle = i18n.translate( + 'xpack.apm.navigation.serviceGroupsTitle', { - defaultMessage: 'All services', + defaultMessage: 'Service groups', } ); @@ -154,11 +153,6 @@ export class ApmPlugin implements Plugin { pluginSetupDeps.home.featureCatalogue.register(featureCatalogueEntry); } - const serviceGroupsEnabled = core.uiSettings.get( - enableServiceGroups, - false - ); - // register observability nav if user has access to plugin plugins.observability.navigation.registerSections( from(core.getStartServices()).pipe( @@ -170,26 +164,18 @@ export class ApmPlugin implements Plugin { label: 'APM', sortKey: 400, entries: [ - serviceGroupsEnabled - ? { - label: servicesTitle, - app: 'apm', - path: '/service-groups', - matchPath(currentPath: string) { - return [ - '/service-groups', - '/services', - '/service-map', - ].some((testPath) => - currentPath.startsWith(testPath) - ); - }, - } - : { - label: servicesTitle, - app: 'apm', - path: '/services', - }, + { + label: servicesTitle, + app: 'apm', + path: '/services', + matchPath(currentPath: string) { + return [ + '/service-groups', + '/services', + '/service-map', + ].some((testPath) => currentPath.startsWith(testPath)); + }, + }, { label: tracesTitle, app: 'apm', path: '/traces' }, { label: dependenciesTitle, @@ -209,15 +195,6 @@ export class ApmPlugin implements Plugin { } }, }, - ...(serviceGroupsEnabled - ? [] - : [ - { - label: serviceMapTitle, - app: 'apm', - path: '/service-map', - }, - ]), ], }, ]; @@ -298,18 +275,14 @@ export class ApmPlugin implements Plugin { icon: 'plugins/apm/public/icon.svg', category: DEFAULT_APP_CATEGORIES.observability, deepLinks: [ - ...(serviceGroupsEnabled - ? [ - { - id: 'service-groups-list', - title: servicesTitle, - path: '/service-groups', - }, - ] - : []), + { + id: 'service-groups-list', + title: serviceGroupsTitle, + path: '/service-groups', + }, { id: 'services', - title: serviceGroupsEnabled ? allServicesTitle : servicesTitle, + title: servicesTitle, path: '/services', }, { id: 'traces', title: tracesTitle, path: '/traces' }, diff --git a/x-pack/plugins/observability/common/index.ts b/x-pack/plugins/observability/common/index.ts index 123c0639f2d49..7a2100e15225a 100644 --- a/x-pack/plugins/observability/common/index.ts +++ b/x-pack/plugins/observability/common/index.ts @@ -18,7 +18,6 @@ export { enableComparisonByDefault, defaultApmServiceEnvironment, apmProgressiveLoading, - enableServiceGroups, apmServiceInventoryOptimizedSorting, apmServiceGroupMaxNumberOfServices, apmTraceExplorerTab, diff --git a/x-pack/plugins/observability/common/ui_settings_keys.ts b/x-pack/plugins/observability/common/ui_settings_keys.ts index ab1684c2e5bfe..7de867608bfcb 100644 --- a/x-pack/plugins/observability/common/ui_settings_keys.ts +++ b/x-pack/plugins/observability/common/ui_settings_keys.ts @@ -11,7 +11,6 @@ export const maxSuggestions = 'observability:maxSuggestions'; export const enableComparisonByDefault = 'observability:enableComparisonByDefault'; export const defaultApmServiceEnvironment = 'observability:apmDefaultServiceEnvironment'; export const apmProgressiveLoading = 'observability:apmProgressiveLoading'; -export const enableServiceGroups = 'observability:enableServiceGroups'; export const apmServiceInventoryOptimizedSorting = 'observability:apmServiceInventoryOptimizedSorting'; export const apmServiceGroupMaxNumberOfServices = diff --git a/x-pack/plugins/observability/public/index.ts b/x-pack/plugins/observability/public/index.ts index 9bc1eb7f2a172..8c083012448e6 100644 --- a/x-pack/plugins/observability/public/index.ts +++ b/x-pack/plugins/observability/public/index.ts @@ -27,7 +27,6 @@ export type { export { enableInspectEsQueries, enableComparisonByDefault, - enableServiceGroups, enableNewSyntheticsView, apmServiceGroupMaxNumberOfServices, enableInfrastructureHostsView, diff --git a/x-pack/plugins/observability/server/ui_settings.ts b/x-pack/plugins/observability/server/ui_settings.ts index e979bd6a7fb11..a2bc38727e53e 100644 --- a/x-pack/plugins/observability/server/ui_settings.ts +++ b/x-pack/plugins/observability/server/ui_settings.ts @@ -15,7 +15,6 @@ import { maxSuggestions, defaultApmServiceEnvironment, apmProgressiveLoading, - enableServiceGroups, apmServiceInventoryOptimizedSorting, enableNewSyntheticsView, apmServiceGroupMaxNumberOfServices, @@ -162,24 +161,6 @@ export const uiSettings: Record = { }, showInLabs: true, }, - [enableServiceGroups]: { - category: [observabilityFeatureId], - name: i18n.translate('xpack.observability.enableServiceGroups', { - defaultMessage: 'Service groups feature', - }), - value: false, - description: i18n.translate('xpack.observability.enableServiceGroupsDescription', { - defaultMessage: - '{technicalPreviewLabel} Enable the Service groups feature on APM UI. {feedbackLink}.', - values: { - technicalPreviewLabel: `[${technicalPreviewLabel}]`, - feedbackLink: feedbackLink({ href: 'https://ela.st/feedback-service-groups' }), - }, - }), - schema: schema.boolean(), - requiresPageReload: true, - showInLabs: true, - }, [enableServiceMetrics]: { category: [observabilityFeatureId], name: i18n.translate('xpack.observability.apmEnableServiceMetrics', { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 7d1b626c1c7e8..087c56fab47b9 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -7431,7 +7431,6 @@ "xpack.apm.mlCallout.updateAvailableCalloutButtonText": "Mettre à jour les tâches", "xpack.apm.mlCallout.updateAvailableCalloutText": "Nous avons mis à jour les tâches de détection des anomalies qui fournissent des indications sur la dégradation des performances et ajouté des détecteurs de débit et de taux de transactions ayant échoué. Si vous choisissez de mettre à jour, nous créerons les nouvelles tâches et fermerons les tâches héritées. Les données affichées dans l'application APM passeront automatiquement aux nouvelles. Veuillez noter que l'option de migration de toutes les tâches existantes ne sera pas disponible si vous choisissez de créer une nouvelle tâche.", "xpack.apm.mlCallout.updateAvailableCalloutTitle": "Mises à jour disponibles", - "xpack.apm.navigation.allServicesTitle": "Tous les services", "xpack.apm.navigation.apmSettingsTitle": "Paramètres", "xpack.apm.navigation.dependenciesTitle": "Dépendances", "xpack.apm.navigation.serviceMapTitle": "Carte des services", @@ -7466,14 +7465,16 @@ "xpack.apm.serviceGroup.serviceInventory": "Inventory", "xpack.apm.serviceGroup.serviceMap": "Carte des services", "xpack.apm.serviceGroups.breadcrumb.title": "Services", + "xpack.apm.serviceGroups.buttonGroup.allServices": "Tous les services", + "xpack.apm.serviceGroups.buttonGroup.serviceGroups": "Groupes de services", "xpack.apm.serviceGroups.cardsList.emptyDescription": "Aucune description disponible", "xpack.apm.serviceGroups.createGroupLabel": "Créer un groupe", "xpack.apm.serviceGroups.createSuccess.toast.text": "Votre groupe est maintenant visible dans la nouvelle vue Services pour les groupes.", "xpack.apm.serviceGroups.deleteFailure.unknownId.toast.text": "Impossible de supprimer le groupe : id du groupe de service inconnu.", "xpack.apm.serviceGroups.editGroupLabel": "Modifier un groupe", "xpack.apm.serviceGroups.editSuccess.toast.text": "Nouveaux changements dans le groupe de services enregistrés.", - "xpack.apm.serviceGroups.emptyPrompt.message": "Aucun groupe trouvé pour ce filtre", - "xpack.apm.serviceGroups.emptyPrompt.serviceGroups": "Groupes de services", + "xpack.apm.serviceGroups.filtered.emptyPrompt.message": "Aucun groupe trouvé pour ce filtre", + "xpack.apm.serviceGroups.filtered.emptyPrompt.serviceGroups": "Groupes de services", "xpack.apm.serviceGroups.groupDetailsForm.cancel": "Annuler", "xpack.apm.serviceGroups.groupDetailsForm.color": "Couleur", "xpack.apm.serviceGroups.groupDetailsForm.create.title": "Créer un groupe", @@ -7484,8 +7485,6 @@ "xpack.apm.serviceGroups.groupDetailsForm.invalidColorError": "Veuillez fournir une valeur de couleur valide", "xpack.apm.serviceGroups.groupDetailsForm.name": "Nom", "xpack.apm.serviceGroups.groupDetailsForm.selectServices": "Sélectionner des services", - "xpack.apm.serviceGroups.list.allServices.description": "Afficher tous les services", - "xpack.apm.serviceGroups.list.allServices.name": "Tous les services", "xpack.apm.serviceGroups.list.sort.alphabetical": "Alphabétique", "xpack.apm.serviceGroups.list.sort.recentlyAdded": "Récemment ajouté", "xpack.apm.serviceGroups.selectServicesForm.cancel": "Annuler", @@ -7506,8 +7505,6 @@ "xpack.apm.serviceGroups.tour.dismiss": "Rejeter", "xpack.apm.serviceGroups.tour.editGroups.content": "Utilisez l'option de modification pour changer le nom, la requête ou les détails de ce groupe de services.", "xpack.apm.serviceGroups.tour.editGroups.title": "Modifier ce groupe de services", - "xpack.apm.serviceGroups.tour.serviceGroups.content": "Maintenant que vous avez créé un groupe de services, votre inventaire Tous les services a été déplacé ici. Ce groupe ne peut être ni modifié ni retiré.", - "xpack.apm.serviceGroups.tour.serviceGroups.title": "Groupe Tous les services", "xpack.apm.serviceHealthStatus.critical": "Critique", "xpack.apm.serviceHealthStatus.healthy": "Intègre", "xpack.apm.serviceHealthStatus.unknown": "Inconnu", @@ -23390,7 +23387,6 @@ "xpack.observability.enableInspectEsQueriesExperimentName": "Inspecter les recherches ES", "xpack.observability.enableNewSyntheticsViewExperimentDescription": "Activez la nouvelle application de monitoring synthétique dans Observability. Actualisez la page pour appliquer le paramètre.", "xpack.observability.enableNewSyntheticsViewExperimentName": "Activer la nouvelle application de monitoring synthétique", - "xpack.observability.enableServiceGroups": "Fonctionnalité de groupes de services", "xpack.observability.exp.breakDownFilter.noBreakdown": "Pas de répartition", "xpack.observability.exp.breakDownFilter.unavailable": "La répartition par nom d'étape n'est pas disponible pour l'indicateur de durée de monitoring. Utilisez l'indicateur de durée d'étape pour répartir par nom d'étape.", "xpack.observability.exp.breakDownFilter.warning": "Les répartitions ne peuvent être appliquées qu’à une seule série à la fois.", @@ -33678,4 +33674,4 @@ "xpack.painlessLab.title": "Painless Lab", "xpack.painlessLab.walkthroughButtonLabel": "Présentation" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index d3f6cb84354ae..f4c281167d8b6 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7419,7 +7419,6 @@ "xpack.apm.mlCallout.updateAvailableCalloutButtonText": "ジョブの更新", "xpack.apm.mlCallout.updateAvailableCalloutText": "劣化したパフォーマンスに関する詳細な分析を提供する異常検知ジョブを更新し、スループットと失敗したトランザクションレートの検知機能を追加しました。アップグレードを選択する場合は、新しいジョブが作成され、既存のレガシージョブが終了します。APMアプリに表示されるデータは自動的に新しいジョブに切り替わります。新しいジョブの作成を選択した場合は、すべての既存のジョブを移行するオプションを使用できません。", "xpack.apm.mlCallout.updateAvailableCalloutTitle": "更新が可能です", - "xpack.apm.navigation.allServicesTitle": "すべてのサービス", "xpack.apm.navigation.apmSettingsTitle": "設定", "xpack.apm.navigation.dependenciesTitle": "依存関係", "xpack.apm.navigation.serviceMapTitle": "サービスマップ", @@ -7453,14 +7452,16 @@ "xpack.apm.serviceGroup.serviceInventory": "インベントリ", "xpack.apm.serviceGroup.serviceMap": "サービスマップ", "xpack.apm.serviceGroups.breadcrumb.title": "サービス", + "xpack.apm.serviceGroups.buttonGroup.allServices": "すべてのサービス", + "xpack.apm.serviceGroups.buttonGroup.serviceGroups": "サービスグループ", "xpack.apm.serviceGroups.cardsList.emptyDescription": "説明がありません", "xpack.apm.serviceGroups.createGroupLabel": "グループを作成", "xpack.apm.serviceGroups.createSuccess.toast.text": "グループは、グループの新しいサービスビューに表示されます。", "xpack.apm.serviceGroups.deleteFailure.unknownId.toast.text": "グループを削除できません。不明なサービスグループIDです。", "xpack.apm.serviceGroups.editGroupLabel": "グループを編集", "xpack.apm.serviceGroups.editSuccess.toast.text": "サービスグループの新しいグループが保存されました。", - "xpack.apm.serviceGroups.emptyPrompt.message": "このフィルターのグループが見つかりません", - "xpack.apm.serviceGroups.emptyPrompt.serviceGroups": "サービスグループ", + "xpack.apm.serviceGroups.filtered.emptyPrompt.message": "このフィルターのグループが見つかりません", + "xpack.apm.serviceGroups.filtered.emptyPrompt.serviceGroups": "サービスグループ", "xpack.apm.serviceGroups.groupDetailsForm.cancel": "キャンセル", "xpack.apm.serviceGroups.groupDetailsForm.color": "色", "xpack.apm.serviceGroups.groupDetailsForm.create.title": "グループを作成", @@ -7471,8 +7472,6 @@ "xpack.apm.serviceGroups.groupDetailsForm.invalidColorError": "有効な色値を指定してください", "xpack.apm.serviceGroups.groupDetailsForm.name": "名前", "xpack.apm.serviceGroups.groupDetailsForm.selectServices": "サービスを選択", - "xpack.apm.serviceGroups.list.allServices.description": "すべてのサービスを表示", - "xpack.apm.serviceGroups.list.allServices.name": "すべてのサービス", "xpack.apm.serviceGroups.list.sort.alphabetical": "アルファベット順", "xpack.apm.serviceGroups.list.sort.recentlyAdded": "最近追加された項目", "xpack.apm.serviceGroups.selectServicesForm.cancel": "キャンセル", @@ -7493,8 +7492,6 @@ "xpack.apm.serviceGroups.tour.dismiss": "閉じる", "xpack.apm.serviceGroups.tour.editGroups.content": "編集オプションを使用して、名前、クエリ、このサービスグループの詳細を変更します。", "xpack.apm.serviceGroups.tour.editGroups.title": "このサービスグループを編集", - "xpack.apm.serviceGroups.tour.serviceGroups.content": "サービスグループが作成されたため、すべてのサービスインベントリがここに移動されました。このグループは編集または削除できません。", - "xpack.apm.serviceGroups.tour.serviceGroups.title": "すべてのサービスグループ", "xpack.apm.serviceHealthStatus.critical": "重大", "xpack.apm.serviceHealthStatus.healthy": "正常", "xpack.apm.serviceHealthStatus.unknown": "不明", @@ -23369,7 +23366,6 @@ "xpack.observability.enableInspectEsQueriesExperimentName": "ESクエリを調査", "xpack.observability.enableNewSyntheticsViewExperimentDescription": "オブザーバビリティで新しい合成監視アプリケーションを有効にします。設定を適用するにはページを更新してください。", "xpack.observability.enableNewSyntheticsViewExperimentName": "新しい合成監視アプリケーションを有効にする", - "xpack.observability.enableServiceGroups": "サービスグループ機能", "xpack.observability.exp.breakDownFilter.noBreakdown": "内訳なし", "xpack.observability.exp.breakDownFilter.unavailable": "モニター期間メトリックでは、ステップ名内訳を使用できません。ステップ期間メトリックを使用して、ステップ名で分解します。", "xpack.observability.exp.breakDownFilter.warning": "内訳は一度に1つの系列にのみ適用できます。", @@ -33652,4 +33648,4 @@ "xpack.painlessLab.title": "Painless Lab", "xpack.painlessLab.walkthroughButtonLabel": "実地検証" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1239010846ed6..ce903ab668bef 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7435,7 +7435,6 @@ "xpack.apm.mlCallout.updateAvailableCalloutButtonText": "更新作业", "xpack.apm.mlCallout.updateAvailableCalloutText": "我们已更新有助于深入了解性能降级的异常检测作业,并添加了检测工具以获取吞吐量和失败事务率。如果您选择进行升级,我们将创建新作业,并关闭现有的旧版作业。APM 应用中显示的数据将自动切换到新数据。请注意,如果您选择创建新作业,用于迁移所有现有作业的选项将不可用。", "xpack.apm.mlCallout.updateAvailableCalloutTitle": "可用更新", - "xpack.apm.navigation.allServicesTitle": "所有服务", "xpack.apm.navigation.apmSettingsTitle": "设置", "xpack.apm.navigation.dependenciesTitle": "依赖项", "xpack.apm.navigation.serviceMapTitle": "服务地图", @@ -7470,14 +7469,16 @@ "xpack.apm.serviceGroup.serviceInventory": "库存", "xpack.apm.serviceGroup.serviceMap": "服务地图", "xpack.apm.serviceGroups.breadcrumb.title": "服务", + "xpack.apm.serviceGroups.buttonGroup.allServices": "所有服务", + "xpack.apm.serviceGroups.buttonGroup.serviceGroups": "服务组", "xpack.apm.serviceGroups.cardsList.emptyDescription": "描述不可用", "xpack.apm.serviceGroups.createGroupLabel": "创建组", "xpack.apm.serviceGroups.createSuccess.toast.text": "您的组当前在组的新服务视图中可见。", "xpack.apm.serviceGroups.deleteFailure.unknownId.toast.text": "无法删除组:服务组 ID 未知。", "xpack.apm.serviceGroups.editGroupLabel": "编辑组", "xpack.apm.serviceGroups.editSuccess.toast.text": "已将新更改保存到服务组。", - "xpack.apm.serviceGroups.emptyPrompt.message": "找不到此筛选的组", - "xpack.apm.serviceGroups.emptyPrompt.serviceGroups": "服务组", + "xpack.apm.serviceGroups.filtered.emptyPrompt.message": "找不到此筛选的组", + "xpack.apm.serviceGroups.filtered.emptyPrompt.serviceGroups": "服务组", "xpack.apm.serviceGroups.groupDetailsForm.cancel": "取消", "xpack.apm.serviceGroups.groupDetailsForm.color": "颜色", "xpack.apm.serviceGroups.groupDetailsForm.create.title": "创建组", @@ -7488,8 +7489,6 @@ "xpack.apm.serviceGroups.groupDetailsForm.invalidColorError": "请提供有效的颜色值", "xpack.apm.serviceGroups.groupDetailsForm.name": "名称", "xpack.apm.serviceGroups.groupDetailsForm.selectServices": "选择服务", - "xpack.apm.serviceGroups.list.allServices.description": "查看所有服务", - "xpack.apm.serviceGroups.list.allServices.name": "所有服务", "xpack.apm.serviceGroups.list.sort.alphabetical": "按字母顺序", "xpack.apm.serviceGroups.list.sort.recentlyAdded": "最近添加", "xpack.apm.serviceGroups.selectServicesForm.cancel": "取消", @@ -7510,8 +7509,6 @@ "xpack.apm.serviceGroups.tour.dismiss": "关闭", "xpack.apm.serviceGroups.tour.editGroups.content": "使用编辑选项更改此服务组的名称、查询或详情。", "xpack.apm.serviceGroups.tour.editGroups.title": "编辑此服务组", - "xpack.apm.serviceGroups.tour.serviceGroups.content": "既然您已创建服务组,您的所有服务库存已移到此处。无法编辑或移除该组。", - "xpack.apm.serviceGroups.tour.serviceGroups.title": "所有服务组", "xpack.apm.serviceHealthStatus.critical": "紧急", "xpack.apm.serviceHealthStatus.healthy": "运行正常", "xpack.apm.serviceHealthStatus.unknown": "未知", @@ -23400,7 +23397,6 @@ "xpack.observability.enableInspectEsQueriesExperimentName": "检查 ES 查询", "xpack.observability.enableNewSyntheticsViewExperimentDescription": "在 Observability 中启用新的组合监测应用程序。刷新页面可应用该设置。", "xpack.observability.enableNewSyntheticsViewExperimentName": "启用新的组合监测应用程序", - "xpack.observability.enableServiceGroups": "服务组功能", "xpack.observability.exp.breakDownFilter.noBreakdown": "无细目", "xpack.observability.exp.breakDownFilter.unavailable": "步骤名称细目不可用于监测持续时间指标。使用步骤持续时间指标以按步骤名称细分。", "xpack.observability.exp.breakDownFilter.warning": "一次只能将细目应用于一个序列。", @@ -33689,4 +33685,4 @@ "xpack.painlessLab.title": "Painless 实验室", "xpack.painlessLab.walkthroughButtonLabel": "指导" } -} \ No newline at end of file +}