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 7e74961e57ea1..b072c22c09c19 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 @@ -79,6 +79,14 @@ export class InnerCustomPlot extends PureComponent { return i === _i ? !disabledValue : !!disabledValue; }); + if (typeof this.props.onToggleLegend === 'function') { + //Filters out disabled series + const availableSeries = this.props.series.filter( + (serie, index) => !nextSeriesEnabledState[index] + ); + this.props.onToggleLegend(availableSeries); + } + return { seriesEnabledState: nextSeriesEnabledState, }; @@ -235,6 +243,7 @@ InnerCustomPlot.propTypes = { }) ), noHits: PropTypes.bool, + onToggleLegend: PropTypes.func, }; InnerCustomPlot.defaultProps = { diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/TransactionLineChart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/TransactionLineChart/index.tsx index eaad883d2f9f6..3657a02b1589c 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/TransactionLineChart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/TransactionLineChart/index.tsx @@ -5,22 +5,13 @@ */ import React, { useCallback } from 'react'; -import { - Coordinate, - RectCoordinate, -} from '../../../../../../typings/timeseries'; +import { Coordinate, TimeSeries } from '../../../../../../typings/timeseries'; import { useChartsSync } from '../../../../../hooks/useChartsSync'; // @ts-ignore import CustomPlot from '../../CustomPlot'; interface Props { - series: Array<{ - color: string; - title: React.ReactNode; - titleShort?: React.ReactNode; - data: Array; - type: string; - }>; + series: TimeSeries[]; truncateLegends?: boolean; tickFormatY: (y: number) => React.ReactNode; formatTooltipValue: (c: Coordinate) => React.ReactNode; @@ -28,6 +19,7 @@ interface Props { height?: number; stacked?: boolean; onHover?: () => void; + onToggleLegend?: (visibleSeries: TimeSeries[]) => void; } function TransactionLineChart(props: Props) { @@ -40,6 +32,7 @@ function TransactionLineChart(props: Props) { truncateLegends, stacked = false, onHover, + onToggleLegend, } = props; const syncedChartsProps = useChartsSync(); @@ -66,6 +59,7 @@ function TransactionLineChart(props: Props) { height={height} truncateLegends={truncateLegends} {...(stacked ? { stackBy: 'y' } : {})} + 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 583a16281edc4..e55f86bd3abf3 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 @@ -29,7 +29,11 @@ import { Coordinate, TimeSeries } from '../../../../../typings/timeseries'; import { LicenseContext } from '../../../../context/LicenseContext'; import { IUrlParams } from '../../../../context/UrlParamsContext/types'; import { ITransactionChartData } from '../../../../selectors/chartSelectors'; -import { asDecimal, asDuration, tpmUnit } from '../../../../utils/formatters'; +import { + asDecimal, + getDurationFormatter, + tpmUnit, +} from '../../../../utils/formatters'; import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; import { MLJobLink } from '../../Links/MachineLearningLinks/MLJobLink'; import { BrowserLineChart } from './BrowserLineChart'; @@ -54,11 +58,6 @@ const ShiftedEuiText = styled(EuiText)` top: 5px; `; -const getResponseTimeTickFormatter = (t: number) => asDuration(t); - -const getResponseTimeTooltipFormatter = (p: Coordinate) => - isValidCoordinateValue(p.y) ? asDuration(p.y) : NOT_AVAILABLE_LABEL; - export function getMaxY(responseTimeSeries: TimeSeries[]) { const coordinates = flatten( responseTimeSeries.map((serie: TimeSeries) => serie.data as Coordinate[]) @@ -140,9 +139,28 @@ export function TransactionCharts({ ); } - const { responseTimeSeries, tpmSeries } = charts; const { transactionType } = urlParams; + const maxY = getMaxY(responseTimeSeries); + let formatter = getDurationFormatter(maxY); + + function onToggleLegend(visibleSeries: TimeSeries[]) { + if (!isEmpty(visibleSeries)) { + // recalculate the formatter based on the max Y from the visible series + const maxVisibleY = getMaxY(visibleSeries); + formatter = getDurationFormatter(maxVisibleY); + } + } + + function getResponseTimeTickFormatter(t: number) { + return formatter(t).formatted; + } + + function getResponseTimeTooltipFormatter(coordinate: Coordinate) { + return isValidCoordinateValue(coordinate.y) + ? formatter(coordinate.y).formatted + : NOT_AVAILABLE_LABEL; + } return ( <> @@ -166,6 +184,7 @@ export function TransactionCharts({ series={responseTimeSeries} tickFormatY={getResponseTimeTickFormatter} formatTooltipValue={getResponseTimeTooltipFormatter} + onToggleLegend={onToggleLegend} /> diff --git a/x-pack/plugins/apm/public/utils/formatters/__test__/duration.test.ts b/x-pack/plugins/apm/public/utils/formatters/__test__/duration.test.ts index c4d59beb4b7a2..ca8a4919dd216 100644 --- a/x-pack/plugins/apm/public/utils/formatters/__test__/duration.test.ts +++ b/x-pack/plugins/apm/public/utils/formatters/__test__/duration.test.ts @@ -20,9 +20,12 @@ describe('duration formatters', () => { '10,000 ms' ); expect(asDuration(toMicroseconds(20, 'seconds'))).toEqual('20 s'); - expect(asDuration(toMicroseconds(10, 'minutes'))).toEqual('10 min'); + expect(asDuration(toMicroseconds(10, 'minutes'))).toEqual('600 s'); + expect(asDuration(toMicroseconds(11, 'minutes'))).toEqual('11 min'); expect(asDuration(toMicroseconds(1, 'hours'))).toEqual('60 min'); - expect(asDuration(toMicroseconds(1.5, 'hours'))).toEqual('1.5 h'); + expect(asDuration(toMicroseconds(1.5, 'hours'))).toEqual('90 min'); + expect(asDuration(toMicroseconds(10, 'hours'))).toEqual('600 min'); + expect(asDuration(toMicroseconds(11, 'hours'))).toEqual('11 h'); }); it('falls back to default value', () => { diff --git a/x-pack/plugins/apm/public/utils/formatters/duration.ts b/x-pack/plugins/apm/public/utils/formatters/duration.ts index 64a9e3b952b98..8381b0afb5f07 100644 --- a/x-pack/plugins/apm/public/utils/formatters/duration.ts +++ b/x-pack/plugins/apm/public/utils/formatters/duration.ts @@ -127,10 +127,10 @@ export const toMicroseconds = (value: number, timeUnit: TimeUnit) => moment.duration(value, timeUnit).asMilliseconds() * 1000; function getDurationUnitKey(max: number): DurationTimeUnit { - if (max > toMicroseconds(1, 'hours')) { + if (max > toMicroseconds(10, 'hours')) { return 'hours'; } - if (max > toMicroseconds(1, 'minutes')) { + if (max > toMicroseconds(10, 'minutes')) { return 'minutes'; } if (max > toMicroseconds(10, 'seconds')) {