mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[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:
parent
fd604538ca
commit
1f7a383b7b
9 changed files with 117 additions and 22 deletions
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) => ({
|
||||
|
|
|
@ -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'),
|
||||
},
|
||||
];
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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 |
Loading…
Add table
Add a link
Reference in a new issue