mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Integrate Profiling with APM] Navigate from the transaction details view into the Profiling (#159686)
- The new profiling items will be only visible when the profiling plugin has been already installed. Otherwise, these are going to be hidden. - The profiling plugin exposes three new Locators to facilitate the navigation to the Flamegraph, TopN functions and Stacktraces pages. - Add `new` badge property on the section component <img width="486" alt="Screenshot 2023-06-14 at 1 55 09 PM" src="6e353bfc
-050c-4294-a4e4-fc46205d5d0e">234863a4
-0d99-4140-a5b5-702896b2c4a3ee1635bd
-5127-41d6-b434-4cee9b5ebe9246ec9bb7
-2cd0-43fc-9a1e-0d6eef70612f --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b22dd68d39
commit
d118fb4ba4
18 changed files with 267 additions and 15 deletions
|
@ -102,7 +102,7 @@ pageLoadAssetSize:
|
|||
osquery: 107090
|
||||
painlessLab: 179748
|
||||
presentationUtil: 58834
|
||||
profiling: 18628
|
||||
profiling: 36694
|
||||
remoteClusters: 51327
|
||||
reporting: 57003
|
||||
rollup: 97204
|
||||
|
|
|
@ -46,7 +46,8 @@
|
|||
"taskManager",
|
||||
"usageCollection",
|
||||
"customIntegrations", // Move this to requiredPlugins after completely migrating from the Tutorials Home App
|
||||
"licenseManagement"
|
||||
"licenseManagement",
|
||||
"profiling"
|
||||
],
|
||||
"requiredBundles": [
|
||||
"advancedSettings",
|
||||
|
|
|
@ -12,13 +12,14 @@ import { isEmpty, pickBy } from 'lodash';
|
|||
import moment from 'moment';
|
||||
import url from 'url';
|
||||
import type { InfraLocators } from '@kbn/infra-plugin/common/locators';
|
||||
import type { ProfilingLocators } from '@kbn/profiling-plugin/public';
|
||||
import type { Transaction } from '../../../../typings/es_schemas/ui/transaction';
|
||||
import { getDiscoverHref } from '../links/discover_links/discover_link';
|
||||
import { getDiscoverQuery } from '../links/discover_links/discover_transaction_link';
|
||||
import { getInfraHref } from '../links/infra_link';
|
||||
import { fromQuery } from '../links/url_helpers';
|
||||
import { SectionRecord, getNonEmptySections, Action } from './sections_helper';
|
||||
import { TRACE_ID } from '../../../../common/es_fields/apm';
|
||||
import { HOST_NAME, TRACE_ID } from '../../../../common/es_fields/apm';
|
||||
import { ApmRouter } from '../../routing/apm_route_config';
|
||||
|
||||
function getInfraMetricsQuery(transaction: Transaction) {
|
||||
|
@ -38,6 +39,7 @@ export const getSections = ({
|
|||
apmRouter,
|
||||
infraLocators,
|
||||
infraLinksAvailable,
|
||||
profilingLocators,
|
||||
}: {
|
||||
transaction?: Transaction;
|
||||
basePath: IBasePath;
|
||||
|
@ -45,6 +47,7 @@ export const getSections = ({
|
|||
apmRouter: ApmRouter;
|
||||
infraLocators: InfraLocators;
|
||||
infraLinksAvailable: boolean;
|
||||
profilingLocators?: ProfilingLocators;
|
||||
}) => {
|
||||
if (!transaction) return [];
|
||||
const hostName = transaction.host?.hostname;
|
||||
|
@ -163,6 +166,42 @@ export const getSections = ({
|
|||
}),
|
||||
condition: !!hostName,
|
||||
},
|
||||
{
|
||||
key: 'hostProfilingFlamegraph',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.transactionActionMenu.showHostProfilingFlamegraphLinkLabel',
|
||||
{ defaultMessage: 'Host flamegraph' }
|
||||
),
|
||||
href: profilingLocators?.flamegraphLocator.getRedirectUrl({
|
||||
kuery: `${HOST_NAME}: "${hostName}"`,
|
||||
}),
|
||||
condition: !!hostName && !!profilingLocators,
|
||||
showNewBadge: true,
|
||||
},
|
||||
{
|
||||
key: 'hostProfilingTopNFunctions',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.transactionActionMenu.showHostProfilingTopNFunctionsLinkLabel',
|
||||
{ defaultMessage: 'Host topN functions' }
|
||||
),
|
||||
href: profilingLocators?.topNFunctionsLocator.getRedirectUrl({
|
||||
kuery: `${HOST_NAME}: "${hostName}"`,
|
||||
}),
|
||||
condition: !!hostName && !!profilingLocators,
|
||||
showNewBadge: true,
|
||||
},
|
||||
{
|
||||
key: 'hostProfilingStacktraces',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.transactionActionMenu.showHostProfilingStacktracesLinkLabel',
|
||||
{ defaultMessage: 'Host stacktraces' }
|
||||
),
|
||||
href: profilingLocators?.stacktracesLocator.getRedirectUrl({
|
||||
kuery: `${HOST_NAME}: "${hostName}"`,
|
||||
}),
|
||||
condition: !!hostName && !!profilingLocators,
|
||||
showNewBadge: true,
|
||||
},
|
||||
];
|
||||
|
||||
const logActions: Action[] = [
|
||||
|
|
|
@ -14,6 +14,7 @@ export interface Action {
|
|||
href?: string;
|
||||
onClick?: (event: MouseEvent) => void;
|
||||
condition: boolean;
|
||||
showNewBadge?: boolean;
|
||||
}
|
||||
|
||||
interface Section {
|
||||
|
|
|
@ -7,17 +7,18 @@
|
|||
|
||||
import { EuiButton } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ObservabilityTriggerId } from '@kbn/observability-shared-plugin/common';
|
||||
import {
|
||||
ActionMenu,
|
||||
ActionMenuDivider,
|
||||
getContextMenuItemsFromActions,
|
||||
Section,
|
||||
SectionLink,
|
||||
SectionLinks,
|
||||
SectionSubtitle,
|
||||
SectionTitle,
|
||||
} from '@kbn/observability-shared-plugin/public';
|
||||
import { ObservabilityTriggerId } from '@kbn/observability-shared-plugin/common';
|
||||
import { getContextMenuItemsFromActions } from '@kbn/observability-shared-plugin/public';
|
||||
import { ProfilingLocators } from '@kbn/profiling-plugin/public';
|
||||
import React, { useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
|
@ -27,6 +28,7 @@ import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_
|
|||
import { useLicenseContext } from '../../../context/license/use_license_context';
|
||||
import { useApmFeatureFlag } from '../../../hooks/use_apm_feature_flag';
|
||||
import { useApmRouter } from '../../../hooks/use_apm_router';
|
||||
import { useProfilingPlugin } from '../../../hooks/use_profiling_plugin';
|
||||
import { CustomLinkMenuSection } from './custom_link_menu_section';
|
||||
import { getSections } from './sections';
|
||||
|
||||
|
@ -63,6 +65,9 @@ export function TransactionActionMenu({ transaction, isLoading }: Props) {
|
|||
|
||||
const [isActionPopoverOpen, setIsActionPopoverOpen] = useState(false);
|
||||
|
||||
const { isProfilingPluginInitialized, profilingLocators } =
|
||||
useProfilingPlugin();
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActionMenu
|
||||
|
@ -72,7 +77,7 @@ export function TransactionActionMenu({ transaction, isLoading }: Props) {
|
|||
anchorPosition="downRight"
|
||||
button={
|
||||
<ActionMenuButton
|
||||
isLoading={isLoading}
|
||||
isLoading={isLoading || isProfilingPluginInitialized === undefined}
|
||||
onClick={() =>
|
||||
setIsActionPopoverOpen(
|
||||
(prevIsActionPopoverOpen) => !prevIsActionPopoverOpen
|
||||
|
@ -81,14 +86,23 @@ export function TransactionActionMenu({ transaction, isLoading }: Props) {
|
|||
/>
|
||||
}
|
||||
>
|
||||
<ActionMenuSections transaction={transaction} />
|
||||
<ActionMenuSections
|
||||
transaction={transaction}
|
||||
profilingLocators={profilingLocators}
|
||||
/>
|
||||
{hasGoldLicense && <CustomLinkMenuSection transaction={transaction} />}
|
||||
</ActionMenu>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ActionMenuSections({ transaction }: { transaction?: Transaction }) {
|
||||
function ActionMenuSections({
|
||||
transaction,
|
||||
profilingLocators,
|
||||
}: {
|
||||
transaction?: Transaction;
|
||||
profilingLocators?: ProfilingLocators;
|
||||
}) {
|
||||
const {
|
||||
core,
|
||||
uiActions,
|
||||
|
@ -108,6 +122,7 @@ function ActionMenuSections({ transaction }: { transaction?: Transaction }) {
|
|||
apmRouter,
|
||||
infraLocators: locators,
|
||||
infraLinksAvailable,
|
||||
profilingLocators,
|
||||
});
|
||||
|
||||
const externalMenuItems = useAsync(() => {
|
||||
|
@ -156,6 +171,7 @@ function ActionMenuSections({ transaction }: { transaction?: Transaction }) {
|
|||
label={action.label}
|
||||
href={action.href}
|
||||
onClick={action.onClick}
|
||||
showNewBadge={action.showNewBadge}
|
||||
/>
|
||||
))}
|
||||
</SectionLinks>
|
||||
|
|
35
x-pack/plugins/apm/public/hooks/use_profiling_plugin.tsx
Normal file
35
x-pack/plugins/apm/public/hooks/use_profiling_plugin.tsx
Normal file
|
@ -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 { useEffect, useState } from 'react';
|
||||
import { useApmPluginContext } from '../context/apm_plugin/use_apm_plugin_context';
|
||||
|
||||
export function useProfilingPlugin() {
|
||||
const { plugins } = useApmPluginContext();
|
||||
const [isProfilingPluginInitialized, setIsProfilingPluginInitialized] =
|
||||
useState<boolean | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchIsProfilingSetup() {
|
||||
if (!plugins.profiling) {
|
||||
setIsProfilingPluginInitialized(false);
|
||||
return;
|
||||
}
|
||||
const resp = await plugins.profiling.hasSetup();
|
||||
setIsProfilingPluginInitialized(resp);
|
||||
}
|
||||
|
||||
fetchIsProfilingSetup();
|
||||
}, [plugins.profiling]);
|
||||
|
||||
return {
|
||||
isProfilingPluginInitialized,
|
||||
profilingLocators: isProfilingPluginInitialized
|
||||
? plugins.profiling?.locators
|
||||
: undefined,
|
||||
};
|
||||
}
|
|
@ -62,6 +62,10 @@ import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
|||
import { UiActionsStart, UiActionsSetup } from '@kbn/ui-actions-plugin/public';
|
||||
import { ObservabilityTriggerId } from '@kbn/observability-shared-plugin/common';
|
||||
import { LicenseManagementUIPluginSetup } from '@kbn/license-management-plugin/public';
|
||||
import {
|
||||
ProfilingPluginSetup,
|
||||
ProfilingPluginStart,
|
||||
} from '@kbn/profiling-plugin/public';
|
||||
import {
|
||||
DiscoverStart,
|
||||
DiscoverSetup,
|
||||
|
@ -98,6 +102,7 @@ export interface ApmPluginSetupDeps {
|
|||
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
|
||||
share: SharePluginSetup;
|
||||
uiActions: UiActionsSetup;
|
||||
profiling?: ProfilingPluginSetup;
|
||||
}
|
||||
|
||||
export interface ApmPluginStartDeps {
|
||||
|
@ -124,6 +129,7 @@ export interface ApmPluginStartDeps {
|
|||
storage: IStorageWrapper;
|
||||
lens: LensPublicStart;
|
||||
uiActions: UiActionsStart;
|
||||
profiling?: ProfilingPluginStart;
|
||||
}
|
||||
|
||||
const servicesTitle = i18n.translate('xpack.apm.navigation.servicesTitle', {
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
"@kbn/dashboard-plugin",
|
||||
"@kbn/controls-plugin",
|
||||
"@kbn/core-http-server",
|
||||
"@kbn/profiling-plugin",
|
||||
"@kbn/logs-shared-plugin",
|
||||
"@kbn/unified-field-list",
|
||||
"@kbn/slo-schema",
|
||||
|
|
|
@ -11,10 +11,14 @@ import {
|
|||
EuiSpacer,
|
||||
EuiListGroupItem,
|
||||
EuiListGroupItemProps,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiBadge,
|
||||
} from '@elastic/eui';
|
||||
import React, { ReactNode } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { EuiListGroupProps } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export function SectionTitle({ children }: { children?: ReactNode }) {
|
||||
return (
|
||||
|
@ -40,7 +44,7 @@ export function SectionSubtitle({ children }: { children?: ReactNode }) {
|
|||
|
||||
export function SectionLinks({ children, ...props }: { children?: ReactNode } & EuiListGroupProps) {
|
||||
return (
|
||||
<EuiListGroup {...props} flush={true} bordered={false}>
|
||||
<EuiListGroup {...props} size={'s'} color={'primary'} flush={true} bordered={false}>
|
||||
{children}
|
||||
</EuiListGroup>
|
||||
);
|
||||
|
@ -58,6 +62,24 @@ export const Section = styled.div`
|
|||
`;
|
||||
|
||||
export type SectionLinkProps = EuiListGroupItemProps;
|
||||
export function SectionLink(props: SectionLinkProps) {
|
||||
return <EuiListGroupItem style={{ padding: 0 }} size={'xs'} {...props} />;
|
||||
export function SectionLink({
|
||||
showNewBadge,
|
||||
...props
|
||||
}: SectionLinkProps & { showNewBadge?: boolean }) {
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem>
|
||||
<EuiListGroupItem style={{ padding: 0 }} size={'xs'} {...props} />
|
||||
</EuiFlexItem>
|
||||
{showNewBadge && (
|
||||
<EuiFlexItem grow={false} style={{ justifyContent: 'center' }}>
|
||||
<EuiBadge color="accent">
|
||||
{i18n.translate('xpack.observabilityShared.sectionLink.newLabel', {
|
||||
defaultMessage: 'New',
|
||||
})}
|
||||
</EuiBadge>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { merge } from 'lodash';
|
||||
import { RecursivePartial } from '@kbn/apm-plugin/typings/common';
|
||||
import type { RecursivePartial } from '@elastic/eui';
|
||||
|
||||
export interface SetupState {
|
||||
cloud: {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
"observability",
|
||||
"observabilityShared",
|
||||
"unifiedSearch",
|
||||
"share"
|
||||
],
|
||||
"requiredBundles": [
|
||||
"kibanaReact",
|
||||
|
|
|
@ -6,7 +6,12 @@
|
|||
*/
|
||||
|
||||
import { ProfilingPlugin } from './plugin';
|
||||
import type { ProfilingPluginSetup, ProfilingPluginStart } from './plugin';
|
||||
|
||||
export function plugin() {
|
||||
return new ProfilingPlugin();
|
||||
}
|
||||
|
||||
export type { ProfilingPluginSetup, ProfilingPluginStart };
|
||||
|
||||
export type ProfilingLocators = ProfilingPluginSetup['locators'];
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 qs from 'query-string';
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
|
||||
|
||||
export interface FlamegraphLocatorParams extends SerializableRecord {
|
||||
kuery?: string;
|
||||
rangeFrom?: string;
|
||||
rangeTo?: string;
|
||||
}
|
||||
|
||||
export type FlamegraphLocator = LocatorPublic<FlamegraphLocatorParams>;
|
||||
|
||||
export class FlamegraphLocatorDefinition implements LocatorDefinition<FlamegraphLocatorParams> {
|
||||
public readonly id = 'flamegraphLocator';
|
||||
|
||||
public readonly getLocation = async ({ rangeFrom, rangeTo, kuery }: FlamegraphLocatorParams) => {
|
||||
const params = { rangeFrom, rangeTo, kuery };
|
||||
return {
|
||||
app: 'profiling',
|
||||
path: `/flamegraphs/flamegraph?${qs.stringify(params)}`,
|
||||
state: {},
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 qs from 'query-string';
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
|
||||
|
||||
export interface StacktracesLocatorParams extends SerializableRecord {
|
||||
kuery?: string;
|
||||
rangeFrom?: string;
|
||||
rangeTo?: string;
|
||||
}
|
||||
|
||||
export type StacktracesLocator = LocatorPublic<StacktracesLocatorParams>;
|
||||
|
||||
export class StacktracesLocatorDefinition implements LocatorDefinition<StacktracesLocatorParams> {
|
||||
public readonly id = 'stacktracesLocator';
|
||||
|
||||
public readonly getLocation = async ({ rangeFrom, rangeTo, kuery }: StacktracesLocatorParams) => {
|
||||
const params = { rangeFrom, rangeTo, kuery };
|
||||
return {
|
||||
app: 'profiling',
|
||||
path: `/stacktraces/threads?${qs.stringify(params)}`,
|
||||
state: {},
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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 qs from 'query-string';
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
|
||||
|
||||
export interface TopNFunctionsLocatorParams extends SerializableRecord {
|
||||
kuery?: string;
|
||||
rangeFrom?: string;
|
||||
rangeTo?: string;
|
||||
}
|
||||
|
||||
export type TopNFunctionsLocator = LocatorPublic<TopNFunctionsLocatorParams>;
|
||||
|
||||
export class TopNFunctionsLocatorDefinition
|
||||
implements LocatorDefinition<TopNFunctionsLocatorParams>
|
||||
{
|
||||
public readonly id = 'topNFunctionsLocator';
|
||||
|
||||
public readonly getLocation = async ({
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
kuery,
|
||||
}: TopNFunctionsLocatorParams) => {
|
||||
const params = { rangeFrom, rangeTo, kuery };
|
||||
return {
|
||||
app: 'profiling',
|
||||
path: `/functions/topn?${qs.stringify(params)}`,
|
||||
state: {},
|
||||
};
|
||||
};
|
||||
}
|
|
@ -14,15 +14,20 @@ import {
|
|||
} from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { NavigationSection } from '@kbn/observability-shared-plugin/public';
|
||||
import { Location } from 'history';
|
||||
import type { Location } from 'history';
|
||||
import { BehaviorSubject, combineLatest, from, map } from 'rxjs';
|
||||
import { FlamegraphLocatorDefinition } from './locators/flamegraph_locator';
|
||||
import { StacktracesLocatorDefinition } from './locators/stacktraces_locator';
|
||||
import { TopNFunctionsLocatorDefinition } from './locators/topn_functions_locator';
|
||||
import { getServices } from './services';
|
||||
import type { ProfilingPluginPublicSetupDeps, ProfilingPluginPublicStartDeps } from './types';
|
||||
|
||||
export type ProfilingPluginSetup = ReturnType<ProfilingPlugin['setup']>;
|
||||
export type ProfilingPluginStart = void;
|
||||
|
||||
export class ProfilingPlugin implements Plugin {
|
||||
public setup(coreSetup: CoreSetup, pluginsSetup: ProfilingPluginPublicSetupDeps) {
|
||||
// Register an application into the side navigation menu
|
||||
|
||||
const links = [
|
||||
{
|
||||
id: 'stacktraces',
|
||||
|
@ -125,6 +130,27 @@ export class ProfilingPlugin implements Plugin {
|
|||
};
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
locators: {
|
||||
flamegraphLocator: pluginsSetup.share.url.locators.create(
|
||||
new FlamegraphLocatorDefinition()
|
||||
),
|
||||
topNFunctionsLocator: pluginsSetup.share.url.locators.create(
|
||||
new TopNFunctionsLocatorDefinition()
|
||||
),
|
||||
stacktracesLocator: pluginsSetup.share.url.locators.create(
|
||||
new StacktracesLocatorDefinition()
|
||||
),
|
||||
},
|
||||
hasSetup: async () => {
|
||||
const response = (await coreSetup.http.get('/api/profiling/v1/setup/es_resources')) as {
|
||||
has_setup: boolean;
|
||||
has_data: boolean;
|
||||
};
|
||||
return response.has_setup;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
} from '@kbn/observability-shared-plugin/public/plugin';
|
||||
import { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { LicensingPluginSetup } from '@kbn/licensing-plugin/public';
|
||||
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
|
||||
export interface ProfilingPluginPublicSetupDeps {
|
||||
observability: ObservabilityPublicSetup;
|
||||
|
@ -27,6 +28,7 @@ export interface ProfilingPluginPublicSetupDeps {
|
|||
data: DataPublicPluginSetup;
|
||||
charts: ChartsPluginSetup;
|
||||
licensing: LicensingPluginSetup;
|
||||
share: SharePluginSetup;
|
||||
}
|
||||
|
||||
export interface ProfilingPluginPublicStartDeps {
|
||||
|
@ -35,4 +37,5 @@ export interface ProfilingPluginPublicStartDeps {
|
|||
dataViews: DataViewsPublicPluginStart;
|
||||
data: DataPublicPluginStart;
|
||||
charts: ChartsPluginStart;
|
||||
share: SharePluginStart;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
"@kbn/share-plugin",
|
||||
"@kbn/observability-shared-plugin",
|
||||
"@kbn/licensing-plugin",
|
||||
"@kbn/apm-plugin",
|
||||
"@kbn/utility-types",
|
||||
// add references to other TypeScript projects the plugin depends on
|
||||
|
||||
// requiredPlugins from ./kibana.json
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue