Skip to content

Commit

Permalink
[8.x] [Observability Onboarding] Prevent showing duplcated AWS servic…
Browse files Browse the repository at this point in the history
…es in Firehose flow (elastic#201613) (elastic#202894)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Observability Onboarding] Prevent showing duplcated AWS services in
Firehose flow (elastic#201613)](elastic#201613)

<!--- Backport version: 9.4.3 -->

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

<!--BACKPORT [{"author":{"name":"Mykola
Harmash","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-12-04T10:49:47Z","message":"[Observability
Onboarding] Prevent showing duplcated AWS services in Firehose flow
(elastic#201613)\n\nCloses elastic#200931 \r\n\r\nSwitched to using AWS service list
as a base to showing the detected\r\nservices in the UI instead of the
list of populated indices as multiple\r\nindices can be related to a
single service.\r\n\r\n### How to test\r\n\r\n1. Go to Firehose flow
`/observabilityOnboarding/firehose`\r\n2. Open Kibana dev tools in
another tab\r\n3. Ingest documents related into multiple data streams
which related to\r\na single AWS service:\r\n```\r\nPOST
logs-aws.apigateway_logs-default/_doc\r\n{\r\n \"@timestamp\":
\"2024-11-25T13:32:01.000Z\",\r\n \"some\": 111,\r\n
\"aws.kinesis.name\": \"Elastic-CloudwatchLogs\"\r\n}\r\n\r\nPOST
metrics-aws.apigateway_metrics-default/_doc\r\n{\r\n \"@timestamp\":
\"2024-11-25T13:31:01.000Z\",\r\n \"agent\": {\r\n \"type\":
\"firehose\"\r\n },\r\n \"aws\": {\r\n \"cloudwatch\": {\r\n
\"namespace\": \"AWS/ApiGateway\"\r\n },\r\n \"exporter\": {\r\n
\"arn\":
\"arn:aws:cloudwatch:us-west-2:975050175126:metric-stream/Elastic-CloudwatchLogsAndMetricsToFirehose-CloudWatchMetricStream-Nhb4NhzPdL4J\"\r\n
}\r\n },\r\n \"cloud\": {\r\n \"account\": {\r\n \"id\":
\"975050175126\"\r\n },\r\n \"provider\": \"aws\",\r\n \"region\":
\"us-west-2\"\r\n }\r\n}\r\n```\r\n4. Make sure you see only one entry
for the service appear in the\r\nFirehose
flow","sha":"a2fb9b736cd8007a0ba04b9b1051d7988c690b5b","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:prev-minor","backport:prev-major","ci:project-deploy-observability"],"title":"[Observability
Onboarding] Prevent showing duplcated AWS services in Firehose
flow","number":201613,"url":"https://github.com/elastic/kibana/pull/201613","mergeCommit":{"message":"[Observability
Onboarding] Prevent showing duplcated AWS services in Firehose flow
(elastic#201613)\n\nCloses elastic#200931 \r\n\r\nSwitched to using AWS service list
as a base to showing the detected\r\nservices in the UI instead of the
list of populated indices as multiple\r\nindices can be related to a
single service.\r\n\r\n### How to test\r\n\r\n1. Go to Firehose flow
`/observabilityOnboarding/firehose`\r\n2. Open Kibana dev tools in
another tab\r\n3. Ingest documents related into multiple data streams
which related to\r\na single AWS service:\r\n```\r\nPOST
logs-aws.apigateway_logs-default/_doc\r\n{\r\n \"@timestamp\":
\"2024-11-25T13:32:01.000Z\",\r\n \"some\": 111,\r\n
\"aws.kinesis.name\": \"Elastic-CloudwatchLogs\"\r\n}\r\n\r\nPOST
metrics-aws.apigateway_metrics-default/_doc\r\n{\r\n \"@timestamp\":
\"2024-11-25T13:31:01.000Z\",\r\n \"agent\": {\r\n \"type\":
\"firehose\"\r\n },\r\n \"aws\": {\r\n \"cloudwatch\": {\r\n
\"namespace\": \"AWS/ApiGateway\"\r\n },\r\n \"exporter\": {\r\n
\"arn\":
\"arn:aws:cloudwatch:us-west-2:975050175126:metric-stream/Elastic-CloudwatchLogsAndMetricsToFirehose-CloudWatchMetricStream-Nhb4NhzPdL4J\"\r\n
}\r\n },\r\n \"cloud\": {\r\n \"account\": {\r\n \"id\":
\"975050175126\"\r\n },\r\n \"provider\": \"aws\",\r\n \"region\":
\"us-west-2\"\r\n }\r\n}\r\n```\r\n4. Make sure you see only one entry
for the service appear in the\r\nFirehose
flow","sha":"a2fb9b736cd8007a0ba04b9b1051d7988c690b5b"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/201613","number":201613,"mergeCommit":{"message":"[Observability
Onboarding] Prevent showing duplcated AWS services in Firehose flow
(elastic#201613)\n\nCloses elastic#200931 \r\n\r\nSwitched to using AWS service list
as a base to showing the detected\r\nservices in the UI instead of the
list of populated indices as multiple\r\nindices can be related to a
single service.\r\n\r\n### How to test\r\n\r\n1. Go to Firehose flow
`/observabilityOnboarding/firehose`\r\n2. Open Kibana dev tools in
another tab\r\n3. Ingest documents related into multiple data streams
which related to\r\na single AWS service:\r\n```\r\nPOST
logs-aws.apigateway_logs-default/_doc\r\n{\r\n \"@timestamp\":
\"2024-11-25T13:32:01.000Z\",\r\n \"some\": 111,\r\n
\"aws.kinesis.name\": \"Elastic-CloudwatchLogs\"\r\n}\r\n\r\nPOST
metrics-aws.apigateway_metrics-default/_doc\r\n{\r\n \"@timestamp\":
\"2024-11-25T13:31:01.000Z\",\r\n \"agent\": {\r\n \"type\":
\"firehose\"\r\n },\r\n \"aws\": {\r\n \"cloudwatch\": {\r\n
\"namespace\": \"AWS/ApiGateway\"\r\n },\r\n \"exporter\": {\r\n
\"arn\":
\"arn:aws:cloudwatch:us-west-2:975050175126:metric-stream/Elastic-CloudwatchLogsAndMetricsToFirehose-CloudWatchMetricStream-Nhb4NhzPdL4J\"\r\n
}\r\n },\r\n \"cloud\": {\r\n \"account\": {\r\n \"id\":
\"975050175126\"\r\n },\r\n \"provider\": \"aws\",\r\n \"region\":
\"us-west-2\"\r\n }\r\n}\r\n```\r\n4. Make sure you see only one entry
for the service appear in the\r\nFirehose
flow","sha":"a2fb9b736cd8007a0ba04b9b1051d7988c690b5b"}}]}] BACKPORT-->

Co-authored-by: Mykola Harmash <[email protected]>
  • Loading branch information
kibanamachine and mykolaharmash authored Dec 6, 2024
1 parent ba9ba62 commit f55a0aa
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common';
import { AWSIndexName } from '../../../../common/aws_firehose';
import { ObservabilityOnboardingContextValue } from '../../../plugin';

interface AWSServiceGetStartedConfig {
export interface AWSServiceGetStartedConfig {
id: string;
indexNameList: AWSIndexName[];
title: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ import { EuiIcon, EuiSpacer, EuiText, useGeneratedHtmlId } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect, useState } from 'react';
import useInterval from 'react-use/lib/useInterval';
import { union } from 'lodash';
import { unionBy } from 'lodash';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { FormattedMessage } from '@kbn/i18n-react';
import { ObservabilityOnboardingAppServices } from '../../..';
import {
FIREHOSE_CLOUDFORMATION_STACK_NAME,
FIREHOSE_LOGS_STREAM_NAME,
type AWSIndexName,
} from '../../../../common/aws_firehose';
import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher';
import { AccordionWithIcon } from '../shared/accordion_with_icon';
import { GetStartedPanel } from '../shared/get_started_panel';
import { useAWSServiceGetStartedList } from './use_aws_service_get_started_list';
import {
type AWSServiceGetStartedConfig,
useAWSServiceGetStartedList,
} from './use_aws_service_get_started_list';
import { AutoRefreshCallout } from './auto_refresh_callout';
import { ProgressCallout } from './progress_callout';
import { HAS_DATA_FETCH_INTERVAL } from './utils';
Expand All @@ -36,12 +38,12 @@ interface Props {

export function VisualizeData({ onboardingId, selectedCreateStackOption }: Props) {
const accordionId = useGeneratedHtmlId({ prefix: 'accordion' });
const [orderedPopulatedAWSLogsIndexList, setOrderedPopulatedAWSLogsIndexList] = useState<
AWSIndexName[]
const [orderedVisibleAWSServiceList, setOrderedVisibleAWSServiceList] = useState<
AWSServiceGetStartedConfig[]
>([]);
const [shouldShowDataReceivedToast, setShouldShowDataReceivedToast] = useState<boolean>(true);
const {
data: populatedAWSLogsIndexList,
data: populatedAWSIndexList,
status,
refetch,
} = useFetcher((callApi) => {
Expand All @@ -60,12 +62,13 @@ export function VisualizeData({ onboardingId, selectedCreateStackOption }: Props
context: { cloudServiceProvider },
},
} = useKibana<ObservabilityOnboardingAppServices>();
const awsServiceGetStartedConfigList = useAWSServiceGetStartedList();

useEffect(() => {
if (
shouldShowDataReceivedToast &&
Array.isArray(populatedAWSLogsIndexList) &&
populatedAWSLogsIndexList.length > 0
Array.isArray(populatedAWSIndexList) &&
populatedAWSIndexList.length > 0
) {
notifications?.toasts.addSuccess(
{
Expand All @@ -90,17 +93,27 @@ export function VisualizeData({ onboardingId, selectedCreateStackOption }: Props
setShouldShowDataReceivedToast(false);
}

setOrderedPopulatedAWSLogsIndexList((currentList) =>
setOrderedVisibleAWSServiceList((currentList) =>
/**
* Using union() to ensure items in the array are unique
* add stay in the insertion order to keep the order of
* the AWS services in the UI.
* unionBy() ensures uniqueness of the resulting list
* and preserves the order of the first list passed to it,
* which in turn keeps already visible services in the UI
* in place and new services are only appended to the end.
*/
union(currentList, populatedAWSLogsIndexList)
unionBy(
currentList,
awsServiceGetStartedConfigList.filter(({ indexNameList }) =>
indexNameList.some((indexName) => populatedAWSIndexList?.includes(indexName))
),
'id'
)
);
}, [notifications?.toasts, populatedAWSLogsIndexList, shouldShowDataReceivedToast]);

const awsServiceGetStartedConfigList = useAWSServiceGetStartedList();
}, [
awsServiceGetStartedConfigList,
notifications?.toasts,
populatedAWSIndexList,
shouldShowDataReceivedToast,
]);

useInterval(() => {
if (REQUEST_PENDING_STATUS_LIST.includes(status)) {
Expand All @@ -110,7 +123,7 @@ export function VisualizeData({ onboardingId, selectedCreateStackOption }: Props
refetch();
}, HAS_DATA_FETCH_INTERVAL);

if (populatedAWSLogsIndexList === undefined) {
if (populatedAWSIndexList === undefined) {
return null;
}

Expand All @@ -127,56 +140,48 @@ export function VisualizeData({ onboardingId, selectedCreateStackOption }: Props

<EuiSpacer size="m" />

{orderedPopulatedAWSLogsIndexList.length === 0 && <ProgressCallout />}
{orderedPopulatedAWSLogsIndexList.length > 0 && <AutoRefreshCallout />}
{orderedVisibleAWSServiceList.length === 0 && <ProgressCallout />}
{orderedVisibleAWSServiceList.length > 0 && <AutoRefreshCallout />}

<EuiSpacer size="m" />

<div data-test-subj="observabilityOnboardingAWSServiceList">
{orderedPopulatedAWSLogsIndexList.map((indexName, index) => {
const getStartedConfig = awsServiceGetStartedConfigList.find(({ indexNameList }) =>
indexNameList.includes(indexName)
);

if (!getStartedConfig) {
return null;
{orderedVisibleAWSServiceList.map(
({ id, actionLinks, title, logoURL, previewImage }, index) => {
return (
<AccordionWithIcon
data-test-subj={`observabilityOnboardingAWSService-${id}`}
key={id}
id={`${accordionId}_${id}`}
icon={<EuiIcon type={logoURL} size="l" />}
title={title}
initialIsOpen={true}
borders={
index === 0 || index === orderedVisibleAWSServiceList.length - 1
? 'none'
: 'horizontal'
}
>
<GetStartedPanel
onboardingFlowType="firehose"
dataset={id}
telemetryEventContext={{
firehose: {
selectedCreateStackOption,
cloudServiceProvider,
},
}}
integration="aws"
newTab
isLoading={false}
actionLinks={actionLinks}
previewImage={previewImage}
onboardingId={onboardingId}
/>
</AccordionWithIcon>
);
}

const { id, actionLinks, title, logoURL, previewImage } = getStartedConfig;

return (
<AccordionWithIcon
data-test-subj={`observabilityOnboardingAWSService-${id}`}
key={id}
id={`${accordionId}_${id}`}
icon={<EuiIcon type={logoURL} size="l" />}
title={title}
initialIsOpen={true}
borders={
index === 0 || index === orderedPopulatedAWSLogsIndexList.length - 1
? 'none'
: 'horizontal'
}
>
<GetStartedPanel
onboardingFlowType="firehose"
dataset={indexName}
telemetryEventContext={{
firehose: {
selectedCreateStackOption,
cloudServiceProvider,
},
}}
integration="aws"
newTab
isLoading={false}
actionLinks={actionLinks}
previewImage={previewImage}
onboardingId={onboardingId}
/>
</AccordionWithIcon>
);
})}
)}
</div>
</>
);
Expand Down

0 comments on commit f55a0aa

Please sign in to comment.