Skip to content
/ kibana Public
forked from elastic/kibana

Commit

Permalink
[APM] Fit service map to container (elastic#56336)
Browse files Browse the repository at this point in the history
* Set the height of the service map dynamically
* Move the loading overlay from the outside to the inside of the Cytoscape container
* Remove the EUI spacer from the Home and ServiceDetailTabs components and add it to the individual components that use them
smith committed Jan 31, 2020
1 parent 0e15c37 commit 73a6ce4
Showing 13 changed files with 227 additions and 169 deletions.
Original file line number Diff line number Diff line change
@@ -95,39 +95,42 @@ const ErrorGroupOverview: React.FC = () => {
}

return (
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localUIFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiFlexGroup>
<EuiFlexItem>
<EuiPanel>
<ErrorDistribution
distribution={errorDistributionData}
title={i18n.translate(
'xpack.apm.serviceDetails.metrics.errorOccurrencesChartTitle',
{
defaultMessage: 'Error occurrences'
}
)}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localUIFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiFlexGroup>
<EuiFlexItem>
<EuiPanel>
<ErrorDistribution
distribution={errorDistributionData}
title={i18n.translate(
'xpack.apm.serviceDetails.metrics.errorOccurrencesChartTitle',
{
defaultMessage: 'Error occurrences'
}
)}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer size="s" />

<EuiPanel>
<EuiTitle size="xs">
<h3>Errors</h3>
</EuiTitle>
<EuiSpacer size="s" />

<ErrorGroupList items={errorGroupListData} />
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<EuiPanel>
<EuiTitle size="xs">
<h3>Errors</h3>
</EuiTitle>
<EuiSpacer size="s" />

<ErrorGroupList items={errorGroupListData} />
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
};

20 changes: 9 additions & 11 deletions x-pack/legacy/plugins/apm/public/components/app/Home/index.tsx
Original file line number Diff line number Diff line change
@@ -5,27 +5,26 @@
*/

import {
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiTitle,
EuiButtonEmpty,
EuiTabs,
EuiSpacer
EuiTitle
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { $ElementType } from 'utility-types';
import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
import { ApmHeader } from '../../shared/ApmHeader';
import { SetupInstructionsLink } from '../../shared/Links/SetupInstructionsLink';
import { ServiceOverview } from '../ServiceOverview';
import { TraceOverview } from '../TraceOverview';
import { ServiceOverviewLink } from '../../shared/Links/apm/ServiceOverviewLink';
import { TraceOverviewLink } from '../../shared/Links/apm/TraceOverviewLink';
import { EuiTabLink } from '../../shared/EuiTabLink';
import { SettingsLink } from '../../shared/Links/apm/SettingsLink';
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
import { ServiceOverviewLink } from '../../shared/Links/apm/ServiceOverviewLink';
import { SettingsLink } from '../../shared/Links/apm/SettingsLink';
import { TraceOverviewLink } from '../../shared/Links/apm/TraceOverviewLink';
import { SetupInstructionsLink } from '../../shared/Links/SetupInstructionsLink';
import { ServiceMap } from '../ServiceMap';
import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
import { ServiceOverview } from '../ServiceOverview';
import { TraceOverview } from '../TraceOverview';

function getHomeTabs({
serviceMapEnabled = false
@@ -116,7 +115,6 @@ export function Home({ tab }: Props) {
</EuiTabLink>
))}
</EuiTabs>
<EuiSpacer />
{selectedTab.render()}
</div>
);
Original file line number Diff line number Diff line change
@@ -4,24 +4,24 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiTabs } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { EuiTabs, EuiSpacer } from '@elastic/eui';
import { ErrorGroupOverview } from '../ErrorGroupOverview';
import { TransactionOverview } from '../TransactionOverview';
import { ServiceMetrics } from '../ServiceMetrics';
import { isRumAgentName, isJavaAgentName } from '../../../../common/agent_name';
import { EuiTabLink } from '../../shared/EuiTabLink';
import { isJavaAgentName, isRumAgentName } from '../../../../common/agent_name';
import { useAgentName } from '../../../hooks/useAgentName';
import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';
import { EuiTabLink } from '../../shared/EuiTabLink';
import { ErrorOverviewLink } from '../../shared/Links/apm/ErrorOverviewLink';
import { MetricOverviewLink } from '../../shared/Links/apm/MetricOverviewLink';
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
import { ServiceNodeOverviewLink } from '../../shared/Links/apm/ServiceNodeOverviewLink';
import { ServiceNodeOverview } from '../ServiceNodeOverview';
import { useAgentName } from '../../../hooks/useAgentName';
import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';
import { ErrorGroupOverview } from '../ErrorGroupOverview';
import { ServiceMap } from '../ServiceMap';
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
import { ServiceMetrics } from '../ServiceMetrics';
import { ServiceNodeOverview } from '../ServiceNodeOverview';
import { TransactionOverview } from '../TransactionOverview';

interface Props {
tab: 'transactions' | 'errors' | 'metrics' | 'nodes' | 'service-map';
@@ -124,7 +124,6 @@ export function ServiceDetailTabs({ tab }: Props) {
</EuiTabLink>
))}
</EuiTabs>
<EuiSpacer />
{selectedTab ? selectedTab.render() : null}
</>
);
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ export const CytoscapeContext = createContext<cytoscape.Core | undefined>(
interface CytoscapeProps {
children?: ReactNode;
elements: cytoscape.ElementDefinition[];
height: number;
serviceName?: string;
style?: CSSProperties;
}
@@ -54,11 +55,16 @@ function useCytoscape(options: cytoscape.CytoscapeOptions) {
export function Cytoscape({
children,
elements,
height,
serviceName,
style
}: CytoscapeProps) {
const [ref, cy] = useCytoscape({ ...cytoscapeOptions, elements });

// Add the height to the div style. The height is a separate prop because it
// is required and can trigger rendering when changed.
const divStyle = { ...style, height };

// Trigger a custom "data" event when data changes
useEffect(() => {
if (cy) {
@@ -108,7 +114,7 @@ export function Cytoscape({

return (
<CytoscapeContext.Provider value={cy}>
<div ref={ref} style={style}>
<div ref={ref} style={divStyle}>
{children}
</div>
</CytoscapeContext.Provider>
Original file line number Diff line number Diff line change
@@ -31,16 +31,11 @@ const ProgressBarContainer = styled.div`
`;

interface Props {
children: React.ReactNode;
isLoading: boolean;
percentageLoaded: number;
}

export const LoadingOverlay = ({
children,
isLoading,
percentageLoaded
}: Props) => (
export const LoadingOverlay = ({ isLoading, percentageLoaded }: Props) => (
<Container>
{isLoading && (
<Overlay>
@@ -61,6 +56,5 @@ export const LoadingOverlay = ({
</EuiText>
</Overlay>
)}
{children}
</Container>
);
Original file line number Diff line number Diff line change
@@ -30,13 +30,13 @@ import { getCytoscapeElements } from './get_cytoscape_elements';
import { LoadingOverlay } from './LoadingOverlay';
import { PlatinumLicensePrompt } from './PlatinumLicensePrompt';
import { Popover } from './Popover';
import { useRefHeight } from './useRefHeight';

interface ServiceMapProps {
serviceName?: string;
}

const cytoscapeDivStyle = {
height: '85vh',
background: `linear-gradient(
90deg,
${theme.euiPageBackgroundColor}
@@ -52,7 +52,8 @@ linear-gradient(
center,
${theme.euiColorLightShade}`,
backgroundSize: `${theme.euiSizeL} ${theme.euiSizeL}`,
margin: `-${theme.gutterTypes.gutterLarge}`
margin: `-${theme.gutterTypes.gutterLarge}`,
marginTop: 0
};

const MAX_REQUESTS = 5;
@@ -198,17 +199,27 @@ export function ServiceMap({ serviceName }: ServiceMapProps) {
license?.isActive &&
(license?.type === 'platinum' || license?.type === 'trial');

const [wrapperRef, height] = useRefHeight();

return isValidPlatinumLicense ? (
<LoadingOverlay isLoading={isLoading} percentageLoaded={percentageLoaded}>
<div
style={{ height: height - parseInt(theme.gutterTypes.gutterLarge, 10) }}
ref={wrapperRef}
>
<Cytoscape
elements={renderedElements.current}
serviceName={serviceName}
height={height}
style={cytoscapeDivStyle}
>
<LoadingOverlay
isLoading={isLoading}
percentageLoaded={percentageLoaded}
/>
<Controls />
<Popover focusedServiceName={serviceName} />
</Cytoscape>
</LoadingOverlay>
</div>
) : (
<PlatinumLicensePrompt />
);
Original file line number Diff line number Diff line change
@@ -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 { MutableRefObject, useRef } from 'react';
import { useWindowSize } from 'react-use';

export function useRefHeight(): [
MutableRefObject<HTMLDivElement | null>,
number
] {
const ref = useRef<HTMLDivElement>(null);
const windowHeight = useWindowSize().height;
const topOffset = ref.current?.getBoundingClientRect()?.top ?? 0;

const height = ref.current ? windowHeight - topOffset : 0;

return [ref, height];
}
Original file line number Diff line number Diff line change
@@ -43,24 +43,27 @@ export function ServiceMetrics({ agentName }: ServiceMetricsProps) {
);

return (
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<ChartsSyncContextProvider>
<EuiFlexGrid columns={2} gutterSize="s">
{data.charts.map(chart => (
<EuiFlexItem key={chart.key}>
<EuiPanel>
<MetricsChart start={start} end={end} chart={chart} />
</EuiPanel>
</EuiFlexItem>
))}
</EuiFlexGrid>
<EuiSpacer size="xxl" />
</ChartsSyncContextProvider>
</EuiFlexItem>
</EuiFlexGroup>
<>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<ChartsSyncContextProvider>
<EuiFlexGrid columns={2} gutterSize="s">
{data.charts.map(chart => (
<EuiFlexItem key={chart.key}>
<EuiPanel>
<MetricsChart start={start} end={end} chart={chart} />
</EuiPanel>
</EuiFlexItem>
))}
</EuiFlexGrid>
<EuiSpacer size="xxl" />
</ChartsSyncContextProvider>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
}
Original file line number Diff line number Diff line change
@@ -4,7 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useMemo } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiToolTip } from '@elastic/eui';
import {
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiToolTip,
EuiSpacer
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import styled from 'styled-components';
import { UNIDENTIFIED_SERVICE_NODES_LABEL } from '../../../../common/i18n';
@@ -150,25 +156,31 @@ const ServiceNodeOverview = () => {
];

return (
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiPanel>
<ManagedTable
noItemsMessage={i18n.translate('xpack.apm.jvmsTable.noJvmsLabel', {
defaultMessage: 'No JVMs were found'
})}
items={items}
columns={columns}
initialPageSize={INITIAL_PAGE_SIZE}
initialSortField={INITIAL_SORT_FIELD}
initialSortDirection={INITIAL_SORT_DIRECTION}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiPanel>
<ManagedTable
noItemsMessage={i18n.translate(
'xpack.apm.jvmsTable.noJvmsLabel',
{
defaultMessage: 'No JVMs were found'
}
)}
items={items}
columns={columns}
initialPageSize={INITIAL_PAGE_SIZE}
initialSortField={INITIAL_SORT_FIELD}
initialSortDirection={INITIAL_SORT_DIRECTION}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
};

Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect, useMemo } from 'react';
@@ -94,23 +94,26 @@ export function ServiceOverview() {
);

return (
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiPanel>
<ServiceList
items={data.items}
noItemsMessage={
<NoServicesMessage
historicalDataFound={data.hasHistoricalData}
status={status}
/>
}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiPanel>
<ServiceList
items={data.items}
noItemsMessage={
<NoServicesMessage
historicalDataFound={data.hasHistoricalData}
status={status}
/>
}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
}
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import React, { useMemo } from 'react';
import { FETCH_STATUS, useFetcher } from '../../../hooks/useFetcher';
import { TraceList } from './TraceList';
@@ -47,15 +47,21 @@ export function TraceOverview() {
}, []);

return (
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localUIFiltersConfig} showCount={false} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiPanel>
<TraceList items={data} isLoading={status === FETCH_STATUS.LOADING} />
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localUIFiltersConfig} showCount={false} />
</EuiFlexItem>
<EuiFlexItem grow={7}>
<EuiPanel>
<TraceList
items={data}
isLoading={status === FETCH_STATUS.LOADING}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
}
Original file line number Diff line number Diff line change
@@ -119,41 +119,44 @@ export function TransactionOverview() {
}

return (
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig}>
<TransactionTypeFilter transactionTypes={serviceTransactionTypes} />
<EuiSpacer size="xl" />
<EuiHorizontalRule margin="none" />
</LocalUIFilters>
</EuiFlexItem>
<EuiFlexItem grow={7}>
<ChartsSyncContextProvider>
<TransactionBreakdown initialIsOpen={true} />
<>
<EuiSpacer />
<EuiFlexGroup>
<EuiFlexItem grow={1}>
<LocalUIFilters {...localFiltersConfig}>
<TransactionTypeFilter transactionTypes={serviceTransactionTypes} />
<EuiSpacer size="xl" />
<EuiHorizontalRule margin="none" />
</LocalUIFilters>
</EuiFlexItem>
<EuiFlexItem grow={7}>
<ChartsSyncContextProvider>
<TransactionBreakdown initialIsOpen={true} />

<EuiSpacer size="s" />

<TransactionCharts
hasMLJob={hasMLJob}
charts={transactionCharts}
location={location}
urlParams={urlParams}
/>
</ChartsSyncContextProvider>

<EuiSpacer size="s" />

<TransactionCharts
hasMLJob={hasMLJob}
charts={transactionCharts}
location={location}
urlParams={urlParams}
/>
</ChartsSyncContextProvider>

<EuiSpacer size="s" />

<EuiPanel>
<EuiTitle size="xs">
<h3>Transactions</h3>
</EuiTitle>
<EuiSpacer size="s" />
<TransactionList
isLoading={transactionListStatus === 'loading'}
items={transactionListData}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<EuiPanel>
<EuiTitle size="xs">
<h3>Transactions</h3>
</EuiTitle>
<EuiSpacer size="s" />
<TransactionList
isLoading={transactionListStatus === 'loading'}
items={transactionListData}
/>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</>
);
}
4 changes: 2 additions & 2 deletions x-pack/legacy/plugins/apm/public/new-platform/plugin.tsx
Original file line number Diff line number Diff line change
@@ -39,15 +39,15 @@ import { setReadonlyBadge } from './updateBadge';

export const REACT_APP_ROOT_ID = 'react-apm-root';

const MainContainer = styled.main`
const MainContainer = styled.div`
min-width: ${px(unit * 50)};
padding: ${px(units.plus)};
height: 100%;
`;

const App = () => {
return (
<MainContainer data-test-subj="apmMainContainer">
<MainContainer data-test-subj="apmMainContainer" role="main">
<UpdateBreadcrumbs routes={routes} />
<Route component={ScrollToTopOnPathChange} />
<Switch>

0 comments on commit 73a6ce4

Please sign in to comment.