Skip to content

Commit

Permalink
[8.16] [Observability Onboarding] Change CTA for System integration i…
Browse files Browse the repository at this point in the history
…n Auto Detect (elastic#197836) (elastic#199435)

# Backport

This will backport the following commits from `main` to `8.16`:
- [[Observability Onboarding] Change CTA for System integration in Auto
Detect (elastic#197836)](elastic#197836)

<!--- Backport version: 8.9.8 -->

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

<!--BACKPORT [{"author":{"name":"Mykola
Harmash","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-30T10:54:15Z","message":"[Observability
Onboarding] Change CTA for System integration in Auto Detect
(elastic#197836)\n\nCloses
elastic/observability-dev#4053 🔒\r\n\r\n* Adds
an option to specify metadata for integrations installed
from\r\nregistry as a third parameter in the TSV provided to
the\r\n`/integrations/install` endpoint. For now only `system`
integration has\r\nmetadata with a hostname, but it's made generic to
support other\r\nintegrations when needed.\r\n* Changes CTA for the
System integration to point to the Host details\r\n* Adds sorting in the
detected integrations in the UI to alway show\r\nSystem integration at
the
top","sha":"0ee968480cac02640939a552276aaf4213fbd43d","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport
missing","v9.0.0","backport:prev-major","ci:project-deploy-observability"],"number":197836,"url":"https://github.com/elastic/kibana/pull/197836","mergeCommit":{"message":"[Observability
Onboarding] Change CTA for System integration in Auto Detect
(elastic#197836)\n\nCloses
elastic/observability-dev#4053 🔒\r\n\r\n* Adds
an option to specify metadata for integrations installed
from\r\nregistry as a third parameter in the TSV provided to
the\r\n`/integrations/install` endpoint. For now only `system`
integration has\r\nmetadata with a hostname, but it's made generic to
support other\r\nintegrations when needed.\r\n* Changes CTA for the
System integration to point to the Host details\r\n* Adds sorting in the
detected integrations in the UI to alway show\r\nSystem integration at
the
top","sha":"0ee968480cac02640939a552276aaf4213fbd43d"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/197836","number":197836,"mergeCommit":{"message":"[Observability
Onboarding] Change CTA for System integration in Auto Detect
(elastic#197836)\n\nCloses
elastic/observability-dev#4053 🔒\r\n\r\n* Adds
an option to specify metadata for integrations installed
from\r\nregistry as a third parameter in the TSV provided to
the\r\n`/integrations/install` endpoint. For now only `system`
integration has\r\nmetadata with a hostname, but it's made generic to
support other\r\nintegrations when needed.\r\n* Changes CTA for the
System integration to point to the Host details\r\n* Adds sorting in the
detected integrations in the UI to alway show\r\nSystem integration at
the
top","sha":"0ee968480cac02640939a552276aaf4213fbd43d"}},{"url":"https://github.com/elastic/kibana/pull/199133","number":199133,"branch":"8.x","state":"OPEN"}]}]
BACKPORT-->
  • Loading branch information
mykolaharmash authored Nov 12, 2024
1 parent bf1087e commit 367d479
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from '@kbn/deeplinks-observability/locators';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { DASHBOARD_APP_LOCATOR } from '@kbn/deeplinks-analytics';
import { ASSET_DETAILS_LOCATOR_ID } from '@kbn/observability-shared-plugin/common';
import { getAutoDetectCommand } from './get_auto_detect_command';
import { DASHBOARDS, useOnboardingFlow } from './use_onboarding_flow';
import { ProgressIndicator } from '../shared/progress_indicator';
Expand Down Expand Up @@ -66,6 +67,7 @@ export const AutoDetectPanel: FunctionComponent = () => {
(integration) => integration.installSource === 'custom'
);
const dashboardLocator = share.url.locators.get(DASHBOARD_APP_LOCATOR);
const assetDetailsLocator = share.url.locators.get(ASSET_DETAILS_LOCATOR_ID);

return (
<EuiPanel hasBorder paddingSize="xl">
Expand Down Expand Up @@ -147,88 +149,133 @@ export const AutoDetectPanel: FunctionComponent = () => {
installedIntegrations.length > 0 ? (
<>
<EuiSpacer />
{registryIntegrations.map((integration) => (
<AccordionWithIcon
key={integration.pkgName}
id={`${accordionId}_${integration.pkgName}`}
icon={
isSupportedLogo(integration.pkgName) ? (
<LogoIcon size="l" logo={integration.pkgName} />
) : (
<EuiIcon type="desktop" size="l" />
)
}
title={i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.h3.getStartedWithNginxLabel',
{
defaultMessage: 'Get started with {title}',
values: { title: integration.title },
}
)}
isDisabled={status !== 'dataReceived'}
initialIsOpen
>
<GetStartedPanel
onboardingFlowType="auto-detect"
dataset={integration.pkgName}
onboardingId={data?.onboardingFlow?.id}
telemetryEventContext={{
autoDetect: {
installSource: integration.installSource,
pkgVersion: integration.pkgVersion,
title: integration.title,
},
}}
integration={integration.pkgName}
newTab
isLoading={status !== 'dataReceived'}
actionLinks={integration.kibanaAssets
.filter((asset) => asset.type === 'dashboard')
.map((asset) => {
const dashboard = DASHBOARDS[asset.id as keyof typeof DASHBOARDS];
const href =
dashboardLocator?.getRedirectUrl({
dashboardId: asset.id,
}) ?? '';
{registryIntegrations
.slice()
/**
* System integration should always be on top
*/
.sort((a, b) => (a.pkgName === 'system' ? -1 : 0))
.map((integration) => {
let actionLinks;

return {
id: asset.id,
title:
dashboard.type === 'metrics'
? i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreMetricsDataTitle',
{
defaultMessage:
'Overview your metrics data with this pre-made dashboard',
}
)
: i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreLogsDataTitle',
switch (integration.pkgName) {
case 'system':
actionLinks =
assetDetailsLocator !== undefined
? [
{
id: 'inventory-host-details',
title: i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.systemOverviewTitle',
{
defaultMessage:
'Overview your logs data with this pre-made dashboard',
'Overview your system health within the Hosts Inventory',
}
),
label:
dashboard.type === 'metrics'
? i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreMetricsDataLabel',
label: i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.systemOverviewLabel',
{
defaultMessage: 'Explore metrics data',
}
)
: i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreLogsDataLabel',
{
defaultMessage: 'Explore logs data',
}
),
href,
};
})}
/>
</AccordionWithIcon>
))}
href: assetDetailsLocator.getRedirectUrl({
assetType: 'host',
assetId: integration.metadata?.hostname,
}),
},
]
: [];
break;
default:
actionLinks =
dashboardLocator !== undefined
? integration.kibanaAssets
.filter((asset) => asset.type === 'dashboard')
.map((asset) => {
const dashboard =
DASHBOARDS[asset.id as keyof typeof DASHBOARDS];
const href = dashboardLocator.getRedirectUrl({
dashboardId: asset.id,
});

return {
id: asset.id,
title:
dashboard.type === 'metrics'
? i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreMetricsDataTitle',
{
defaultMessage:
'Overview your metrics data with this pre-made dashboard',
}
)
: i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreLogsDataTitle',
{
defaultMessage:
'Overview your logs data with this pre-made dashboard',
}
),
label:
dashboard.type === 'metrics'
? i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreMetricsDataLabel',
{
defaultMessage: 'Explore metrics data',
}
)
: i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.exploreLogsDataLabel',
{
defaultMessage: 'Explore logs data',
}
),
href,
};
})
: [];
}

return (
<AccordionWithIcon
key={integration.pkgName}
id={`${accordionId}_${integration.pkgName}`}
icon={
isSupportedLogo(integration.pkgName) ? (
<LogoIcon size="l" logo={integration.pkgName} />
) : (
<EuiIcon type="desktop" size="l" />
)
}
title={i18n.translate(
'xpack.observability_onboarding.autoDetectPanel.h3.getStartedWithNginxLabel',
{
defaultMessage: 'Get started with {title}',
values: { title: integration.title },
}
)}
isDisabled={status !== 'dataReceived'}
initialIsOpen
>
<GetStartedPanel
onboardingFlowType="auto-detect"
dataset={integration.pkgName}
onboardingId={data?.onboardingFlow?.id}
telemetryEventContext={{
autoDetect: {
installSource: integration.installSource,
pkgVersion: integration.pkgVersion,
title: integration.title,
},
}}
integration={integration.pkgName}
newTab
isLoading={status !== 'dataReceived'}
actionLinks={actionLinks}
/>
</AccordionWithIcon>
);
})}
{customIntegrations.length > 0 && (
<AccordionWithIcon
id={`${accordionId}_custom`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,15 @@ install_integrations() {
local install_integrations_api_body_string=""

for item in "${selected_known_integrations_array[@]}"; do
install_integrations_api_body_string+="$item\tregistry\n"
local metadata=""

case "$item" in
"system")
metadata="\t$(hostname | tr '[:upper:]' '[:lower:]')"
;;
esac

install_integrations_api_body_string+="$item\tregistry$metadata\n"
done

for item in "${selected_unknown_log_file_pattern_array[@]}" "${custom_log_file_path_list_array[@]}"; do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,16 @@ const integrationsInstallRoute = createObservabilityOnboardingServerRoute({
},
});

interface InstalledSystemIntegrationMetadata {
hostname: string;
}

type RegistryIntegrationMetadata = InstalledSystemIntegrationMetadata;

export interface RegistryIntegrationToInstall {
pkgName: string;
installSource: 'registry';
metadata?: RegistryIntegrationMetadata;
}
export interface CustomIntegrationToInstall {
pkgName: string;
Expand Down Expand Up @@ -435,6 +442,7 @@ async function ensureInstalledIntegrations(
dataStreams:
packageInfo.data_streams?.map(({ type, dataset }) => ({ type, dataset })) ?? [],
kibanaAssets: pkg.installed_kibana,
metadata: integration.metadata,
};
}

Expand Down Expand Up @@ -489,7 +497,8 @@ async function ensureInstalledIntegrations(
* Example input:
*
* ```text
* system registry
* system registry hostname
* nginx registry
* product_service custom /path/to/access.log
* product_service custom /path/to/error.log
* checkout_service custom /path/to/access.log
Expand All @@ -502,39 +511,36 @@ function parseIntegrationsTSV(tsv: string) {
.trim()
.split('\n')
.map((line) => line.split('\t', 3))
.reduce<Record<string, IntegrationToInstall>>(
(acc, [pkgName, installSource, logFilePath]) => {
const key = `${pkgName}-${installSource}`;
if (installSource === 'registry') {
if (logFilePath) {
throw new Error(`Integration '${pkgName}' does not support a file path`);
}
acc[key] = {
pkgName,
installSource,
};
return acc;
} else if (installSource === 'custom') {
if (!logFilePath) {
throw new Error(`Missing file path for integration: ${pkgName}`);
}
// Append file path if integration is already in the list
const existing = acc[key];
if (existing && existing.installSource === 'custom') {
existing.logFilePaths.push(logFilePath);
return acc;
}
acc[key] = {
pkgName,
installSource,
logFilePaths: [logFilePath],
};
.reduce<Record<string, IntegrationToInstall>>((acc, [pkgName, installSource, parameter]) => {
const key = `${pkgName}-${installSource}`;
if (installSource === 'registry') {
const metadata = parseRegistryIntegrationMetadata(pkgName, parameter);

acc[key] = {
pkgName,
installSource,
metadata,
};
return acc;
} else if (installSource === 'custom') {
if (!parameter) {
throw new Error(`Missing file path for integration: ${pkgName}`);
}
// Append file path if integration is already in the list
const existing = acc[key];
if (existing && existing.installSource === 'custom') {
existing.logFilePaths.push(parameter);
return acc;
}
throw new Error(`Invalid install source: ${installSource}`);
},
{}
)
acc[key] = {
pkgName,
installSource,
logFilePaths: [parameter],
};
return acc;
}
throw new Error(`Invalid install source: ${installSource}`);
}, {})
);
}

Expand All @@ -557,6 +563,22 @@ const generateAgentConfigYAML = ({
});
};

function parseRegistryIntegrationMetadata(
pkgName: string,
parameter: string
): RegistryIntegrationMetadata | undefined {
switch (pkgName) {
case 'system':
if (!parameter) {
throw new Error('Missing hostname for System integration');
}

return { hostname: parameter };
default:
return undefined;
}
}

const generateAgentConfigTar = ({
elasticsearchUrl,
installedIntegrations,
Expand Down
Loading

0 comments on commit 367d479

Please sign in to comment.