[Profiling] Add Universal Profiling to O11y overview and Setup guide (#165092)

All pages link to `/profiling/add-data-instructions`

- Observability overview page
<img width="1786" alt="Screenshot 2023-08-29 at 13 45 59"
src="9639341b-7b33-4493-a4f7-5190922a26fc">

- ~~Observability onboarding page~~
<img width="888" alt="Screenshot 2023-08-29 at 14 00 14"
src="77912f5c-cfa4-4ab8-900a-0644cd8176a2">

- Kibana setup guides page
<img width="1424" alt="Screenshot 2023-08-29 at 14 10 43"
src="5b8bf2d5-5583-47ca-93ab-efbb8d774336">

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Cauê Marcondes 2023-09-18 10:16:55 +02:00 committed by GitHub
parent fd604538ca
commit 1f7a383b7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 117 additions and 22 deletions

View file

@ -297,6 +297,33 @@ exports[`guide cards snapshots should render all cards 1`] = `
size="m"
/>
</EuiFlexItem>
<EuiFlexItem
grow={false}
key="5"
>
<GuideCard
activateGuide={[MockFunction]}
activeFilter="all"
card={
Object {
"icon": "visBarHorizontal",
"navigateTo": Object {
"appId": "profiling",
"path": "/add-data-instructions",
},
"order": 15,
"solution": "observability",
"telemetryId": "onboarding--observability--profiling",
"title": "Optimize my workloads with Universal Profiling",
}
}
guidesState={Array []}
navigateToApp={[MockFunction]}
/>
<EuiSpacer
size="m"
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem

View file

@ -170,6 +170,20 @@ export const guideCards: GuideCardConstants[] = [
telemetryId: 'onboarding--observability--synthetics',
order: 14,
},
{
solution: 'observability',
icon: 'visBarHorizontal',
title: i18n.translate(
'guidedOnboardingPackage.gettingStarted.cards.universalProfilingObservability.title',
{ defaultMessage: 'Optimize my workloads with Universal Profiling' }
),
navigateTo: {
appId: 'profiling',
path: '/add-data-instructions',
},
telemetryId: 'onboarding--observability--profiling',
order: 15,
},
{
solution: 'security',
icon: 'securitySignal',

View file

@ -12,3 +12,4 @@ export const UPTIME_APP = 'uptime';
export const APM_APP = 'apm';
export const INFRA_LOGS_APP = 'infra_logs';
export const INFRA_METRICS_APP = 'infra_metrics';
export const UNIVERSAL_PROFILING_APP = 'universal_profiling';

View file

@ -61,7 +61,7 @@ describe('HasDataContextProvider', () => {
const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper });
expect(result.current).toMatchObject({
hasDataMap: {},
hasAnyData: undefined,
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -78,6 +78,7 @@ describe('HasDataContextProvider', () => {
infra_metrics: { hasData: undefined, status: 'success' },
ux: { hasData: undefined, status: 'success' },
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: false,
isAllRequestsComplete: true,
@ -114,8 +115,10 @@ describe('HasDataContextProvider', () => {
const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper });
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: {
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -139,6 +142,7 @@ describe('HasDataContextProvider', () => {
status: 'success',
},
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: false,
isAllRequestsComplete: true,
@ -176,8 +180,8 @@ describe('HasDataContextProvider', () => {
it('hasAnyData returns true apm returns true and all other apps return false', async () => {
const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper });
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: { universal_profiling: { hasData: false, status: 'success' } },
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -203,6 +207,7 @@ describe('HasDataContextProvider', () => {
status: 'success',
},
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: true,
isAllRequestsComplete: true,
@ -240,8 +245,8 @@ describe('HasDataContextProvider', () => {
it('hasAnyData returns true and all apps return true', async () => {
const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper });
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: { universal_profiling: { hasData: false, status: 'success' } },
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -271,6 +276,7 @@ describe('HasDataContextProvider', () => {
status: 'success',
},
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: true,
isAllRequestsComplete: true,
@ -295,8 +301,8 @@ describe('HasDataContextProvider', () => {
wrapper,
});
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: { universal_profiling: { hasData: false, status: 'success' } },
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -314,6 +320,7 @@ describe('HasDataContextProvider', () => {
infra_metrics: { hasData: undefined, status: 'success' },
ux: { hasData: undefined, status: 'success' },
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: true,
isAllRequestsComplete: true,
@ -340,8 +347,8 @@ describe('HasDataContextProvider', () => {
wrapper,
});
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: { universal_profiling: { hasData: false, status: 'success' } },
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -363,6 +370,7 @@ describe('HasDataContextProvider', () => {
infra_metrics: { hasData: undefined, status: 'success' },
ux: { hasData: undefined, status: 'success' },
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: false,
isAllRequestsComplete: true,
@ -406,8 +414,8 @@ describe('HasDataContextProvider', () => {
it('hasAnyData returns true, apm is undefined and all other apps return true', async () => {
const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper });
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: { universal_profiling: { hasData: false, status: 'success' } },
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -434,6 +442,7 @@ describe('HasDataContextProvider', () => {
status: 'success',
},
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: true,
isAllRequestsComplete: true,
@ -484,8 +493,8 @@ describe('HasDataContextProvider', () => {
it('hasAnyData returns false and all apps return undefined', async () => {
const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper });
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: { universal_profiling: { hasData: false, status: 'success' } },
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -503,6 +512,7 @@ describe('HasDataContextProvider', () => {
infra_metrics: { hasData: undefined, status: 'failure' },
ux: { hasData: undefined, status: 'failure' },
alert: { hasData: false, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: false,
isAllRequestsComplete: true,
@ -530,8 +540,8 @@ describe('HasDataContextProvider', () => {
it('returns if alerts are available', async () => {
const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper });
expect(result.current).toEqual({
hasDataMap: {},
hasAnyData: undefined,
hasDataMap: { universal_profiling: { hasData: false, status: 'success' } },
hasAnyData: false,
isAllRequestsComplete: false,
forceUpdate: expect.any(String),
onRefreshTimeRange: expect.any(Function),
@ -548,10 +558,8 @@ describe('HasDataContextProvider', () => {
infra_logs: { hasData: undefined, status: 'success' },
infra_metrics: { hasData: undefined, status: 'success' },
ux: { hasData: undefined, status: 'success' },
alert: {
hasData: true,
status: 'success',
},
alert: { hasData: true, status: 'success' },
universal_profiling: { hasData: false, status: 'success' },
},
hasAnyData: true,
isAllRequestsComplete: true,

View file

@ -16,6 +16,7 @@ import {
APM_APP,
INFRA_LOGS_APP,
INFRA_METRICS_APP,
UNIVERSAL_PROFILING_APP,
UPTIME_APP,
UX_APP,
} from '../constants';
@ -54,6 +55,7 @@ const apps: DataContextApps[] = [
INFRA_METRICS_APP,
UX_APP,
ALERT_APP,
UNIVERSAL_PROFILING_APP,
];
export function HasDataContextProvider({ children }: { children: React.ReactNode }) {
@ -123,6 +125,10 @@ export function HasDataContextProvider({ children }: { children: React.ReactNode
indices: resultInfraMetrics?.indices,
});
break;
case UNIVERSAL_PROFILING_APP:
// Profiling only shows the empty section for now
updateState({ hasData: false });
break;
}
} catch (e) {
setHasDataMap((prevState) => ({

View file

@ -147,5 +147,23 @@ const getEmptySections = ({ http }: { http: HttpSetup }): Section[] => {
}),
href: http.basePath.prepend(paths.observability.rules),
},
{
id: 'universal_profiling',
title: i18n.translate('xpack.observability.emptySection.apps.universalProfiling.title', {
defaultMessage: 'Universal Profiling',
}),
icon: 'logoObservability',
description: i18n.translate(
'xpack.observability.emptySection.apps.universalProfiling.description',
{
defaultMessage:
'Understand what lines of code are consuming compute resources across your entire infrastructure, with minimal overhead and zero instrumentation',
}
),
linkTitle: i18n.translate('xpack.observability.emptySection.apps.universalProfiling.link', {
defaultMessage: 'Install Profiling Host Agent',
}),
href: http.basePath.prepend('/app/profiling/add-data-instructions'),
},
];
};

View file

@ -66,6 +66,10 @@ export interface InfraLogsHasDataResponse {
indices: string;
}
interface UniversalProfilingHasDataResponse {
hasData: boolean;
}
export type FetchData<T extends FetchDataResponse = FetchDataResponse> = (
fetchDataParams: FetchDataParams
) => Promise<T>;
@ -150,12 +154,15 @@ export interface UxFetchDataResponse extends FetchDataResponse {
coreWebVitals: UXMetrics;
}
export type UniversalProfilingDataResponse = FetchDataResponse;
export interface ObservabilityFetchDataResponse {
apm: ApmFetchDataResponse;
infra_metrics: MetricsFetchDataResponse;
infra_logs: LogsFetchDataResponse;
uptime: UptimeFetchDataResponse;
ux: UxFetchDataResponse;
universal_profiling: UniversalProfilingDataResponse;
}
export interface ObservabilityHasDataResponse {
@ -164,4 +171,5 @@ export interface ObservabilityHasDataResponse {
infra_logs: InfraLogsHasDataResponse;
uptime: SyntheticsHasDataResponse;
ux: UXHasDataResponse;
universal_profiling: UniversalProfilingHasDataResponse;
}

View file

@ -17,7 +17,8 @@ export type ObservabilityApp =
| 'observability-overview'
| 'stack_monitoring'
| 'ux'
| 'fleet';
| 'fleet'
| 'universal_profiling';
export type { Coordinates } from '../public/typings/fetch_overview_data';

View file

@ -0,0 +1,12 @@
<svg width="48" height="46" viewBox="0 0 48 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_305_179324)">
<path d="M46 0H2C0.89543 0 0 0.89543 0 2V18C0 19.1046 0.89543 20 2 20H46C47.1046 20 48 19.1046 48 18V2C48 0.89543 47.1046 0 46 0Z" fill="#F04E98"/>
<path d="M20 24H2C0.89543 24 0 24.8954 0 26V44C0 45.1046 0.89543 46 2 46H20C21.1046 46 22 45.1046 22 44V26C22 24.8954 21.1046 24 20 24Z" fill="#FEC514"/>
<path d="M45 25H29C27.8954 25 27 25.8954 27 27V43C27 44.1046 27.8954 45 29 45H45C46.1046 45 47 44.1046 47 43V27C47 25.8954 46.1046 25 45 25Z" stroke="#0077CC"/>
</g>
<defs>
<clipPath id="clip0_305_179324">
<rect width="48" height="46" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 713 B