diff --git a/x-pack/plugins/apm/public/utils/formatters/__test__/formatters.test.ts b/x-pack/plugins/apm/common/utils/formatters.test.ts
similarity index 96%
rename from x-pack/plugins/apm/public/utils/formatters/__test__/formatters.test.ts
rename to x-pack/plugins/apm/common/utils/formatters.test.ts
index 66101baf3a746..ce317c5a6a827 100644
--- a/x-pack/plugins/apm/public/utils/formatters/__test__/formatters.test.ts
+++ b/x-pack/plugins/apm/common/utils/formatters.test.ts
@@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { asPercent } from '../formatters';
+import { asPercent } from './formatters';
describe('formatters', () => {
describe('asPercent', () => {
diff --git a/x-pack/plugins/apm/common/utils/formatters.ts b/x-pack/plugins/apm/common/utils/formatters.ts
new file mode 100644
index 0000000000000..f7c609d949adf
--- /dev/null
+++ b/x-pack/plugins/apm/common/utils/formatters.ts
@@ -0,0 +1,28 @@
+/*
+ * 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 numeral from '@elastic/numeral';
+
+export function asPercent(
+ numerator: number,
+ denominator: number | undefined,
+ fallbackResult = ''
+) {
+ if (!denominator || isNaN(numerator)) {
+ return fallbackResult;
+ }
+
+ const decimal = numerator / denominator;
+
+ // 33.2 => 33%
+ // 3.32 => 3.3%
+ // 0 => 0%
+ if (Math.abs(decimal) >= 0.1 || decimal === 0) {
+ return numeral(decimal).format('0%');
+ }
+
+ return numeral(decimal).format('0.0%');
+}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx
index be52018735099..ba4451c37b304 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx
+++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx
@@ -8,8 +8,9 @@ import { i18n } from '@kbn/i18n';
import { isNumber } from 'lodash';
import React from 'react';
import styled from 'styled-components';
+import { asPercent } from '../../../../../common/utils/formatters';
import { ServiceNodeStats } from '../../../../../common/service_map';
-import { asDuration, asPercent, tpmUnit } from '../../../../utils/formatters';
+import { asDuration, tpmUnit } from '../../../../utils/formatters';
export const ItemRow = styled('tr')`
line-height: 2;
diff --git a/x-pack/plugins/apm/public/components/app/ServiceNodeOverview/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceNodeOverview/index.tsx
index 3cde48aa483cb..9940a7aabb219 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceNodeOverview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/ServiceNodeOverview/index.tsx
@@ -13,6 +13,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import styled from 'styled-components';
+import { asPercent } from '../../../../common/utils/formatters';
import { UNIDENTIFIED_SERVICE_NODES_LABEL } from '../../../../common/i18n';
import { SERVICE_NODE_NAME_MISSING } from '../../../../common/service_nodes';
import { Projection } from '../../../../common/projections';
@@ -20,11 +21,7 @@ import { LocalUIFilters } from '../../shared/LocalUIFilters';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { ManagedTable, ITableColumn } from '../../shared/ManagedTable';
import { useFetcher } from '../../../hooks/useFetcher';
-import {
- asDynamicBytes,
- asInteger,
- asPercent,
-} from '../../../utils/formatters';
+import { asDynamicBytes, asInteger } from '../../../utils/formatters';
import { ServiceNodeMetricOverviewLink } from '../../shared/Links/apm/ServiceNodeMetricOverviewLink';
import { truncate, px, unit } from '../../../style/variables';
diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/PercentOfParent.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/PercentOfParent.tsx
index 1725a13f4da66..41c958838803e 100644
--- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/PercentOfParent.tsx
+++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/PercentOfParent.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiToolTip } from '@elastic/eui';
-import { asPercent } from '../../../../utils/formatters';
+import { asPercent } from '../../../../../common/utils/formatters';
interface PercentOfParentProps {
duration: number;
diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx
index 0dc2f607b1ef2..515fcbc88c901 100644
--- a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx
@@ -5,32 +5,29 @@
*/
import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiHorizontalRule,
EuiPanel,
EuiSpacer,
EuiTitle,
- EuiHorizontalRule,
- EuiFlexGroup,
- EuiFlexItem,
} from '@elastic/eui';
import React, { useMemo } from 'react';
-import { EuiFlexGrid } from '@elastic/eui';
+import { useTrackPageview } from '../../../../../observability/public';
+import { Projection } from '../../../../common/projections';
+import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext';
+import { FETCH_STATUS } from '../../../hooks/useFetcher';
+import { useLocation } from '../../../hooks/useLocation';
import { useTransactionCharts } from '../../../hooks/useTransactionCharts';
import { useTransactionDistribution } from '../../../hooks/useTransactionDistribution';
+import { useUrlParams } from '../../../hooks/useUrlParams';
import { useWaterfall } from '../../../hooks/useWaterfall';
-import { TransactionCharts } from '../../shared/charts/TransactionCharts';
import { ApmHeader } from '../../shared/ApmHeader';
+import { TransactionCharts } from '../../shared/charts/TransactionCharts';
+import { HeightRetainer } from '../../shared/HeightRetainer';
+import { LocalUIFilters } from '../../shared/LocalUIFilters';
import { TransactionDistribution } from './Distribution';
import { WaterfallWithSummmary } from './WaterfallWithSummmary';
-import { useLocation } from '../../../hooks/useLocation';
-import { useUrlParams } from '../../../hooks/useUrlParams';
-import { FETCH_STATUS } from '../../../hooks/useFetcher';
-import { TransactionBreakdown } from '../../shared/TransactionBreakdown';
-import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext';
-import { useTrackPageview } from '../../../../../observability/public';
-import { Projection } from '../../../../common/projections';
-import { LocalUIFilters } from '../../shared/LocalUIFilters';
-import { HeightRetainer } from '../../shared/HeightRetainer';
-import { ErroneousTransactionsRateChart } from '../../shared/charts/ErroneousTransactionsRateChart';
export function TransactionDetails() {
const location = useLocation();
@@ -86,21 +83,9 @@ export function TransactionDetails() {
-
-
-
-
-
-
-
-
-
-
-
diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx
index 0757ae572152c..81d8a6f807375 100644
--- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx
@@ -7,7 +7,6 @@
import {
EuiCallOut,
EuiCode,
- EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
@@ -29,13 +28,11 @@ import { useServiceTransactionTypes } from '../../../hooks/useServiceTransaction
import { useTransactionCharts } from '../../../hooks/useTransactionCharts';
import { useTransactionList } from '../../../hooks/useTransactionList';
import { useUrlParams } from '../../../hooks/useUrlParams';
-import { ErroneousTransactionsRateChart } from '../../shared/charts/ErroneousTransactionsRateChart';
import { TransactionCharts } from '../../shared/charts/TransactionCharts';
import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
import { fromQuery, toQuery } from '../../shared/Links/url_helpers';
import { LocalUIFilters } from '../../shared/LocalUIFilters';
import { TransactionTypeFilter } from '../../shared/LocalUIFilters/TransactionTypeFilter';
-import { TransactionBreakdown } from '../../shared/TransactionBreakdown';
import { TransactionList } from './List';
import { useRedirect } from './useRedirect';
@@ -125,20 +122,8 @@ export function TransactionOverview() {
-
-
-
-
-
-
-
-
-
-
-
diff --git a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx
index 209657971620b..b908eb8da4d03 100644
--- a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx
@@ -4,19 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useMemo } from 'react';
import { throttle } from 'lodash';
+import React, { useMemo } from 'react';
+import { asPercent } from '../../../../../common/utils/formatters';
+import { useUiTracker } from '../../../../../../observability/public';
import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n';
-import { Coordinate, TimeSeries } from '../../../../../typings/timeseries';
import { Maybe } from '../../../../../typings/common';
-import { TransactionLineChart } from '../../charts/TransactionCharts/TransactionLineChart';
-import { asPercent } from '../../../../utils/formatters';
-import { unit } from '../../../../style/variables';
+import { Coordinate, TimeSeries } from '../../../../../typings/timeseries';
+import { useUrlParams } from '../../../../hooks/useUrlParams';
import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue';
-import { useUiTracker } from '../../../../../../observability/public';
+import { getEmptySeries } from '../../charts/CustomPlot/getEmptySeries';
+import { TransactionLineChart } from '../../charts/TransactionCharts/TransactionLineChart';
interface Props {
timeseries: TimeSeries[];
+ noHits: boolean;
}
const tickFormatY = (y: Maybe) => {
@@ -29,8 +31,9 @@ const formatTooltipValue = (coordinate: Coordinate) => {
: NOT_AVAILABLE_LABEL;
};
-function TransactionBreakdownGraph(props: Props) {
- const { timeseries } = props;
+function TransactionBreakdownGraph({ timeseries, noHits }: Props) {
+ const { urlParams } = useUrlParams();
+ const { rangeFrom, rangeTo } = urlParams;
const trackApmEvent = useUiTracker({ app: 'apm' });
const handleHover = useMemo(
() =>
@@ -38,15 +41,23 @@ function TransactionBreakdownGraph(props: Props) {
[trackApmEvent]
);
+ const emptySeries =
+ rangeFrom && rangeTo
+ ? getEmptySeries(
+ new Date(rangeFrom).getTime(),
+ new Date(rangeTo).getTime()
+ )
+ : [];
+
return (
);
}
diff --git a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownKpiList.tsx b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownKpiList.tsx
deleted file mode 100644
index d3761cf0fe38e..0000000000000
--- a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownKpiList.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 React from 'react';
-import {
- EuiFlexGrid,
- EuiFlexItem,
- EuiFlexGroup,
- EuiText,
- EuiTitle,
- EuiIcon,
-} from '@elastic/eui';
-import styled from 'styled-components';
-import { asPercent } from '../../../utils/formatters';
-
-interface TransactionBreakdownKpi {
- name: string;
- percentage: number;
- color: string;
-}
-
-interface Props {
- kpis: TransactionBreakdownKpi[];
-}
-
-const Description = styled.span`
- {
- white-space: nowrap;
- }
-`;
-
-function KpiDescription({ name, color }: { name: string; color: string }) {
- return (
-
-
-
-
-
-
- {name}
-
-
-
- );
-}
-
-function TransactionBreakdownKpiList({ kpis }: Props) {
- return (
-
- {kpis.map((kpi) => (
-
-
-
-
-
-
-
- {asPercent(kpi.percentage, 1)}
-
-
-
-
- ))}
-
- );
-}
-
-export { TransactionBreakdownKpiList };
diff --git a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx
index 80ed9163ec08d..55826497ca385 100644
--- a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx
@@ -3,28 +3,18 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiPanel,
- EuiText,
- EuiTitle,
-} from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
+import { isEmpty } from 'lodash';
import React from 'react';
import { FETCH_STATUS } from '../../../hooks/useFetcher';
import { useTransactionBreakdown } from '../../../hooks/useTransactionBreakdown';
import { TransactionBreakdownGraph } from './TransactionBreakdownGraph';
-import { TransactionBreakdownKpiList } from './TransactionBreakdownKpiList';
-
-const emptyMessage = i18n.translate('xpack.apm.transactionBreakdown.noData', {
- defaultMessage: 'No data within this time range.',
-});
function TransactionBreakdown() {
const { data, status } = useTransactionBreakdown();
- const { kpis, timeseries } = data;
- const noHits = data.kpis.length === 0 && status === FETCH_STATUS.SUCCESS;
+ const { timeseries } = data;
+ const noHits = isEmpty(timeseries) && status === FETCH_STATUS.SUCCESS;
return (
@@ -39,14 +29,7 @@ function TransactionBreakdown() {
- {noHits ? (
- {emptyMessage}
- ) : (
-
- )}
-
-
-
+
diff --git a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/index.js b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/index.js
index 41925d651e361..501d30b5e2ba1 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/index.js
+++ b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/index.js
@@ -67,7 +67,7 @@ export class InnerCustomPlot extends PureComponent {
(series) => {
return series.slice(
0,
- VISIBLE_LEGEND_COUNT + getHiddenLegendCount(series)
+ this.props.visibleLegendCount + getHiddenLegendCount(series)
);
}
);
@@ -128,14 +128,20 @@ export class InnerCustomPlot extends PureComponent {
}
render() {
- const { series, truncateLegends, width, annotations } = this.props;
+ const {
+ series,
+ truncateLegends,
+ width,
+ annotations,
+ visibleLegendCount,
+ } = this.props;
if (!width) {
return null;
}
const hiddenSeriesCount = Math.max(
- series.length - VISIBLE_LEGEND_COUNT - getHiddenLegendCount(series),
+ series.length - visibleLegendCount - getHiddenLegendCount(series),
0
);
const visibleSeries = this.getVisibleSeries({ series });
@@ -239,6 +245,7 @@ InnerCustomPlot.propTypes = {
})
),
noHits: PropTypes.bool,
+ visibleLegendCount: PropTypes.number,
onToggleLegend: PropTypes.func,
};
@@ -249,6 +256,7 @@ InnerCustomPlot.defaultProps = {
truncateLegends: false,
xAxisTickSizeOuter: 0,
noHits: false,
+ visibleLegendCount: VISIBLE_LEGEND_COUNT,
};
export default makeWidthFlexible(InnerCustomPlot);
diff --git a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/plotUtils.tsx b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/plotUtils.tsx
index 7721375a404c4..67b7fd31b05bc 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/plotUtils.tsx
+++ b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/plotUtils.tsx
@@ -19,7 +19,7 @@ const XY_HEIGHT = unit * 16;
const XY_MARGIN = {
top: unit,
left: unit * 5,
- right: 0,
+ right: unit,
bottom: unit * 2,
};
diff --git a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap
index f413610ebd984..20636fa144479 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap
+++ b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap
@@ -82,7 +82,7 @@ Array [
className="rv-xy-plot__axis__line"
style={Object {}}
x1={0}
- x2={720}
+ x2={704}
y1={0}
y2={0}
/>
@@ -93,7 +93,7 @@ Array [
@@ -434,7 +434,7 @@ Array [
>
`;
@@ -3018,7 +3018,7 @@ Array [
className="rv-xy-plot__axis__line"
style={Object {}}
x1={0}
- x2={720}
+ x2={704}
y1={0}
y2={0}
/>
@@ -3029,7 +3029,7 @@ Array [
@@ -3370,7 +3370,7 @@ Array [
>
@@ -5132,7 +5132,7 @@ Array [
rv-hint--verticalAlign-bottom"
style={
Object {
- "left": 440,
+ "left": 432,
"position": "absolute",
"top": 120,
}
@@ -5339,7 +5339,7 @@ Array [
>
@@ -6097,7 +6097,7 @@ Array [
diff --git a/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx
index 3b6d1684e08e1..1676d3f68b57c 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx
@@ -8,11 +8,12 @@ import theme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import React, { useCallback } from 'react';
import { EuiPanel } from '@elastic/eui';
+import { EuiSpacer } from '@elastic/eui';
+import { asPercent } from '../../../../../common/utils/formatters';
import { useChartsSync } from '../../../../hooks/useChartsSync';
import { useFetcher } from '../../../../hooks/useFetcher';
import { useUrlParams } from '../../../../hooks/useUrlParams';
import { callApmApi } from '../../../../services/rest/createCallApmApi';
-import { asPercent } from '../../../../utils/formatters';
// @ts-ignore
import CustomPlot from '../CustomPlot';
@@ -71,6 +72,7 @@ export function ErroneousTransactionsRateChart() {
})}
+
void;
+ visibleLegendCount?: number;
onToggleLegend?: (disabledSeriesState: boolean[]) => void;
}
@@ -32,6 +33,7 @@ function TransactionLineChart(props: Props) {
truncateLegends,
stacked = false,
onHover,
+ visibleLegendCount,
onToggleLegend,
} = props;
@@ -59,6 +61,7 @@ function TransactionLineChart(props: Props) {
height={height}
truncateLegends={truncateLegends}
{...(stacked ? { stackBy: 'y' } : {})}
+ visibleLegendCount={visibleLegendCount}
onToggleLegend={onToggleLegend}
/>
);
diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx
index d11925dc0303d..6ba080a07b9d3 100644
--- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx
@@ -13,7 +13,6 @@ import {
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { Location } from 'history';
import React from 'react';
import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n';
import {
@@ -29,6 +28,8 @@ import { asDecimal, tpmUnit } from '../../../../utils/formatters';
import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue';
import { BrowserLineChart } from './BrowserLineChart';
import { DurationByCountryMap } from './DurationByCountryMap';
+import { ErroneousTransactionsRateChart } from '../ErroneousTransactionsRateChart';
+import { TransactionBreakdown } from '../../TransactionBreakdown';
import {
getResponseTimeTickFormatter,
getResponseTimeTooltipFormatter,
@@ -39,13 +40,11 @@ import { useFormatter } from './use_formatter';
interface TransactionChartProps {
charts: ITransactionChartData;
- location: Location;
urlParams: IUrlParams;
}
export function TransactionCharts({
charts,
- location,
urlParams,
}: TransactionChartProps) {
const getTPMFormatter = (t: number) => {
@@ -72,48 +71,56 @@ export function TransactionCharts({
-
-
-
-
- {responseTimeLabel(transactionType)}
-
-
-
- {(license) => (
-
- )}
-
-
-
-
+
+
+
+ {responseTimeLabel(transactionType)}
+
+
+
+ {(license) => (
+
+ )}
+
+
+
-
-
- {tpmLabel(transactionType)}
-
-
-
+
+ {tpmLabel(transactionType)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{transactionType === TRANSACTION_PAGE_LOAD && (
<>
diff --git a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts
index 2449c13f29435..9db78fde2d8c8 100644
--- a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts
+++ b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts
@@ -13,7 +13,7 @@ export function useTransactionBreakdown() {
uiFilters,
} = useUrlParams();
- const { data = { kpis: [], timeseries: [] }, error, status } = useFetcher(
+ const { data = { timeseries: [] }, error, status } = useFetcher(
(callApmApi) => {
if (serviceName && start && end && transactionType) {
return callApmApi({
diff --git a/x-pack/plugins/apm/public/utils/formatters/formatters.ts b/x-pack/plugins/apm/public/utils/formatters/formatters.ts
index 649f11063b149..6249ce53b6779 100644
--- a/x-pack/plugins/apm/public/utils/formatters/formatters.ts
+++ b/x-pack/plugins/apm/public/utils/formatters/formatters.ts
@@ -23,24 +23,3 @@ export function tpmUnit(type?: string) {
defaultMessage: 'tpm',
});
}
-
-export function asPercent(
- numerator: number,
- denominator: number | undefined,
- fallbackResult = ''
-) {
- if (!denominator || isNaN(numerator)) {
- return fallbackResult;
- }
-
- const decimal = numerator / denominator;
-
- // 33.2 => 33%
- // 3.32 => 3.3%
- // 0 => 0%
- if (Math.abs(decimal) >= 0.1 || decimal === 0) {
- return numeral(decimal).format('0%');
- }
-
- return numeral(decimal).format('0.0%');
-}
diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts
index 731f75226cbe4..e943214b0b517 100644
--- a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts
+++ b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts
@@ -50,40 +50,9 @@ describe('getTransactionBreakdown', () => {
setup: getMockSetup(noDataResponse),
});
- expect(response.kpis.length).toBe(0);
-
expect(Object.keys(response.timeseries).length).toBe(0);
});
- it('returns transaction breakdowns grouped by type and subtype', async () => {
- const response = await getTransactionBreakdown({
- serviceName: 'myServiceName',
- transactionType: 'request',
- setup: getMockSetup(dataResponse),
- });
-
- expect(response.kpis.length).toBe(4);
-
- expect(response.kpis.map((kpi) => kpi.name)).toEqual([
- 'app',
- 'dispatcher-servlet',
- 'http',
- 'postgresql',
- ]);
-
- expect(response.kpis[0]).toEqual({
- name: 'app',
- color: '#54b399',
- percentage: 0.5408550899466306,
- });
-
- expect(response.kpis[3]).toEqual({
- name: 'postgresql',
- color: '#9170b8',
- percentage: 0.047366859295002,
- });
- });
-
it('returns a timeseries grouped by type and subtype', async () => {
const response = await getTransactionBreakdown({
serviceName: 'myServiceName',
@@ -98,7 +67,7 @@ describe('getTransactionBreakdown', () => {
const appTimeseries = timeseries[0];
expect(appTimeseries.title).toBe('app');
expect(appTimeseries.type).toBe('areaStacked');
- expect(appTimeseries.hideLegend).toBe(true);
+ expect(appTimeseries.hideLegend).toBe(false);
// empty buckets should result in null values for visible types
expect(appTimeseries.data.length).toBe(276);
diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts
index fbdddea32deb4..9730ddbbf38d7 100644
--- a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts
+++ b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts
@@ -5,6 +5,7 @@
*/
import { flatten, orderBy, last } from 'lodash';
+import { asPercent } from '../../../../common/utils/formatters';
import { ProcessorEvent } from '../../../../common/processor_event';
import {
SERVICE_NAME,
@@ -149,9 +150,16 @@ export async function getTransactionBreakdown({
)
: [];
- const kpis = orderBy(visibleKpis, 'name').map((kpi, index) => {
- return {
+ const kpis = orderBy(
+ visibleKpis.map((kpi) => ({
...kpi,
+ lowerCaseName: kpi.name.toLowerCase(),
+ })),
+ 'lowerCaseName'
+ ).map((kpi, index) => {
+ const { lowerCaseName, ...rest } = kpi;
+ return {
+ ...rest,
color: getVizColorForIndex(index),
};
});
@@ -213,11 +221,9 @@ export async function getTransactionBreakdown({
color: kpi.color,
type: 'areaStacked',
data: timeseriesPerSubtype[kpi.name],
- hideLegend: true,
+ hideLegend: false,
+ legendValue: asPercent(kpi.percentage, 1),
}));
- return {
- kpis,
- timeseries,
- };
+ return { timeseries };
}
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 83dac4912d4ac..911fb147511ab 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -5067,7 +5067,6 @@
"xpack.apm.transactionActionMenu.viewInUptime": "ステータス",
"xpack.apm.transactionActionMenu.viewSampleDocumentLinkLabel": "サンプルドキュメントを表示",
"xpack.apm.transactionBreakdown.chartTitle": "スパンタイプ別時間",
- "xpack.apm.transactionBreakdown.noData": "この時間範囲のデータがありません。",
"xpack.apm.transactionCardinalityWarning.body": "一意のトランザクション名の数が構成された値{bucketSize}を超えています。エージェントを再構成し、類似したトランザクションをグループ化するか、{codeBlock}の値を増やしてください。",
"xpack.apm.transactionCardinalityWarning.docsLink": "詳細はドキュメントをご覧ください",
"xpack.apm.transactionCardinalityWarning.title": "このビューには、報告されたトランザクションのサブセットが表示されます。",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 8b3a1941f450a..6495341539343 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -5069,7 +5069,6 @@
"xpack.apm.transactionActionMenu.viewInUptime": "状态",
"xpack.apm.transactionActionMenu.viewSampleDocumentLinkLabel": "查看样例文档",
"xpack.apm.transactionBreakdown.chartTitle": "跨度类型花费的时间",
- "xpack.apm.transactionBreakdown.noData": "此时间范围内没有数据。",
"xpack.apm.transactionCardinalityWarning.body": "唯一事务名称的数目超过 {bucketSize} 的已配置值。尝试重新配置您的代理以对类似的事务分组或增大 {codeBlock} 的值",
"xpack.apm.transactionCardinalityWarning.docsLink": "在文档中了解详情",
"xpack.apm.transactionCardinalityWarning.title": "此视图显示已报告事务的子集。",
diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts
index 5b61112a374c1..0b94abaa15890 100644
--- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts
+++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts
@@ -6,7 +6,6 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import expectedBreakdown from './expectation/breakdown.json';
-import expectedBreakdownWithTransactionName from './expectation/breakdown_transaction_name.json';
export default function ApiTest({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@@ -25,7 +24,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
`/api/apm/services/opbeans-node/transaction_groups/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}`
);
expect(response.status).to.be(200);
- expect(response.body).to.eql({ kpis: [], timeseries: [] });
+ expect(response.body).to.eql({ timeseries: [] });
});
});
@@ -47,15 +46,32 @@ export default function ApiTest({ getService }: FtrProviderContext) {
);
expect(response.status).to.be(200);
- expect(response.body).to.eql(expectedBreakdownWithTransactionName);
+ const { timeseries } = response.body;
+ const { title, color, type, data, hideLegend, legendValue } = timeseries[0];
+ expect(data).to.eql([
+ { x: 1593413100000, y: null },
+ { x: 1593413130000, y: null },
+ { x: 1593413160000, y: null },
+ { x: 1593413190000, y: null },
+ { x: 1593413220000, y: null },
+ { x: 1593413250000, y: null },
+ { x: 1593413280000, y: null },
+ { x: 1593413310000, y: 1 },
+ { x: 1593413340000, y: null },
+ ]);
+ expect(title).to.be('app');
+ expect(color).to.be('#54b399');
+ expect(type).to.be('areaStacked');
+ expect(hideLegend).to.be(false);
+ expect(legendValue).to.be('100%');
});
- it('returns the top 4 by percentage and sorts them by name', async () => {
+ it('returns the transaction breakdown sorted by name', async () => {
const response = await supertest.get(
`/api/apm/services/opbeans-node/transaction_groups/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}`
);
expect(response.status).to.be(200);
- expect(response.body.kpis.map((kpi: { name: string }) => kpi.name)).to.eql([
+ expect(response.body.timeseries.map((serie: { title: string }) => serie.title)).to.eql([
'app',
'http',
'postgresql',
diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/expectation/breakdown.json b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/expectation/breakdown.json
index 3b884a9eb7907..8ffbba64ec7ab 100644
--- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/expectation/breakdown.json
+++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/expectation/breakdown.json
@@ -1,26 +1,4 @@
{
- "kpis":[
- {
- "name":"app",
- "percentage":0.16700861715223636,
- "color":"#54b399"
- },
- {
- "name":"http",
- "percentage":0.7702092736971686,
- "color":"#6092c0"
- },
- {
- "name":"postgresql",
- "percentage":0.0508822322527698,
- "color":"#d36086"
- },
- {
- "name":"redis",
- "percentage":0.011899876897825195,
- "color":"#9170b8"
- }
- ],
"timeseries":[
{
"title":"app",
@@ -64,7 +42,8 @@
"y":null
}
],
- "hideLegend":true
+ "hideLegend":false,
+ "legendValue": "17%"
},
{
"title":"http",
@@ -108,7 +87,8 @@
"y":null
}
],
- "hideLegend":true
+ "hideLegend":false,
+ "legendValue": "77%"
},
{
"title":"postgresql",
@@ -152,7 +132,8 @@
"y":null
}
],
- "hideLegend":true
+ "hideLegend":false,
+ "legendValue": "5.1%"
},
{
"title":"redis",
@@ -196,7 +177,8 @@
"y":null
}
],
- "hideLegend":true
+ "hideLegend":false,
+ "legendValue": "1.2%"
}
]
}
\ No newline at end of file
diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/expectation/breakdown_transaction_name.json b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/expectation/breakdown_transaction_name.json
deleted file mode 100644
index b4f8e376d3609..0000000000000
--- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/expectation/breakdown_transaction_name.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "kpis":[
- {
- "name":"app",
- "percentage":1,
- "color":"#54b399"
- }
- ],
- "timeseries":[
- {
- "title":"app",
- "color":"#54b399",
- "type":"areaStacked",
- "data":[
- {
- "x":1593413100000,
- "y":null
- },
- {
- "x":1593413130000,
- "y":null
- },
- {
- "x":1593413160000,
- "y":null
- },
- {
- "x":1593413190000,
- "y":null
- },
- {
- "x":1593413220000,
- "y":null
- },
- {
- "x":1593413250000,
- "y":null
- },
- {
- "x":1593413280000,
- "y":null
- },
- {
- "x":1593413310000,
- "y":1
- },
- {
- "x":1593413340000,
- "y":null
- }
- ],
- "hideLegend":true
- }
- ]
-}
\ No newline at end of file