Skip to content

Commit

Permalink
[APM][ECO] Order tabs accordingly based on the Signal types available (
Browse files Browse the repository at this point in the history
…elastic#191935)

closes elastic#190524

### **When EEM is disabled: Keeps the standard tab order**
<img width="1531" alt="Screenshot 2024-09-02 at 17 03 45"
src="https://github.com/user-attachments/assets/0916d18c-818f-41a8-a5e8-41f4f2e6825d">

### **When EEM is enabled and Service has APM only signal type: Keeps
the standard tab order**
<img width="1553" alt="Screenshot 2024-09-02 at 17 03 26"
src="https://github.com/user-attachments/assets/be98626b-18b1-4122-a80b-0d7aa5a38d0d">

### **When EEM is enabled and Service has APM and Logs Signal types:
Keeps the standard tab order**
<img width="1533" alt="Screenshot 2024-09-02 at 17 03 16"
src="https://github.com/user-attachments/assets/4ff6dd23-078b-43cd-a519-9050d05756e1">

### **When EEM is enabled and Service has Logs only signal type:
Reordering Overview | Logs | dashboard | ...**
<img width="1542" alt="Screenshot 2024-09-02 at 17 03 03"
src="https://github.com/user-attachments/assets/7ad8d4e4-e955-4310-b4c6-6316d6266284">
  • Loading branch information
cauemarcondes authored Sep 3, 2024
1 parent 73f15a1 commit 5c46dad
Show file tree
Hide file tree
Showing 9 changed files with 718 additions and 393 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,24 @@
* 2.0.
*/

import {
EuiBadge,
EuiFlexGroup,
EuiFlexItem,
EuiLoadingLogo,
EuiPageHeaderProps,
EuiSpacer,
EuiTitle,
EuiToolTip,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { enableAwsLambdaMetrics } from '@kbn/observability-plugin/common';
import { omit } from 'lodash';
import { EuiFlexGroup, EuiFlexItem, EuiLoadingLogo, EuiSpacer, EuiTitle } from '@elastic/eui';
import React from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { useProfilingIntegrationSetting } from '../../../../hooks/use_profiling_integration_setting';
import {
isAWSLambdaAgentName,
isAzureFunctionsAgentName,
isMobileAgentName,
isRumAgentName,
isRumOrMobileAgentName,
isServerlessAgentName,
} from '../../../../../common/agent_name';
import { ApmFeatureFlagName } from '../../../../../common/apm_feature_flags';
import { ServerlessType } from '../../../../../common/serverless';
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
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';
import { useBreadcrumb } from '../../../../context/breadcrumbs/use_breadcrumb';
import { ServiceAnomalyTimeseriesContextProvider } from '../../../../context/service_anomaly_timeseries/service_anomaly_timeseries_context';
import { useApmFeatureFlag } from '../../../../hooks/use_apm_feature_flag';
import { useApmParams } from '../../../../hooks/use_apm_params';
import { useApmRouter } from '../../../../hooks/use_apm_router';
import { isPending, useFetcher } from '../../../../hooks/use_fetcher';
import { isPending } from '../../../../hooks/use_fetcher';
import { useTimeRange } from '../../../../hooks/use_time_range';
import { getAlertingCapabilities } from '../../../alerting/utils/get_alerting_capabilities';
import { BetaBadge } from '../../../shared/beta_badge';
import { replace } from '../../../shared/links/url_helpers';
import { SearchBar } from '../../../shared/search_bar/search_bar';
import { ServiceIcons } from '../../../shared/service_icons';
import { TechnicalPreviewBadge } from '../../../shared/technical_preview_badge';
import { ApmMainTemplate } from '../apm_main_template';
import { AnalyzeDataButton } from './analyze_data_button';

type Tab = NonNullable<EuiPageHeaderProps['tabs']>[0] & {
key:
| 'overview'
| 'transactions'
| 'dependencies'
| 'errors'
| 'metrics'
| 'nodes'
| 'infrastructure'
| 'service-map'
| 'logs'
| 'alerts'
| 'profiling'
| 'dashboards';
hidden?: boolean;
};
import { Tab, useTabs } from './use_tabs';

interface Props {
title: string;
Expand Down Expand Up @@ -167,236 +124,3 @@ function TemplateWithContext({ title, children, selectedTab, searchBarOptions }:
</ApmMainTemplate>
);
}

export function isMetricsTabHidden({
agentName,
serverlessType,
isAwsLambdaEnabled,
}: {
agentName?: string;
serverlessType?: ServerlessType;
isAwsLambdaEnabled?: boolean;
}) {
if (isAWSLambdaAgentName(serverlessType)) {
return !isAwsLambdaEnabled;
}
return !agentName || isRumAgentName(agentName) || isAzureFunctionsAgentName(serverlessType);
}

export function isInfraTabHidden({
agentName,
serverlessType,
isInfraTabAvailable,
}: {
agentName?: string;
serverlessType?: ServerlessType;
isInfraTabAvailable: boolean;
}) {
return (
!agentName ||
isRumAgentName(agentName) ||
isServerlessAgentName(serverlessType) ||
!isInfraTabAvailable
);
}

function useTabs({ selectedTab }: { selectedTab: Tab['key'] }) {
const { agentName, serverlessType } = useApmServiceContext();
const { core, plugins } = useApmPluginContext();
const { capabilities } = core.application;
const { isAlertingAvailable, canReadAlerts } = getAlertingCapabilities(plugins, capabilities);

const router = useApmRouter();
const isInfraTabAvailable = useApmFeatureFlag(ApmFeatureFlagName.InfrastructureTabAvailable);

const isProfilingIntegrationEnabled = useProfilingIntegrationSetting();

const isAwsLambdaEnabled = core.uiSettings.get<boolean>(enableAwsLambdaMetrics, true);

const {
path: { serviceName },
query: queryFromUrl,
} = useApmParams(`/services/{serviceName}/${selectedTab}` as const);

const { rangeFrom, rangeTo, environment } = queryFromUrl;
const { start, end } = useTimeRange({ rangeFrom, rangeTo });

const { data: serviceAlertsCount = { alertsCount: 0 } } = useFetcher(
(callApmApi) => {
return callApmApi('GET /internal/apm/services/{serviceName}/alerts_count', {
params: {
path: {
serviceName,
},
query: {
start,
end,
environment,
},
},
});
},
[serviceName, start, end, environment]
);

const query = omit(queryFromUrl, 'page', 'pageSize', 'sortField', 'sortDirection');

const tabs: Tab[] = [
{
key: 'overview',
href: router.link('/services/{serviceName}/overview', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.serviceDetails.overviewTabLabel', {
defaultMessage: 'Overview',
}),
},
{
key: 'transactions',
href: router.link('/services/{serviceName}/transactions', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.serviceDetails.transactionsTabLabel', {
defaultMessage: 'Transactions',
}),
},
{
key: 'dependencies',
href: router.link('/services/{serviceName}/dependencies', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.serviceDetails.dependenciesTabLabel', {
defaultMessage: 'Dependencies',
}),
hidden: !agentName || isRumAgentName(agentName),
},
{
key: 'errors',
href: router.link('/services/{serviceName}/errors', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.serviceDetails.errorsTabLabel', {
defaultMessage: 'Errors',
}),
},
{
key: 'metrics',
href: router.link('/services/{serviceName}/metrics', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.serviceDetails.metricsTabLabel', {
defaultMessage: 'Metrics',
}),
append: isServerlessAgentName(serverlessType) && <TechnicalPreviewBadge icon="beaker" />,
hidden: isMetricsTabHidden({
agentName,
serverlessType,
isAwsLambdaEnabled,
}),
},
{
key: 'infrastructure',
href: router.link('/services/{serviceName}/infrastructure', {
path: { serviceName },
query,
}),
append: <BetaBadge icon="beta" />,
label: i18n.translate('xpack.apm.home.infraTabLabel', {
defaultMessage: 'Infrastructure',
}),
hidden: isInfraTabHidden({
agentName,
serverlessType,
isInfraTabAvailable,
}),
},
{
key: 'service-map',
href: router.link('/services/{serviceName}/service-map', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.home.serviceMapTabLabel', {
defaultMessage: 'Service Map',
}),
},
{
key: 'logs',
href: router.link('/services/{serviceName}/logs', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.home.serviceLogsTabLabel', {
defaultMessage: 'Logs',
}),
append: isServerlessAgentName(serverlessType) && <TechnicalPreviewBadge icon="beaker" />,
hidden: !agentName || isRumAgentName(agentName) || isAzureFunctionsAgentName(serverlessType),
},
{
key: 'alerts',
href: router.link('/services/{serviceName}/alerts', {
path: { serviceName },
query,
}),
append:
serviceAlertsCount.alertsCount > 0 ? (
<EuiToolTip
position="bottom"
content={i18n.translate(
'xpack.apm.home.serviceAlertsTable.tooltip.activeAlertsExplanation',
{
defaultMessage: 'Active alerts',
}
)}
>
<EuiBadge color="danger">{serviceAlertsCount.alertsCount}</EuiBadge>
</EuiToolTip>
) : null,
label: i18n.translate('xpack.apm.home.alertsTabLabel', {
defaultMessage: 'Alerts',
}),
hidden: !(isAlertingAvailable && canReadAlerts),
},
{
key: 'profiling',
href: router.link('/services/{serviceName}/profiling', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.home.profilingTabLabel', {
defaultMessage: 'Universal Profiling',
}),
hidden:
!isProfilingIntegrationEnabled ||
isRumOrMobileAgentName(agentName) ||
isAWSLambdaAgentName(serverlessType),
},
{
key: 'dashboards',
href: router.link('/services/{serviceName}/dashboards', {
path: { serviceName },
query,
}),
label: i18n.translate('xpack.apm.home.dashboardsTabLabel', {
defaultMessage: 'Dashboards',
}),
append: <TechnicalPreviewBadge icon="beaker" />,
},
];

return tabs
.filter((t) => !t.hidden)
.map(({ href, key, label, prepend, append }) => ({
href,
label,
prepend,
append,
isSelected: key === selectedTab,
'data-test-subj': `${key}Tab`,
}));
}
Loading

0 comments on commit 5c46dad

Please sign in to comment.