mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[ObsUX] Add UI Setting for controling Profiling visibility in Infra (#173294)
Closes https://github.com/elastic/kibana/issues/173154
Adds a UI setting to control Infra+Profiling integration from Kibana's
Advanced Settings as well as from the Infra Settings screen.
Note that the plugin config feature flag is still there because I
realized we need it to disable Profiling integration in serverless.
2a5ace9d
-9e18-49a4-be95-c722f24072a7
### How to test
* Make sure profiling is enabled in `kibana.dev.yml`
```
xpack.profiling.enabled: true
```
* Start kibana in traditional mode, go to Infra Settings
* Make sure there is the new toggle for Profiling integration and it's
on
* Go to one of your host's details and make sure you see the profiling
tab
* Toggle the Profiling integration setting off and check that the tap in
host details is not visible
* Start kibana in serverless mode
* Make sure there is no new setting neither in Infra Settings nor in
Advanced Settings
* Make sure Profiling tab is not visible in host details
---------
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
4fc4dfbbda
commit
c627907733
14 changed files with 152 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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.' },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -32,6 +32,7 @@ export {
|
|||
apmTraceExplorerTab,
|
||||
apmLabsButton,
|
||||
enableInfrastructureHostsView,
|
||||
enableInfrastructureProfilingIntegration,
|
||||
enableAwsLambdaMetrics,
|
||||
enableAgentExplorerView,
|
||||
apmAWSLambdaPriceFactor,
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue