mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
* Instrument Snapshot Repositories with UI metrics: * Repository list load * Repository create * Repository update * Repository delete, single * Repository delete, many * Repository show detail panel click * Repository detail panel verify repository button click * Snapshot list load * Snapshot show detail panel click * Snapshot detail panel summary tab click * Snapshot detail panel failed indices tab click * Change detail panel click to link, add footer to snapshot details for close button
This commit is contained in:
parent
25ea8d4ae3
commit
5298adaf78
12 changed files with 177 additions and 26 deletions
|
@ -30,3 +30,18 @@ export enum SNAPSHOT_STATE {
|
|||
PARTIAL = 'PARTIAL',
|
||||
INCOMPATIBLE = 'INCOMPATIBLE',
|
||||
}
|
||||
|
||||
// UI Metric constants
|
||||
export const UIM_APP_NAME = 'snapshot_restore';
|
||||
export const UIM_REPOSITORY_LIST_LOAD = 'repository_list_load';
|
||||
export const UIM_REPOSITORY_CREATE = 'repository_create';
|
||||
export const UIM_REPOSITORY_UPDATE = 'repository_update';
|
||||
export const UIM_REPOSITORY_DELETE = 'repository_delete';
|
||||
export const UIM_REPOSITORY_DELETE_MANY = 'repository_delete_many';
|
||||
export const UIM_REPOSITORY_SHOW_DETAILS_CLICK = 'repository_show_details_click';
|
||||
export const UIM_REPOSITORY_DETAIL_PANEL_VERIFY = 'repository_detail_panel_verify';
|
||||
export const UIM_SNAPSHOT_LIST_LOAD = 'snapshot_list_load';
|
||||
export const UIM_SNAPSHOT_SHOW_DETAILS_CLICK = 'snapshot_show_details_click';
|
||||
export const UIM_SNAPSHOT_DETAIL_PANEL_SUMMARY_TAB = 'snapshot_detail_panel_summary_tab';
|
||||
export const UIM_SNAPSHOT_DETAIL_PANEL_FAILED_INDICES_TAB =
|
||||
'snapshot_detail_panel_failed_indices_tab';
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import React, { Fragment, useEffect } from 'react';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
|
||||
import { Repository } from '../../../../../common/types';
|
||||
import { SectionError, SectionLoading } from '../../../components';
|
||||
import { BASE_PATH } from '../../../constants';
|
||||
import { BASE_PATH, UIM_REPOSITORY_LIST_LOAD } from '../../../constants';
|
||||
import { useAppDependencies } from '../../../index';
|
||||
import { loadRepositories } from '../../../services/http';
|
||||
import { uiMetricService } from '../../../services/ui_metric';
|
||||
|
||||
import { RepositoryDetails } from './repository_details';
|
||||
import { RepositoryTable } from './repository_table';
|
||||
|
@ -40,8 +41,10 @@ export const RepositoryList: React.FunctionComponent<RouteComponentProps<MatchPa
|
|||
request: reload,
|
||||
} = loadRepositories();
|
||||
|
||||
const openRepositoryDetails = (newRepositoryName: Repository['name']) => {
|
||||
history.push(`${BASE_PATH}/repositories/${newRepositoryName}`);
|
||||
const openRepositoryDetailsUrl = (newRepositoryName: Repository['name']): string => {
|
||||
return history.createHref({
|
||||
pathname: `${BASE_PATH}/repositories/${newRepositoryName}`,
|
||||
});
|
||||
};
|
||||
|
||||
const closeRepositoryDetails = () => {
|
||||
|
@ -57,6 +60,12 @@ export const RepositoryList: React.FunctionComponent<RouteComponentProps<MatchPa
|
|||
}
|
||||
};
|
||||
|
||||
// Track component loaded
|
||||
const { trackUiMetric } = uiMetricService;
|
||||
useEffect(() => {
|
||||
trackUiMetric(UIM_REPOSITORY_LIST_LOAD);
|
||||
}, []);
|
||||
|
||||
let content;
|
||||
|
||||
if (loading) {
|
||||
|
@ -124,7 +133,7 @@ export const RepositoryList: React.FunctionComponent<RouteComponentProps<MatchPa
|
|||
<RepositoryTable
|
||||
repositories={repositories || []}
|
||||
reload={reload}
|
||||
openRepositoryDetails={openRepositoryDetails}
|
||||
openRepositoryDetailsUrl={openRepositoryDetailsUrl}
|
||||
onRepositoryDeleted={onRepositoryDeleted}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -20,21 +20,22 @@ import {
|
|||
import { REPOSITORY_TYPES } from '../../../../../../common/constants';
|
||||
import { Repository, RepositoryType } from '../../../../../../common/types';
|
||||
import { RepositoryDeleteProvider } from '../../../../components';
|
||||
import { BASE_PATH } from '../../../../constants';
|
||||
import { BASE_PATH, UIM_REPOSITORY_SHOW_DETAILS_CLICK } from '../../../../constants';
|
||||
import { useAppDependencies } from '../../../../index';
|
||||
import { textService } from '../../../../services/text';
|
||||
import { uiMetricService } from '../../../../services/ui_metric';
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
repositories: Repository[];
|
||||
reload: () => Promise<void>;
|
||||
openRepositoryDetails: (name: Repository['name']) => void;
|
||||
openRepositoryDetailsUrl: (name: Repository['name']) => string;
|
||||
onRepositoryDeleted: (repositoriesDeleted: Array<Repository['name']>) => void;
|
||||
}
|
||||
|
||||
const RepositoryTableUi: React.FunctionComponent<Props> = ({
|
||||
repositories,
|
||||
reload,
|
||||
openRepositoryDetails,
|
||||
openRepositoryDetailsUrl,
|
||||
onRepositoryDeleted,
|
||||
history,
|
||||
}) => {
|
||||
|
@ -42,6 +43,7 @@ const RepositoryTableUi: React.FunctionComponent<Props> = ({
|
|||
core: { i18n },
|
||||
} = useAppDependencies();
|
||||
const { FormattedMessage } = i18n;
|
||||
const { trackUiMetric } = uiMetricService;
|
||||
const [selectedItems, setSelectedItems] = useState<Repository[]>([]);
|
||||
|
||||
const columns = [
|
||||
|
@ -53,7 +55,14 @@ const RepositoryTableUi: React.FunctionComponent<Props> = ({
|
|||
truncateText: true,
|
||||
sortable: true,
|
||||
render: (name: Repository['name'], repository: Repository) => {
|
||||
return <EuiLink onClick={() => openRepositoryDetails(name)}>{name}</EuiLink>;
|
||||
return (
|
||||
<EuiLink
|
||||
onClick={() => trackUiMetric(UIM_REPOSITORY_SHOW_DETAILS_CLICK)}
|
||||
href={openRepositoryDetailsUrl(name)}
|
||||
>
|
||||
{name}
|
||||
</EuiLink>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFlyout,
|
||||
EuiFlyoutBody,
|
||||
EuiFlyoutFooter,
|
||||
EuiFlyoutHeader,
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
|
@ -22,8 +24,13 @@ import { RouteComponentProps, withRouter } from 'react-router-dom';
|
|||
|
||||
import { SectionError, SectionLoading } from '../../../../components';
|
||||
import { useAppDependencies } from '../../../../index';
|
||||
import {
|
||||
UIM_SNAPSHOT_DETAIL_PANEL_SUMMARY_TAB,
|
||||
UIM_SNAPSHOT_DETAIL_PANEL_FAILED_INDICES_TAB,
|
||||
} from '../../../../constants';
|
||||
import { loadSnapshot } from '../../../../services/http';
|
||||
import { linkToRepository } from '../../../../services/navigation';
|
||||
import { uiMetricService } from '../../../../services/ui_metric';
|
||||
import { TabSummary, TabFailures } from './tabs';
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
|
@ -35,6 +42,11 @@ interface Props extends RouteComponentProps {
|
|||
const TAB_SUMMARY = 'summary';
|
||||
const TAB_FAILURES = 'failures';
|
||||
|
||||
const panelTypeToUiMetricMap: { [key: string]: string } = {
|
||||
[TAB_SUMMARY]: UIM_SNAPSHOT_DETAIL_PANEL_SUMMARY_TAB,
|
||||
[TAB_FAILURES]: UIM_SNAPSHOT_DETAIL_PANEL_FAILED_INDICES_TAB,
|
||||
};
|
||||
|
||||
const SnapshotDetailsUi: React.FunctionComponent<Props> = ({
|
||||
repositoryName,
|
||||
snapshotId,
|
||||
|
@ -45,7 +57,7 @@ const SnapshotDetailsUi: React.FunctionComponent<Props> = ({
|
|||
i18n: { FormattedMessage, translate },
|
||||
},
|
||||
} = useAppDependencies();
|
||||
|
||||
const { trackUiMetric } = uiMetricService;
|
||||
const { error, data: snapshotDetails } = loadSnapshot(repositoryName, snapshotId);
|
||||
|
||||
const [activeTab, setActiveTab] = useState<string>(TAB_SUMMARY);
|
||||
|
@ -94,7 +106,10 @@ const SnapshotDetailsUi: React.FunctionComponent<Props> = ({
|
|||
<EuiTabs>
|
||||
{tabOptions.map(tab => (
|
||||
<EuiTab
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
onClick={() => {
|
||||
trackUiMetric(panelTypeToUiMetricMap[tab.id]);
|
||||
setActiveTab(tab.id);
|
||||
}}
|
||||
isSelected={tab.id === activeTab}
|
||||
key={tab.id}
|
||||
data-test-subject={tab.testSubj}
|
||||
|
@ -150,6 +165,26 @@ const SnapshotDetailsUi: React.FunctionComponent<Props> = ({
|
|||
);
|
||||
}
|
||||
|
||||
const renderFooter = () => {
|
||||
return (
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
iconType="cross"
|
||||
flush="left"
|
||||
onClick={onClose}
|
||||
data-test-subj="srSnapshotDetailsFlyoutCloseButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.snapshotRestore.snapshotDetails.closeButtonLabel"
|
||||
defaultMessage="Close"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<EuiFlyout
|
||||
onClose={onClose}
|
||||
|
@ -187,6 +222,7 @@ const SnapshotDetailsUi: React.FunctionComponent<Props> = ({
|
|||
</EuiFlyoutHeader>
|
||||
|
||||
<EuiFlyoutBody data-test-subj="srSnapshotDetailsContent">{content}</EuiFlyoutBody>
|
||||
<EuiFlyoutFooter>{renderFooter()}</EuiFlyoutFooter>
|
||||
</EuiFlyout>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,11 +11,12 @@ import { parse } from 'querystring';
|
|||
import { EuiButton, EuiCallOut, EuiIcon, EuiLink, EuiEmptyPrompt, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import { SectionError, SectionLoading } from '../../../components';
|
||||
import { BASE_PATH } from '../../../constants';
|
||||
import { BASE_PATH, UIM_SNAPSHOT_LIST_LOAD } from '../../../constants';
|
||||
import { useAppDependencies } from '../../../index';
|
||||
import { documentationLinksService } from '../../../services/documentation';
|
||||
import { loadSnapshots } from '../../../services/http';
|
||||
import { linkToRepositories } from '../../../services/navigation';
|
||||
import { uiMetricService } from '../../../services/ui_metric';
|
||||
|
||||
import { SnapshotDetails } from './snapshot_details';
|
||||
import { SnapshotTable } from './snapshot_table';
|
||||
|
@ -45,12 +46,15 @@ export const SnapshotList: React.FunctionComponent<RouteComponentProps<MatchPara
|
|||
request: reload,
|
||||
} = loadSnapshots();
|
||||
|
||||
const openSnapshotDetails = (repositoryNameToOpen: string, snapshotIdToOpen: string) => {
|
||||
history.push(
|
||||
`${BASE_PATH}/snapshots/${encodeURIComponent(repositoryNameToOpen)}/${encodeURIComponent(
|
||||
snapshotIdToOpen
|
||||
)}`
|
||||
);
|
||||
const openSnapshotDetailsUrl = (
|
||||
repositoryNameToOpen: string,
|
||||
snapshotIdToOpen: string
|
||||
): string => {
|
||||
return history.createHref({
|
||||
pathname: `${BASE_PATH}/snapshots/${encodeURIComponent(
|
||||
repositoryNameToOpen
|
||||
)}/${encodeURIComponent(snapshotIdToOpen)}`,
|
||||
});
|
||||
};
|
||||
|
||||
const closeSnapshotDetails = () => {
|
||||
|
@ -69,6 +73,12 @@ export const SnapshotList: React.FunctionComponent<RouteComponentProps<MatchPara
|
|||
}
|
||||
}, []);
|
||||
|
||||
// Track component loaded
|
||||
const { trackUiMetric } = uiMetricService;
|
||||
useEffect(() => {
|
||||
trackUiMetric(UIM_SNAPSHOT_LIST_LOAD);
|
||||
}, []);
|
||||
|
||||
let content;
|
||||
|
||||
if (loading) {
|
||||
|
@ -254,7 +264,7 @@ export const SnapshotList: React.FunctionComponent<RouteComponentProps<MatchPara
|
|||
snapshots={snapshots}
|
||||
repositories={repositories}
|
||||
reload={reload}
|
||||
openSnapshotDetails={openSnapshotDetails}
|
||||
openSnapshotDetailsUrl={openSnapshotDetailsUrl}
|
||||
repositoryFilter={filteredRepository}
|
||||
/>
|
||||
</Fragment>
|
||||
|
|
|
@ -8,17 +8,18 @@ import React from 'react';
|
|||
import { EuiButton, EuiInMemoryTable, EuiLink, Query, EuiLoadingSpinner } from '@elastic/eui';
|
||||
|
||||
import { SnapshotDetails } from '../../../../../../common/types';
|
||||
import { SNAPSHOT_STATE } from '../../../../constants';
|
||||
import { SNAPSHOT_STATE, UIM_SNAPSHOT_SHOW_DETAILS_CLICK } from '../../../../constants';
|
||||
import { useAppDependencies } from '../../../../index';
|
||||
import { formatDate } from '../../../../services/text';
|
||||
import { linkToRepository } from '../../../../services/navigation';
|
||||
import { uiMetricService } from '../../../../services/ui_metric';
|
||||
import { DataPlaceholder } from '../../../../components';
|
||||
|
||||
interface Props {
|
||||
snapshots: SnapshotDetails[];
|
||||
repositories: string[];
|
||||
reload: () => Promise<void>;
|
||||
openSnapshotDetails: (repositoryName: string, snapshotId: string) => void;
|
||||
openSnapshotDetailsUrl: (repositoryName: string, snapshotId: string) => string;
|
||||
repositoryFilter?: string;
|
||||
}
|
||||
|
||||
|
@ -26,7 +27,7 @@ export const SnapshotTable: React.FunctionComponent<Props> = ({
|
|||
snapshots,
|
||||
repositories,
|
||||
reload,
|
||||
openSnapshotDetails,
|
||||
openSnapshotDetailsUrl,
|
||||
repositoryFilter,
|
||||
}) => {
|
||||
const {
|
||||
|
@ -34,6 +35,7 @@ export const SnapshotTable: React.FunctionComponent<Props> = ({
|
|||
i18n: { FormattedMessage, translate },
|
||||
},
|
||||
} = useAppDependencies();
|
||||
const { trackUiMetric } = uiMetricService;
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -44,7 +46,10 @@ export const SnapshotTable: React.FunctionComponent<Props> = ({
|
|||
truncateText: true,
|
||||
sortable: true,
|
||||
render: (snapshotId: string, snapshot: SnapshotDetails) => (
|
||||
<EuiLink onClick={() => openSnapshotDetails(snapshot.repository, snapshotId)}>
|
||||
<EuiLink
|
||||
onClick={() => trackUiMetric(UIM_SNAPSHOT_SHOW_DETAILS_CLICK)}
|
||||
href={openSnapshotDetailsUrl(snapshot.repository, snapshotId)}
|
||||
>
|
||||
{snapshotId}
|
||||
</EuiLink>
|
||||
),
|
||||
|
|
|
@ -5,7 +5,14 @@
|
|||
*/
|
||||
import { API_BASE_PATH } from '../../../../common/constants';
|
||||
import { Repository, EmptyRepository } from '../../../../common/types';
|
||||
import { MINIMUM_TIMEOUT_MS } from '../../constants';
|
||||
import {
|
||||
MINIMUM_TIMEOUT_MS,
|
||||
UIM_REPOSITORY_CREATE,
|
||||
UIM_REPOSITORY_UPDATE,
|
||||
UIM_REPOSITORY_DELETE,
|
||||
UIM_REPOSITORY_DELETE_MANY,
|
||||
UIM_REPOSITORY_DETAIL_PANEL_VERIFY,
|
||||
} from '../../constants';
|
||||
import { httpService } from './http';
|
||||
import { sendRequest, useRequest } from './use_request';
|
||||
|
||||
|
@ -31,6 +38,7 @@ export const verifyRepository = (name: Repository['name']) => {
|
|||
`${API_BASE_PATH}repositories/${encodeURIComponent(name)}/verify`
|
||||
),
|
||||
method: 'get',
|
||||
uimActionType: UIM_REPOSITORY_DETAIL_PANEL_VERIFY,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -47,6 +55,7 @@ export const addRepository = async (newRepository: Repository | EmptyRepository)
|
|||
path: httpService.addBasePath(`${API_BASE_PATH}repositories`),
|
||||
method: 'put',
|
||||
body: newRepository,
|
||||
uimActionType: UIM_REPOSITORY_CREATE,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -57,6 +66,7 @@ export const editRepository = async (editedRepository: Repository | EmptyReposit
|
|||
),
|
||||
method: 'put',
|
||||
body: editedRepository,
|
||||
uimActionType: UIM_REPOSITORY_UPDATE,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -66,5 +76,6 @@ export const deleteRepositories = async (names: Array<Repository['name']>) => {
|
|||
`${API_BASE_PATH}repositories/${names.map(name => encodeURIComponent(name)).join(',')}`
|
||||
),
|
||||
method: 'delete',
|
||||
uimActionType: names.length > 1 ? UIM_REPOSITORY_DELETE_MANY : UIM_REPOSITORY_DELETE,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
*/
|
||||
import { useEffect, useState } from 'react';
|
||||
import { httpService } from './index';
|
||||
import { uiMetricService } from '../ui_metric';
|
||||
|
||||
interface SendRequest {
|
||||
path: string;
|
||||
method: string;
|
||||
body?: any;
|
||||
uimActionType?: string;
|
||||
}
|
||||
|
||||
interface SendRequestResponse {
|
||||
|
@ -17,10 +19,13 @@ interface SendRequestResponse {
|
|||
error: Error;
|
||||
}
|
||||
|
||||
const { trackUiMetric } = uiMetricService;
|
||||
|
||||
export const sendRequest = async ({
|
||||
path,
|
||||
method,
|
||||
body,
|
||||
uimActionType,
|
||||
}: SendRequest): Promise<Partial<SendRequestResponse>> => {
|
||||
try {
|
||||
const response = await httpService.httpClient[method](path, body);
|
||||
|
@ -29,6 +34,11 @@ export const sendRequest = async ({
|
|||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
// Track successful request
|
||||
if (uimActionType) {
|
||||
trackUiMetric(uimActionType);
|
||||
}
|
||||
|
||||
return {
|
||||
data: response.data,
|
||||
};
|
||||
|
@ -45,7 +55,15 @@ interface UseRequest extends SendRequest {
|
|||
timeout?: number;
|
||||
}
|
||||
|
||||
export const useRequest = ({ path, method, body, interval, initialData, timeout }: UseRequest) => {
|
||||
export const useRequest = ({
|
||||
path,
|
||||
method,
|
||||
body,
|
||||
interval,
|
||||
initialData,
|
||||
timeout,
|
||||
uimActionType,
|
||||
}: UseRequest) => {
|
||||
const [error, setError] = useState<null | any>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [data, setData] = useState<any>(initialData);
|
||||
|
@ -62,6 +80,7 @@ export const useRequest = ({ path, method, body, interval, initialData, timeout
|
|||
path,
|
||||
method,
|
||||
body,
|
||||
uimActionType,
|
||||
};
|
||||
|
||||
let response;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
export { uiMetricService } from './ui_metric';
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { UIM_APP_NAME } from '../../constants';
|
||||
|
||||
class UiMetricService {
|
||||
public track: any = () => {};
|
||||
|
||||
public init = (track: any): void => {
|
||||
this.track = track;
|
||||
};
|
||||
|
||||
public trackUiMetric = (actionType: string): any => {
|
||||
return this.track(UIM_APP_NAME, actionType);
|
||||
};
|
||||
}
|
||||
|
||||
export const uiMetricService = new UiMetricService();
|
|
@ -15,13 +15,14 @@ import { breadcrumbService } from './app/services/navigation';
|
|||
import { documentationLinksService } from './app/services/documentation';
|
||||
import { httpService } from './app/services/http';
|
||||
import { textService } from './app/services/text';
|
||||
import { uiMetricService } from './app/services/ui_metric';
|
||||
|
||||
const REACT_ROOT_ID = 'snapshotRestoreReactRoot';
|
||||
|
||||
export class Plugin {
|
||||
public start(core: Core, plugins: Plugins): void {
|
||||
const { i18n, routing, http, chrome, notification, documentation } = core;
|
||||
const { management } = plugins;
|
||||
const { management, uiMetric } = plugins;
|
||||
|
||||
// Register management section
|
||||
const esSection = management.sections.getSection('elasticsearch');
|
||||
|
@ -38,6 +39,7 @@ export class Plugin {
|
|||
textService.init(i18n);
|
||||
breadcrumbService.init(chrome, management.constants.BREADCRUMB);
|
||||
documentationLinksService.init(documentation.esDocBasePath, documentation.esPluginDocBasePath);
|
||||
uiMetricService.init(uiMetric.track);
|
||||
|
||||
const unmountReactApp = (): void => {
|
||||
const elem = document.getElementById(REACT_ROOT_ID);
|
||||
|
|
|
@ -15,6 +15,9 @@ import routes from 'ui/routes';
|
|||
|
||||
import { HashRouter } from 'react-router-dom';
|
||||
|
||||
// @ts-ignore: allow traversal to fail on x-pack build
|
||||
import { trackUiMetric as track } from '../../../../src/legacy/core_plugins/ui_metric/public';
|
||||
|
||||
export interface AppCore {
|
||||
i18n: {
|
||||
[i18nPackage: string]: any;
|
||||
|
@ -57,6 +60,9 @@ export interface Plugins extends AppPlugins {
|
|||
BREADCRUMB: typeof MANAGEMENT_BREADCRUMB;
|
||||
};
|
||||
};
|
||||
uiMetric: {
|
||||
track: typeof track;
|
||||
};
|
||||
}
|
||||
|
||||
export function createShim(): { core: Core; plugins: Plugins } {
|
||||
|
@ -107,6 +113,9 @@ export function createShim(): { core: Core; plugins: Plugins } {
|
|||
BREADCRUMB: MANAGEMENT_BREADCRUMB,
|
||||
},
|
||||
},
|
||||
uiMetric: {
|
||||
track,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue