Skip to content

Commit

Permalink
[Onboarding] Update o11y callout based on create index flow (#206817)
Browse files Browse the repository at this point in the history
## Summary

Update o11y callout in Create index flow based on build Flavor -
Serverless vs Stack

**Changes:** 
1. Serverless & stack - callouts shown for both new onboarding flow and
when there are indices
2. Stack - the o11y callout for "Collect & analyze logs" navigate to
`/app/integrations/browse/observability`
3. Stack - the o11y callout would be "Create an Observability space"
navigated to `/app/management/kibana/spaces/create`
4. FTR for stack search & classic solution  & serverless 


https://github.com/user-attachments/assets/97f45912-8d3e-44d5-9505-508c863f6595



### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
  • Loading branch information
saarikabhasi authored Jan 24, 2025
1 parent a774033 commit ee97316
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { CreateIndexFormState } from '../../types';
import { generateRandomIndexName } from '../../utils/indices';
import { getDefaultCodingLanguage } from '../../utils/language';

import { CreateIndexPanel } from '../shared/create_index_panel';
import { CreateIndexPanel } from '../shared/create_index_panel/create_index_panel';

import { CreateIndexCodeView } from './create_index_code_view';
import { CreateIndexUIView } from './create_index_ui_view';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 React, { useMemo } from 'react';
import { EuiButtonEmpty } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useKibana } from '../../../hooks/use_kibana';

export const CreateIndexCalloutBrowseIntegrationBtn = () => {
const { http } = useKibana().services;

const analyzeLogsIntegration = useMemo(() => {
return http.basePath.prepend('/app/integrations/browse/observability');
}, [http]);

return (
<EuiButtonEmpty
color="text"
iconSide="right"
iconType="popout"
data-test-subj="analyzeLogsBrowseIntegrations"
href={analyzeLogsIntegration}
target="_blank"
>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.logs.browseIntegration.button',
{
defaultMessage: 'Collect and analyze logs',
}
)}
</EuiButtonEmpty>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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 React, { useMemo } from 'react';
import { EuiButtonEmpty } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useKibana } from '../../../hooks/use_kibana';

export const CreateIndexPanelCreateO11ySpaceBtn = () => {
const { http } = useKibana().services;
const o11yCreateSpaceLink = useMemo(() => {
return http.basePath.prepend('/app/management/kibana/spaces/create');
}, [http]);

return (
<EuiButtonEmpty
color="text"
iconSide="right"
iconType="popout"
data-test-subj="createO11ySpaceBtn"
href={o11yCreateSpaceLink}
target="_blank"
>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.createO11ySpace.button',
{
defaultMessage: 'Create an Observability space',
}
)}
</EuiButtonEmpty>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { docLinks } from '../../../common/doc_links';
import { useKibana } from '../../hooks/use_kibana';
import { CreateIndexViewMode } from '../../types';
import { docLinks } from '../../../../common/doc_links';
import { useKibana } from '../../../hooks/use_kibana';
import { CreateIndexViewMode } from '../../../types';
import { CreateIndexCalloutBrowseIntegrationBtn } from './callout_browse_integration_stack';
import { CreateIndexPanelCreateO11ySpaceBtn } from './callout_create_o11y_space_stack';

const WIDTH = '980px';

Expand All @@ -33,7 +35,6 @@ export interface CreateIndexPanelProps {
createIndexView: CreateIndexViewMode;
onChangeView: (id: string) => void;
onClose: () => void;
showCallouts?: boolean;
showSkip?: boolean;
title?: React.ReactNode;
}
Expand All @@ -43,13 +44,14 @@ export const CreateIndexPanel = ({
createIndexView,
onChangeView,
onClose,
showCallouts,
showSkip,
title,
}: CreateIndexPanelProps) => {
const { cloud, http } = useKibana().services;
const { euiTheme } = useEuiTheme();

const isServerless: boolean = cloud?.isServerlessEnabled ?? false;

const o11yTrialLink = useMemo(() => {
if (cloud && cloud.isServerlessEnabled) {
const baseUrl = cloud?.projectsUrl ?? 'https://cloud.elastic.co/projects/';
Expand Down Expand Up @@ -174,85 +176,91 @@ export const CreateIndexPanel = ({
{children}
</EuiFlexGroup>
</EuiPanel>
{showCallouts && (
<>
<EuiSpacer />
<EuiPanel color="transparent">
<EuiTextAlign textAlign="center">
<EuiTitle size="xs">
<h5>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.title',
{
defaultMessage: 'Looking to store your logs or metrics data?',
}
)}
</h5>
</EuiTitle>
</EuiTextAlign>
<EuiSpacer size="m" />
<EuiFlexGroup alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="text"
iconSide="right"
iconType="popout"
data-test-subj="analyzeLogsBtn"
href={docLinks.analyzeLogs}
target="_blank"
>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.logs.button',
{
defaultMessage: 'Collect and analyze logs',
}
)}
</EuiButtonEmpty>
<EuiText color="subdued" size="s" textAlign="center">
<small>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.logs.subTitle',
{
defaultMessage: 'Explore Logstash and Beats',
}
)}
</small>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>or</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="text"
iconSide="right"
iconType="popout"
data-test-subj="startO11yTrialBtn"
href={o11yTrialLink}
target="_blank"
>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.o11yTrial.button',
{
defaultMessage: 'Start an Observability trial',
}
)}
</EuiButtonEmpty>
<EuiText color="subdued" size="s" textAlign="center">
<small>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.o11yTrial.subTitle',
{
defaultMessage: 'Powerful performance monitoring',
}
)}
</small>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</>
)}

<EuiSpacer />
<EuiPanel color="transparent">
<EuiTextAlign textAlign="center">
<EuiTitle size="xs">
<h5>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.title',
{
defaultMessage: 'Looking to store your logs or metrics data?',
}
)}
</h5>
</EuiTitle>
</EuiTextAlign>
<EuiSpacer size="m" />
<EuiFlexGroup alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>
{isServerless ? (
<EuiButtonEmpty
color="text"
iconSide="right"
iconType="popout"
data-test-subj="analyzeLogsBtn"
href={docLinks.analyzeLogs}
target="_blank"
>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.logs.button',
{
defaultMessage: 'Collect and analyze logs',
}
)}
</EuiButtonEmpty>
) : (
<CreateIndexCalloutBrowseIntegrationBtn />
)}

<EuiText color="subdued" size="s" textAlign="center">
<small>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.logs.subTitle',
{
defaultMessage: 'Explore Logstash and Beats',
}
)}
</small>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>or</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
{isServerless ? (
<EuiButtonEmpty
color="text"
iconSide="right"
iconType="popout"
data-test-subj="startO11yTrialBtn"
href={o11yTrialLink}
target="_blank"
>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.o11yTrial.button',
{
defaultMessage: 'Start an Observability trial',
}
)}
</EuiButtonEmpty>
) : (
<CreateIndexPanelCreateO11ySpaceBtn />
)}
<EuiText color="subdued" size="s" textAlign="center">
<small>
{i18n.translate(
'xpack.searchIndices.shared.createIndex.observabilityCallout.o11yTrial.subTitle',
{
defaultMessage: 'Powerful performance monitoring',
}
)}
</small>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiPanel>
{showSkip === true && (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { CreateIndexUIView } from './create_index';
import { CreateIndexCodeView } from '../shared/create_index_code_view';
import { CreateIndexFormState, CreateIndexViewMode } from '../../types';

import { CreateIndexPanel } from '../shared/create_index_panel';
import { CreateIndexPanel } from '../shared/create_index_panel/create_index_panel';
import { useKibana } from '../../hooks/use_kibana';
import { useUserPrivilegesQuery } from '../../hooks/api/use_user_permissions';
import { WorkflowId } from '../../code_examples/workflows';
Expand Down Expand Up @@ -107,7 +107,6 @@ export const ElasticsearchStart: React.FC<ElasticsearchStartProps> = () => {
onChangeView={onChangeView}
onClose={onClose}
showSkip
showCallouts
>
{createIndexView === CreateIndexViewMode.UI && (
<CreateIndexUIView
Expand Down
17 changes: 17 additions & 0 deletions x-pack/test/functional/page_objects/search_start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,22 @@ export function SearchStartProvider({ getService }: FtrProviderContext) {
await testSubjects.missingOrFail('apiKeyHasNotBeenGenerated');
await testSubjects.missingOrFail('apiKeyHasBeenGenerated');
},
async expectAnalyzeLogsIntegrationLink() {
await testSubjects.existOrFail('analyzeLogsBrowseIntegrations');
expect(await testSubjects.getAttribute('analyzeLogsBrowseIntegrations', 'href')).match(
/^https?\:\/\/.*\/app\/integrations\/browse\/observability/
);

expect(await testSubjects.getAttribute('analyzeLogsBrowseIntegrations', 'target')).equal(
'_blank'
);
},
async expectCreateO11ySpaceBtn() {
await testSubjects.existOrFail('createO11ySpaceBtn');
expect(await testSubjects.getAttribute('createO11ySpaceBtn', 'href')).match(
/^https?\:\/\/.*\/app\/management\/kibana\/spaces\/create/
);
expect(await testSubjects.getAttribute('createO11ySpaceBtn', 'target')).equal('_blank');
},
};
}
5 changes: 5 additions & 0 deletions x-pack/test/functional_search/tests/search_start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await searchStart.expectToBeOnMLFileUploadPage();
});

it('should have o11y links', async () => {
await searchStart.expectToBeOnStartPage();
await searchStart.expectAnalyzeLogsIntegrationLink();
await searchStart.expectCreateO11ySpaceBtn();
});
it('should have close button', async () => {
await searchStart.expectToBeOnStartPage();
await searchStart.expectCloseCreateIndexButtonExists();
Expand Down

0 comments on commit ee97316

Please sign in to comment.