Skip to content

Commit

Permalink
Apm pages (#113716)
Browse files Browse the repository at this point in the history
* Apm overview page

* APM instances page

* Add APM instance page

* Add ignores on js components

* One more ts-ignore
  • Loading branch information
matschaffer authored Oct 5, 2021
1 parent 8f7dd3f commit dbad35f
Show file tree
Hide file tree
Showing 6 changed files with 355 additions and 6 deletions.
39 changes: 33 additions & 6 deletions x-pack/plugins/monitoring/public/application/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import { ElasticsearchOverviewPage } from './pages/elasticsearch/overview';
import { BeatsOverviewPage } from './pages/beats/overview';
import { BeatsInstancesPage } from './pages/beats/instances';
import { BeatsInstancePage } from './pages/beats/instance';
import { ApmOverviewPage, ApmInstancesPage, ApmInstancePage } from './pages/apm';
import { KibanaOverviewPage } from './pages/kibana/overview';
import { CODE_PATH_ELASTICSEARCH, CODE_PATH_BEATS, CODE_PATH_KIBANA } from '../../common/constants';
import { ElasticsearchNodesPage } from './pages/elasticsearch/nodes_page';
import { ElasticsearchIndicesPage } from './pages/elasticsearch/indices_page';
import { ElasticsearchIndexPage } from './pages/elasticsearch/index_page';
Expand All @@ -33,6 +33,12 @@ import { ElasticsearchNodePage } from './pages/elasticsearch/node_page';
import { ElasticsearchNodeAdvancedPage } from './pages/elasticsearch/node_advanced_page';
import { MonitoringTimeContainer } from './hooks/use_monitoring_time';
import { BreadcrumbContainer } from './hooks/use_breadcrumbs';
import {
CODE_PATH_ELASTICSEARCH,
CODE_PATH_KIBANA,
CODE_PATH_BEATS,
CODE_PATH_APM,
} from '../../common/constants';

export const renderApp = (
core: CoreStart,
Expand Down Expand Up @@ -87,7 +93,6 @@ const MonitoringApp: React.FC<{
/>

{/* ElasticSearch Views */}

<RouteInit
path="/elasticsearch/indices/:index/advanced"
component={ElasticsearchIndexAdvancedPage}
Expand Down Expand Up @@ -137,6 +142,14 @@ const MonitoringApp: React.FC<{
fetchAllClusters={false}
/>

{/* Kibana Views */}
<RouteInit
path="/kibana"
component={KibanaOverviewPage}
codePaths={[CODE_PATH_KIBANA]}
fetchAllClusters={false}
/>

{/* Beats Views */}
<RouteInit
path="/beats/beat/:instance"
Expand All @@ -159,11 +172,25 @@ const MonitoringApp: React.FC<{
fetchAllClusters={false}
/>

{/* Kibana Views */}
{/* APM Views */}
<RouteInit
path="/kibana"
component={KibanaOverviewPage}
codePaths={[CODE_PATH_KIBANA]}
path="/apm/instances/:instance"
component={ApmInstancePage}
codePaths={[CODE_PATH_APM]}
fetchAllClusters={false}
/>

<RouteInit
path="/apm/instances"
component={ApmInstancesPage}
codePaths={[CODE_PATH_APM]}
fetchAllClusters={false}
/>

<RouteInit
path="/apm"
component={ApmOverviewPage}
codePaths={[CODE_PATH_APM]}
fetchAllClusters={false}
/>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 from 'react';
import { i18n } from '@kbn/i18n';
import { PageTemplate } from '../page_template';
import { TabMenuItem, PageTemplateProps } from '../page_template';

export const ApmTemplate: React.FC<PageTemplateProps> = ({ ...props }) => {
const tabs: TabMenuItem[] = [
{
id: 'overview',
label: i18n.translate('xpack.monitoring.apmNavigation.overviewLinkText', {
defaultMessage: 'Overview',
}),
route: '/apm',
},
{
id: 'instances',
label: i18n.translate('xpack.monitoring.apmNavigation.instancesLinkText', {
defaultMessage: 'Instances',
}),
route: '/apm/instances',
},
];

return <PageTemplate {...props} tabs={tabs} product="apm" />;
};
10 changes: 10 additions & 0 deletions x-pack/plugins/monitoring/public/application/pages/apm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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.
*/

export { ApmOverviewPage } from './overview';
export { ApmInstancesPage } from './instances';
export { ApmInstancePage } from './instance';
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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, { useContext, useState, useCallback, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { find } from 'lodash';
import { ComponentProps } from '../../route_init';
import { GlobalStateContext } from '../../global_state_context';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { useCharts } from '../../hooks/use_charts';
import { BreadcrumbContainer } from '../../hooks/use_breadcrumbs';
import { PageTemplate } from '../page_template';
// @ts-ignore
import { ApmServerInstance } from '../../../components/apm/instance';

export const ApmInstancePage: React.FC<ComponentProps> = ({ clusters }) => {
const { instance }: { instance: string } = useParams();

const globalState = useContext(GlobalStateContext);
const { services } = useKibana<{ data: any }>();
const { generate: generateBreadcrumbs } = useContext(BreadcrumbContainer.Context);
const { zoomInfo, onBrush } = useCharts();
const clusterUuid = globalState.cluster_uuid;
const ccs = globalState.ccs;
const cluster = find(clusters, {
cluster_uuid: clusterUuid,
}) as any;
const [data, setData] = useState({} as any);
const [instanceName, setInstanceName] = useState('');

const title = i18n.translate('xpack.monitoring.apm.instance.routeTitle', {
defaultMessage: '{apm} - Instance',
values: {
apm: 'APM server',
},
});

const pageTitle = i18n.translate('xpack.monitoring.apm.instance.pageTitle', {
defaultMessage: 'APM server instance: {instanceName}',
values: {
instanceName,
},
});

useEffect(() => {
if (cluster) {
generateBreadcrumbs(cluster.cluster_name, {
inApm: true,
instance: instanceName,
});
}
}, [cluster, instanceName, generateBreadcrumbs]);

const getPageData = useCallback(async () => {
const bounds = services.data?.query.timefilter.timefilter.getBounds();
const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm/${instance}`;
const response = await services.http?.fetch(url, {
method: 'POST',
body: JSON.stringify({
ccs,
timeRange: {
min: bounds.min.toISOString(),
max: bounds.max.toISOString(),
},
}),
});

setData(response);
setInstanceName(response.apmSummary.name);
}, [ccs, clusterUuid, instance, services.data?.query.timefilter.timefilter, services.http]);

return (
<PageTemplate
title={title}
pageTitle={pageTitle}
getPageData={getPageData}
data-test-subj="apmInstancePage"
>
<ApmServerInstance
summary={data.apmSummary || {}}
metrics={data.metrics || {}}
onBrush={onBrush}
zoomInfo={zoomInfo}
/>
</PageTemplate>
);
};
112 changes: 112 additions & 0 deletions x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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, { useContext, useState, useCallback, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import { find } from 'lodash';
import { ComponentProps } from '../../route_init';
import { GlobalStateContext } from '../../global_state_context';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { useTable } from '../../hooks/use_table';
import { ApmTemplate } from './apm_template';
// @ts-ignore
import { ApmServerInstances } from '../../../components/apm/instances';
import { SetupModeRenderer } from '../../setup_mode/setup_mode_renderer';
import { SetupModeContext } from '../../../components/setup_mode/setup_mode_context';
import { BreadcrumbContainer } from '../../hooks/use_breadcrumbs';

interface SetupModeProps {
setupMode: any;
flyoutComponent: any;
bottomBarComponent: any;
}

export const ApmInstancesPage: React.FC<ComponentProps> = ({ clusters }) => {
const globalState = useContext(GlobalStateContext);
const { services } = useKibana<{ data: any }>();
const { generate: generateBreadcrumbs } = useContext(BreadcrumbContainer.Context);
const { updateTotalItemCount, getPaginationTableProps } = useTable('apm.instances');
const clusterUuid = globalState.cluster_uuid;
const ccs = globalState.ccs;
const cluster = find(clusters, {
cluster_uuid: clusterUuid,
}) as any;
const [data, setData] = useState({} as any);

const title = i18n.translate('xpack.monitoring.apm.instances.routeTitle', {
defaultMessage: '{apm} - Instances',
values: {
apm: 'APM server',
},
});

const pageTitle = i18n.translate('xpack.monitoring.apm.instances.pageTitle', {
defaultMessage: 'APM server instances',
});

useEffect(() => {
if (cluster) {
generateBreadcrumbs(cluster.cluster_name, {
inApm: true,
});
}
}, [cluster, generateBreadcrumbs]);

const getPageData = useCallback(async () => {
const bounds = services.data?.query.timefilter.timefilter.getBounds();
const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm/instances`;
const response = await services.http?.fetch(url, {
method: 'POST',
body: JSON.stringify({
ccs,
timeRange: {
min: bounds.min.toISOString(),
max: bounds.max.toISOString(),
},
}),
});

setData(response);
updateTotalItemCount(response.stats.total);
}, [
ccs,
clusterUuid,
services.data?.query.timefilter.timefilter,
services.http,
updateTotalItemCount,
]);

const { pagination, sorting, onTableChange } = getPaginationTableProps();

return (
<ApmTemplate
title={title}
pageTitle={pageTitle}
getPageData={getPageData}
data-test-subj="apmInstancesPage"
>
<SetupModeRenderer
productName="apm"
render={({ setupMode, flyoutComponent, bottomBarComponent }: SetupModeProps) => (
<SetupModeContext.Provider value={{ setupModeSupported: true }}>
{flyoutComponent}
<ApmServerInstances
setupMode={setupMode}
apms={{
pagination,
sorting,
onTableChange,
data,
}}
/>
{bottomBarComponent}
</SetupModeContext.Provider>
)}
/>
</ApmTemplate>
);
};
Loading

0 comments on commit dbad35f

Please sign in to comment.