Skip to content

Commit

Permalink
[APM] Adding comparison latency chart (#91339)
Browse files Browse the repository at this point in the history
* adding time comparison to latency chart

* adding time comparison to latency chart

* fixing TS

* fixing api test

* addressing PR comments

* adding api test

* addressing PR comments

* fixing api test

* rounding date diff

* addressing PR comments

* fixing api test

* refactoring

* fixing ts issue

* fixing offset function

* fixing offset function

* addressing PR comments

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
cauemarcondes and kibanamachine authored Mar 10, 2021
1 parent 2bb2329 commit f428b10
Show file tree
Hide file tree
Showing 14 changed files with 690 additions and 287 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { LatencyAggregationType } from '../../../../../common/latency_aggregatio
import { getDurationFormatter } from '../../../../../common/utils/formatters';
import { useLicenseContext } from '../../../../context/license/use_license_context';
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
import { useTheme } from '../../../../hooks/use_theme';
import { useTransactionLatencyChartsFetcher } from '../../../../hooks/use_transaction_latency_chart_fetcher';
import { TimeseriesChart } from '../../../shared/charts/timeseries_chart';
import {
Expand All @@ -21,6 +22,7 @@ import {
} from '../../../shared/charts/transaction_charts/helper';
import { MLHeader } from '../../../shared/charts/transaction_charts/ml_header';
import * as urlHelpers from '../../../shared/Links/url_helpers';
import { getComparisonChartTheme } from '../../time_comparison/get_time_range_comparison';

interface Props {
height?: number;
Expand All @@ -32,20 +34,36 @@ const options: Array<{ value: LatencyAggregationType; text: string }> = [
{ value: LatencyAggregationType.p99, text: '99th percentile' },
];

function filterNil<T>(value: T | null | undefined): value is T {
return value != null;
}

export function LatencyChart({ height }: Props) {
const history = useHistory();
const theme = useTheme();
const comparisonChartTheme = getComparisonChartTheme(theme);
const { urlParams } = useUrlParams();
const { latencyAggregationType } = urlParams;
const { latencyAggregationType, comparisonEnabled } = urlParams;
const license = useLicenseContext();

const {
latencyChartsData,
latencyChartsStatus,
} = useTransactionLatencyChartsFetcher();

const { latencyTimeseries, anomalyTimeseries, mlJobId } = latencyChartsData;
const {
currentPeriod,
previousPeriod,
anomalyTimeseries,
mlJobId,
} = latencyChartsData;

const timeseries = [
currentPeriod,
comparisonEnabled ? previousPeriod : undefined,
].filter(filterNil);

const latencyMaxY = getMaxY(latencyTimeseries);
const latencyMaxY = getMaxY(timeseries);
const latencyFormatter = getDurationFormatter(latencyMaxY);

return (
Expand Down Expand Up @@ -99,7 +117,8 @@ export function LatencyChart({ height }: Props) {
height={height}
fetchStatus={latencyChartsStatus}
id="latencyChart"
timeseries={latencyTimeseries}
customTheme={comparisonChartTheme}
timeseries={timeseries}
yLabelFormat={getResponseTimeTickFormatter(latencyFormatter)}
anomalyTimeseries={anomalyTimeseries}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ function getSelectOptions({
}),
};

const dateDiff = getDateDifference({
start: momentStart,
end: momentEnd,
unitOfTime: 'days',
precise: true,
});
const dateDiff = Number(
getDateDifference({
start: momentStart,
end: momentEnd,
unitOfTime: 'days',
precise: true,
}).toFixed(2)
);

const isRangeToNow = rangeTo === 'now';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useUrlParams } from '../context/url_params_context/use_url_params';
import { useApmServiceContext } from '../context/apm_service/use_apm_service_context';
import { getLatencyChartSelector } from '../selectors/latency_chart_selectors';
import { useTheme } from './use_theme';
import { getTimeRangeComparison } from '../components/shared/time_comparison/get_time_range_comparison';

export function useTransactionLatencyChartsFetcher() {
const { serviceName } = useParams<{ serviceName?: string }>();
Expand All @@ -25,9 +26,16 @@ export function useTransactionLatencyChartsFetcher() {
end,
transactionName,
latencyAggregationType,
comparisonType,
},
} = useUrlParams();

const { comparisonStart, comparisonEnd } = getTimeRangeComparison({
start,
end,
comparisonType,
});

const { data, error, status } = useFetcher(
(callApmApi) => {
if (
Expand All @@ -50,6 +58,8 @@ export function useTransactionLatencyChartsFetcher() {
transactionType,
transactionName,
latencyAggregationType,
comparisonStart,
comparisonEnd,
},
},
});
Expand All @@ -64,6 +74,8 @@ export function useTransactionLatencyChartsFetcher() {
transactionName,
transactionType,
latencyAggregationType,
comparisonStart,
comparisonEnd,
]
);

Expand Down
166 changes: 82 additions & 84 deletions x-pack/plugins/apm/public/selectors/latency_chart_selector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@ const theme = {
euiColorVis5: 'red',
euiColorVis7: 'black',
euiColorVis9: 'yellow',
euiColorLightestShade: 'green',
},
} as EuiTheme;

const latencyChartData = {
overallAvgDuration: 1,
latencyTimeseries: [{ x: 1, y: 10 }],
currentPeriod: {
overallAvgDuration: 1,
latencyTimeseries: [{ x: 1, y: 10 }],
},
previousPeriod: {
overallAvgDuration: 1,
latencyTimeseries: [{ x: 1, y: 10 }],
},
anomalyTimeseries: {
jobId: '1',
anomalyBoundaries: [{ x: 1, y: 2, y0: 1 }],
Expand All @@ -36,69 +43,84 @@ describe('getLatencyChartSelector', () => {
it('returns default values when data is undefined', () => {
const latencyChart = getLatencyChartSelector({ theme });
expect(latencyChart).toEqual({
latencyTimeseries: [],
currentPeriod: undefined,
previousPeriod: undefined,
mlJobId: undefined,
anomalyTimeseries: undefined,
});
});

it('returns average timeseries', () => {
const { anomalyTimeseries, ...latencyWithouAnomaly } = latencyChartData;
const { anomalyTimeseries, ...latencyWithoutAnomaly } = latencyChartData;
const latencyTimeseries = getLatencyChartSelector({
latencyChart: latencyWithouAnomaly as LatencyChartsResponse,
latencyChart: latencyWithoutAnomaly as LatencyChartsResponse,
theme,
latencyAggregationType: LatencyAggregationType.avg,
});
expect(latencyTimeseries).toEqual({
latencyTimeseries: [
{
title: 'Average',
data: [{ x: 1, y: 10 }],
legendValue: '1 μs',
type: 'linemark',
color: 'blue',
},
],
currentPeriod: {
title: 'Average',
data: [{ x: 1, y: 10 }],
legendValue: '1 μs',
type: 'linemark',
color: 'blue',
},

previousPeriod: {
color: 'green',
data: [{ x: 1, y: 10 }],
type: 'area',
title: 'Previous period',
},
});
});

it('returns 95th percentile timeseries', () => {
const { anomalyTimeseries, ...latencyWithouAnomaly } = latencyChartData;
const { anomalyTimeseries, ...latencyWithoutAnomaly } = latencyChartData;
const latencyTimeseries = getLatencyChartSelector({
latencyChart: latencyWithouAnomaly as LatencyChartsResponse,
latencyChart: latencyWithoutAnomaly as LatencyChartsResponse,
theme,
latencyAggregationType: LatencyAggregationType.p95,
});
expect(latencyTimeseries).toEqual({
latencyTimeseries: [
{
title: '95th percentile',
data: [{ x: 1, y: 10 }],
titleShort: '95th',
type: 'linemark',
color: 'red',
},
],
currentPeriod: {
title: '95th percentile',
titleShort: '95th',
data: [{ x: 1, y: 10 }],
type: 'linemark',
color: 'red',
},
previousPeriod: {
data: [{ x: 1, y: 10 }],
type: 'area',
color: 'green',
title: 'Previous period',
},
});
});

it('returns 99th percentile timeseries', () => {
const { anomalyTimeseries, ...latencyWithouAnomaly } = latencyChartData;
const { anomalyTimeseries, ...latencyWithoutAnomaly } = latencyChartData;
const latencyTimeseries = getLatencyChartSelector({
latencyChart: latencyWithouAnomaly as LatencyChartsResponse,
latencyChart: latencyWithoutAnomaly as LatencyChartsResponse,
theme,
latencyAggregationType: LatencyAggregationType.p99,
});

expect(latencyTimeseries).toEqual({
latencyTimeseries: [
{
title: '99th percentile',
data: [{ x: 1, y: 10 }],
titleShort: '99th',
type: 'linemark',
color: 'black',
},
],
currentPeriod: {
title: '99th percentile',
titleShort: '99th',
data: [{ x: 1, y: 10 }],
type: 'linemark',
color: 'black',
},
previousPeriod: {
data: [{ x: 1, y: 10 }],
type: 'area',
color: 'green',
title: 'Previous period',
},
});
});
});
Expand All @@ -111,76 +133,52 @@ describe('getLatencyChartSelector', () => {
latencyAggregationType: LatencyAggregationType.p99,
});
expect(latencyTimeseries).toEqual({
currentPeriod: {
title: '99th percentile',
titleShort: '99th',
data: [{ x: 1, y: 10 }],
type: 'linemark',
color: 'black',
},
previousPeriod: {
data: [{ x: 1, y: 10 }],
type: 'area',
color: 'green',
title: 'Previous period',
},
mlJobId: '1',
anomalyTimeseries: {
boundaries: [
{
color: 'rgba(0,0,0,0)',
areaSeriesStyle: {
point: {
opacity: 0,
},
},
data: [
{
x: 1,
y: 1,
},
],
type: 'area',
fit: 'lookahead',
hideLegend: true,
hideTooltipValue: true,
stackAccessors: ['y'],
areaSeriesStyle: { point: { opacity: 0 } },
title: 'anomalyBoundariesLower',
type: 'area',
data: [{ x: 1, y: 1 }],
color: 'rgba(0,0,0,0)',
},
{
color: 'rgba(0,0,255,0.5)',
areaSeriesStyle: {
point: {
opacity: 0,
},
},
data: [
{
x: 1,
y: 1,
},
],
type: 'area',
fit: 'lookahead',
hideLegend: true,
hideTooltipValue: true,
stackAccessors: ['y'],
areaSeriesStyle: { point: { opacity: 0 } },
title: 'anomalyBoundariesUpper',
type: 'area',
data: [{ x: 1, y: 1 }],
color: 'rgba(0,0,255,0.5)',
},
],
scores: {
color: 'yellow',
data: [
{
x: 1,
x0: 2,
},
],
title: 'anomalyScores',
type: 'rectAnnotation',
data: [{ x: 1, x0: 2 }],
color: 'yellow',
},
},
latencyTimeseries: [
{
color: 'black',
data: [
{
x: 1,
y: 10,
},
],
title: '99th percentile',
titleShort: '99th',
type: 'linemark',
},
],
mlJobId: '1',
});
});
});
Expand Down
Loading

0 comments on commit f428b10

Please sign in to comment.