[8.12] [ObsUX] Add UI Setting for controling Profiling visibility in Infra (#173294) (#173661)

# Backport

This will backport the following commits from `main` to `8.12`:
- [[ObsUX] Add UI Setting for controling Profiling visibility in Infra
(#173294)](https://github.com/elastic/kibana/pull/173294)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Mykola
Harmash","email":"mykola.harmash@gmail.com"},"sourceCommit":{"committedDate":"2023-12-19T15:48:35Z","message":"[ObsUX]
Add UI Setting for controling Profiling visibility in Infra
(#173294)\n\nCloses
https://github.com/elastic/kibana/issues/173154\r\n\r\nAdds a UI setting
to control Infra+Profiling integration from Kibana's\r\nAdvanced
Settings as well as from the Infra Settings screen.\r\n\r\nNote that the
plugin config feature flag is still there because I\r\nrealized we need
it to disable Profiling integration in
serverless.\r\n\r\n\r\n\r\n2a5ace9d-9e18-49a4-be95-c722f24072a7\r\n\r\n###
How to test\r\n\r\n* Make sure profiling is enabled in
`kibana.dev.yml`\r\n```\r\nxpack.profiling.enabled: true\r\n```\r\n*
Start kibana in traditional mode, go to Infra Settings\r\n* Make sure
there is the new toggle for Profiling integration and it's\r\non\r\n* Go
to one of your host's details and make sure you see the
profiling\r\ntab\r\n* Toggle the Profiling integration setting off and
check that the tap in\r\nhost details is not visible\r\n\r\n* Start
kibana in serverless mode\r\n* Make sure there is no new setting neither
in Infra Settings nor in\r\nAdvanced Settings\r\n* Make sure Profiling
tab is not visible in host
details\r\n\r\n---------\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"c62790773374a8eeb47c0398c285148004442d60","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v8.12.0","Team:obs-ux-infra_services","Team:obs-ux-management","v8.13.0"],"number":173294,"url":"https://github.com/elastic/kibana/pull/173294","mergeCommit":{"message":"[ObsUX]
Add UI Setting for controling Profiling visibility in Infra
(#173294)\n\nCloses
https://github.com/elastic/kibana/issues/173154\r\n\r\nAdds a UI setting
to control Infra+Profiling integration from Kibana's\r\nAdvanced
Settings as well as from the Infra Settings screen.\r\n\r\nNote that the
plugin config feature flag is still there because I\r\nrealized we need
it to disable Profiling integration in
serverless.\r\n\r\n\r\n\r\n2a5ace9d-9e18-49a4-be95-c722f24072a7\r\n\r\n###
How to test\r\n\r\n* Make sure profiling is enabled in
`kibana.dev.yml`\r\n```\r\nxpack.profiling.enabled: true\r\n```\r\n*
Start kibana in traditional mode, go to Infra Settings\r\n* Make sure
there is the new toggle for Profiling integration and it's\r\non\r\n* Go
to one of your host's details and make sure you see the
profiling\r\ntab\r\n* Toggle the Profiling integration setting off and
check that the tap in\r\nhost details is not visible\r\n\r\n* Start
kibana in serverless mode\r\n* Make sure there is no new setting neither
in Infra Settings nor in\r\nAdvanced Settings\r\n* Make sure Profiling
tab is not visible in host
details\r\n\r\n---------\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"c62790773374a8eeb47c0398c285148004442d60"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","labelRegex":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/173294","number":173294,"mergeCommit":{"message":"[ObsUX]
Add UI Setting for controling Profiling visibility in Infra
(#173294)\n\nCloses
https://github.com/elastic/kibana/issues/173154\r\n\r\nAdds a UI setting
to control Infra+Profiling integration from Kibana's\r\nAdvanced
Settings as well as from the Infra Settings screen.\r\n\r\nNote that the
plugin config feature flag is still there because I\r\nrealized we need
it to disable Profiling integration in
serverless.\r\n\r\n\r\n\r\n2a5ace9d-9e18-49a4-be95-c722f24072a7\r\n\r\n###
How to test\r\n\r\n* Make sure profiling is enabled in
`kibana.dev.yml`\r\n```\r\nxpack.profiling.enabled: true\r\n```\r\n*
Start kibana in traditional mode, go to Infra Settings\r\n* Make sure
there is the new toggle for Profiling integration and it's\r\non\r\n* Go
to one of your host's details and make sure you see the
profiling\r\ntab\r\n* Toggle the Profiling integration setting off and
check that the tap in\r\nhost details is not visible\r\n\r\n* Start
kibana in serverless mode\r\n* Make sure there is no new setting neither
in Infra Settings nor in\r\nAdvanced Settings\r\n* Make sure Profiling
tab is not visible in host
details\r\n\r\n---------\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"c62790773374a8eeb47c0398c285148004442d60"}}]}]
BACKPORT-->

Co-authored-by: Mykola Harmash <mykola.harmash@gmail.com>
This commit is contained in:
Kibana Machine 2024-01-15 11:19:56 -05:00 committed by GitHub
parent 945643256d
commit ba30fb7b18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 152 additions and 20 deletions

View file

@ -451,6 +451,9 @@ preview:[] When enabled, allows users to create Service Groups from the APM Serv
[[observability-apm-trace-explorer-tab]]`observability:apmTraceExplorerTab`::
preview:[] Enable the APM Trace Explorer feature, that allows you to search and inspect traces with KQL or EQL.
[[observability-infrastructure-profiling-integration]]`observability:enableInfrastructureProfilingIntegration`::
preview:[] Enables the Profiling view in Host details within Infrastructure.
[float]
[[kibana-reporting-settings]]
==== Reporting

View file

@ -581,6 +581,10 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'observability:enableInfrastructureProfilingIntegration': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:enableGroupedNav': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },

View file

@ -46,6 +46,7 @@ export interface UsageStats {
'observability:apmAWSLambdaPriceFactor': string;
'observability:apmAWSLambdaRequestCostPerMillion': number;
'observability:enableInfrastructureHostsView': boolean;
'observability:enableInfrastructureProfilingIntegration': boolean;
'observability:apmAgentExplorerView': boolean;
'visualization:heatmap:maxBuckets': number;
'visualization:colorMapping': string;

View file

@ -10061,6 +10061,12 @@
"description": "Non-default value of setting."
}
},
"observability:enableInfrastructureProfilingIntegration": {
"type": "boolean",
"_meta": {
"description": "Non-default value of setting."
}
},
"securitySolution:enableGroupedNav": {
"type": "boolean",
"_meta": {

View file

@ -5,22 +5,23 @@
* 2.0.
*/
import {
EuiIcon,
type EuiPageHeaderProps,
type EuiBreadcrumbsProps,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
type EuiBreadcrumbsProps,
type EuiPageHeaderProps,
} from '@elastic/eui';
import { useLinkProps } from '@kbn/observability-shared-plugin/public';
import React, { useCallback, useMemo } from 'react';
import { capitalize } from 'lodash';
import { useHistory, useLocation } from 'react-router-dom';
import { FormattedMessage } from '@kbn/i18n-react';
import { useLinkProps } from '@kbn/observability-shared-plugin/public';
import { capitalize } from 'lodash';
import React, { useCallback, useMemo } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { usePluginConfig } from '../../../containers/plugin_config_context';
import { useKibanaContextForPlugin } from '../../../hooks/use_kibana';
import { useProfilingIntegrationSetting } from '../../../hooks/use_profiling_integration_setting';
import { APM_HOST_FILTER_FIELD } from '../constants';
import { LinkToAlertsRule, LinkToApmServices, LinkToNodeDetails } from '../links';
import { ContentTabIds, type RouteState, type LinkOptions, type Tab, type TabIds } from '../types';
import { ContentTabIds, type LinkOptions, type RouteState, type Tab, type TabIds } from '../types';
import { useAssetDetailsRenderPropsContext } from './use_asset_details_render_props';
import { useTabSwitcherContext } from './use_tab_switcher';
@ -110,12 +111,14 @@ const useRightSideItems = (links?: LinkOptions[]) => {
const useFeatureFlagTabs = () => {
const { featureFlags } = usePluginConfig();
const isProfilingEnabled = useProfilingIntegrationSetting();
const featureFlagControlledTabs: Partial<Record<ContentTabIds, boolean>> = useMemo(
() => ({
[ContentTabIds.OSQUERY]: featureFlags.osqueryEnabled,
[ContentTabIds.PROFILING]: featureFlags.profilingEnabled,
[ContentTabIds.PROFILING]: isProfilingEnabled,
}),
[featureFlags.osqueryEnabled, featureFlags.profilingEnabled]
[featureFlags.osqueryEnabled, isProfilingEnabled]
);
const isTabEnabled = useCallback(

View file

@ -10,19 +10,24 @@ import { i18n } from '@kbn/i18n';
import { EuiButtonEmpty } from '@elastic/eui';
import { EuiBadge } from '@elastic/eui';
import { EuiFlexGroup } from '@elastic/eui';
import { usePluginConfig } from '../../../../../containers/plugin_config_context';
import { useProfilingIntegrationSetting } from '../../../../../hooks/use_profiling_integration_setting';
import { useTabSwitcherContext } from '../../../hooks/use_tab_switcher';
export function CpuProfilingPrompt() {
const { showTab } = useTabSwitcherContext();
const { featureFlags } = usePluginConfig();
const isProfilingEnabled = useProfilingIntegrationSetting();
if (!featureFlags.profilingEnabled) {
if (!isProfilingEnabled) {
return null;
}
return (
<EuiFlexGroup alignItems="center" justifyContent="flexStart" gutterSize="s">
<EuiFlexGroup
alignItems="center"
justifyContent="flexStart"
gutterSize="s"
data-test-subj="infraAssetDetailsCPUProfilingPrompt"
>
<EuiBadge color="success">
{i18n.translate('xpack.infra.cpuProfilingPrompt.newBadgeLabel', {
defaultMessage: 'NEW',

View file

@ -0,0 +1,21 @@
/*
* 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 { useUiSetting } from '@kbn/kibana-react-plugin/public';
import { enableInfrastructureProfilingIntegration } from '@kbn/observability-plugin/common';
import { usePluginConfig } from '../containers/plugin_config_context';
export function useProfilingIntegrationSetting(): boolean {
const {
featureFlags: { profilingEnabled },
} = usePluginConfig();
const isProfilingUiSettingEnabled = useUiSetting<boolean>(
enableInfrastructureProfilingIntegration
);
return profilingEnabled && isProfilingUiSettingEnabled;
}

View file

@ -10,9 +10,13 @@ import { EuiSpacer } from '@elastic/eui';
import { EuiForm } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import React from 'react';
import { enableInfrastructureHostsView } from '@kbn/observability-plugin/common';
import {
enableInfrastructureHostsView,
enableInfrastructureProfilingIntegration,
} from '@kbn/observability-plugin/common';
import { useEditableSettings } from '@kbn/observability-shared-plugin/public';
import { LazyField } from '@kbn/advanced-settings-plugin/public';
import { usePluginConfig } from '../../../containers/plugin_config_context';
import { useKibanaContextForPlugin } from '../../../hooks/use_kibana';
type Props = Pick<
@ -31,6 +35,7 @@ export function FeaturesConfigurationPanel({
const {
services: { docLinks, notifications },
} = useKibanaContextForPlugin();
const { featureFlags } = usePluginConfig();
return (
<EuiForm>
@ -52,6 +57,17 @@ export function FeaturesConfigurationPanel({
toasts={notifications.toasts}
unsavedChanges={unsavedChanges[enableInfrastructureHostsView]}
/>
{featureFlags.profilingEnabled && (
<LazyField
key={enableInfrastructureProfilingIntegration}
setting={settingsEditableConfig[enableInfrastructureProfilingIntegration]}
handleChange={handleFieldChange}
enableSaving={!readOnly}
docLinks={docLinks.links}
toasts={notifications.toasts}
unsavedChanges={unsavedChanges[enableInfrastructureProfilingIntegration]}
/>
)}
</EuiForm>
);
}

View file

@ -17,7 +17,10 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React, { useCallback } from 'react';
import { Prompt, useEditableSettings } from '@kbn/observability-shared-plugin/public';
import { enableInfrastructureHostsView } from '@kbn/observability-plugin/common';
import {
enableInfrastructureHostsView,
enableInfrastructureProfilingIntegration,
} from '@kbn/observability-plugin/common';
import { SourceLoadingPage } from '../../../components/source_loading_page';
import { useSourceContext } from '../../../containers/metrics_source';
import { useInfraMLCapabilitiesContext } from '../../../containers/ml/infra_ml_capabilities';
@ -61,7 +64,10 @@ export const SourceConfigurationSettings = ({
formState,
formStateChanges,
} = useSourceConfigurationFormState(source && source.configuration);
const infraUiSettings = useEditableSettings('infra_metrics', [enableInfrastructureHostsView]);
const infraUiSettings = useEditableSettings('infra_metrics', [
enableInfrastructureHostsView,
enableInfrastructureProfilingIntegration,
]);
const resetAllUnsavedChanges = useCallback(() => {
resetForm();

View file

@ -32,6 +32,7 @@ export {
apmTraceExplorerTab,
apmLabsButton,
enableInfrastructureHostsView,
enableInfrastructureProfilingIntegration,
enableAwsLambdaMetrics,
enableAgentExplorerView,
apmAWSLambdaPriceFactor,

View file

@ -17,6 +17,8 @@ export const apmServiceGroupMaxNumberOfServices =
export const apmTraceExplorerTab = 'observability:apmTraceExplorerTab';
export const apmLabsButton = 'observability:apmLabsButton';
export const enableInfrastructureHostsView = 'observability:enableInfrastructureHostsView';
export const enableInfrastructureProfilingIntegration =
'observability:enableInfrastructureProfilingIntegration';
export const enableAwsLambdaMetrics = 'observability:enableAwsLambdaMetrics';
export const enableAgentExplorerView = 'observability:apmAgentExplorerView';
export const apmAWSLambdaPriceFactor = 'observability:apmAWSLambdaPriceFactor';

View file

@ -37,6 +37,7 @@ import {
profilingPervCPUWattArm64,
profilingAWSCostDiscountRate,
profilingCostPervCPUPerHour,
enableInfrastructureProfilingIntegration,
} from '../common/ui_settings_keys';
const betaLabel = i18n.translate('xpack.observability.uiSettings.betaLabel', {
@ -236,6 +237,24 @@ export const uiSettings: Record<string, UiSettings> = {
}),
schema: schema.boolean(),
},
[enableInfrastructureProfilingIntegration]: {
category: [observabilityFeatureId],
name: i18n.translate('xpack.observability.enableInfrastructureProfilingIntegration', {
defaultMessage: 'Universal Profiling integration in Infrastructure',
}),
value: true,
description: i18n.translate(
'xpack.observability.enableInfrastructureProfilingIntegrationDescription',
{
defaultMessage:
'{betaLabel} Enable Universal Profiling integration in the Infrastructure app.',
values: {
betaLabel: `<em>[${betaLabel}]</em>`,
},
}
),
schema: schema.boolean(),
},
[enableAwsLambdaMetrics]: {
category: [observabilityFeatureId],
name: i18n.translate('xpack.observability.enableAwsLambdaMetrics', {
@ -415,9 +434,9 @@ export const uiSettings: Record<string, UiSettings> = {
}),
value: 1.7,
description: i18n.translate('xpack.observability.profilingDatacenterPUEUiSettingDescription', {
defaultMessage: `Data center power usage effectiveness (PUE) measures how efficiently a data center uses energy. Defaults to 1.7, the average on-premise data center PUE according to the {uptimeLink} survey
defaultMessage: `Data center power usage effectiveness (PUE) measures how efficiently a data center uses energy. Defaults to 1.7, the average on-premise data center PUE according to the {uptimeLink} survey
</br></br>
You can also use the PUE that corresponds with your cloud provider:
You can also use the PUE that corresponds with your cloud provider:
<ul style="list-style-type: none;margin-left: 4px;">
<li><strong>AWS:</strong> 1.135</li>
<li><strong>GCP:</strong> 1.1</li>
@ -444,7 +463,7 @@ export const uiSettings: Record<string, UiSettings> = {
}),
value: 0.000379069,
description: i18n.translate('xpack.observability.profilingCo2PerKWHUiSettingDescription', {
defaultMessage: `Carbon intensity measures how clean your data center electricity is.
defaultMessage: `Carbon intensity measures how clean your data center electricity is.
Specifically, it measures the average amount of CO2 emitted per kilowatt-hour (kWh) of electricity consumed in a particular region.
Use the cloud carbon footprint {datasheetLink} to update this value according to your region. Defaults to US East (N. Virginia).`,
values: {

View file

@ -7,6 +7,7 @@
import moment from 'moment';
import expect from '@kbn/expect';
import { enableInfrastructureProfilingIntegration } from '@kbn/observability-plugin/common';
import { FtrProviderContext } from '../../ftr_provider_context';
import { DATES, NODE_DETAILS_PATH, DATE_PICKER_FORMAT } from './constants';
@ -67,6 +68,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await browser.refresh();
};
const setInfrastructureProfilingIntegrationUiSetting = async (value: boolean = true) => {
await kibanaServer.uiSettings.update({ [enableInfrastructureProfilingIntegration]: value });
await browser.refresh();
await pageObjects.header.waitUntilLoadingHasFinished();
};
describe('Node Details', () => {
describe('#With Asset Details', () => {
before(async () => {
@ -190,6 +197,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await pageObjects.header.waitUntilLoadingHasFinished();
await pageObjects.assetDetails.overviewAlertsTitleExists();
});
it('shows the CPU Profiling prompt if UI setting for Profiling integration is enabled', async () => {
await setInfrastructureProfilingIntegrationUiSetting(true);
await pageObjects.assetDetails.cpuProfilingPromptExists();
});
it('hides the CPU Profiling prompt if UI setting for Profiling integration is disabled', async () => {
await setInfrastructureProfilingIntegrationUiSetting(false);
await pageObjects.assetDetails.cpuProfilingPromptMissing();
});
});
describe('Metadata Tab', () => {
@ -312,6 +329,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
});
describe('Profiling tab', () => {
it('shows the Profiling tab if Profiling integration UI setting is enabled', async () => {
await setInfrastructureProfilingIntegrationUiSetting(true);
await pageObjects.assetDetails.profilingTabExists();
});
it('hides the Profiling tab if Profiling integration UI setting is disabled', async () => {
await setInfrastructureProfilingIntegrationUiSetting(false);
await pageObjects.assetDetails.profilingTabMissing();
});
});
describe('Host with alerts and no processes', () => {
before(async () => {
await navigateToNodeDetails('demo-stack-mysql-01', 'demo-stack-mysql-01');

View file

@ -62,6 +62,22 @@ export function AssetDetailsProvider({ getService }: FtrProviderContext) {
return testSubjects.click('infraAssetDetailsMetadataShowAllButton');
},
async cpuProfilingPromptExists() {
return await testSubjects.existOrFail('infraAssetDetailsCPUProfilingPrompt');
},
async cpuProfilingPromptMissing() {
return await testSubjects.missingOrFail('infraAssetDetailsCPUProfilingPrompt');
},
async profilingTabExists() {
return await testSubjects.existOrFail('infraAssetDetailsProfilingTab');
},
async profilingTabMissing() {
return await testSubjects.missingOrFail('infraAssetDetailsProfilingTab');
},
// Metadata
async clickMetadataTab() {
return testSubjects.click('infraAssetDetailsMetadataTab');