Skip to content

Commit

Permalink
[APM] Add error rates to Service Map popovers
Browse files Browse the repository at this point in the history
Make the `getErrorRate` function used in the error rate charts additionally take `service.environment` as a filter and have it return the `average` of the values.

Call that function in the API for the service map metrics.

Fixes elastic#68160.
  • Loading branch information
smith committed Jun 18, 2020
1 parent e552a96 commit f07d9fb
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 56 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/common/service_map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export interface ServiceNodeMetrics {
avgCpuUsage: number | null;
avgTransactionDuration: number | null;
avgRequestsPerMinute: number | null;
avgErrorsPerMinute: number | null;
avgErrorRate: number | null;
}

export function isValidPlatinumLicense(license: ILicense) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,41 @@ import { ServiceMetricList } from './ServiceMetricList';
storiesOf('app/ServiceMap/Popover/ServiceMetricList', module)
.add('example', () => (
<ServiceMetricList
avgErrorsPerMinute={15.738888706725826}
avgTransactionDuration={61634.38905590272}
avgRequestsPerMinute={164.47222031860858}
avgCpuUsage={0.32809666568309237}
avgErrorRate={0.556068173242986}
avgMemoryUsage={0.5504868173242986}
avgRequestsPerMinute={164.47222031860858}
avgTransactionDuration={61634.38905590272}
isLoading={false}
/>
))
.add('loading', () => (
<ServiceMetricList
avgErrorsPerMinute={null}
avgTransactionDuration={null}
avgRequestsPerMinute={null}
avgCpuUsage={null}
avgErrorRate={null}
avgMemoryUsage={null}
avgRequestsPerMinute={null}
avgTransactionDuration={null}
isLoading={true}
/>
))
.add('some null values', () => (
<ServiceMetricList
avgErrorsPerMinute={7.615972134074397}
avgTransactionDuration={238792.54809512055}
avgRequestsPerMinute={8.439583235652972}
avgCpuUsage={null}
avgErrorRate={0.615972134074397}
avgMemoryUsage={null}
avgRequestsPerMinute={8.439583235652972}
avgTransactionDuration={238792.54809512055}
isLoading={false}
/>
))
.add('all null values', () => (
<ServiceMetricList
avgErrorsPerMinute={null}
avgTransactionDuration={null}
avgRequestsPerMinute={null}
avgCpuUsage={null}
avgErrorRate={null}
avgMemoryUsage={null}
avgRequestsPerMinute={null}
avgTransactionDuration={null}
isLoading={false}
/>
));
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ interface ServiceMetricListProps extends ServiceNodeMetrics {
export function ServiceMetricList({
avgTransactionDuration,
avgRequestsPerMinute,
avgErrorsPerMinute,
avgErrorRate,
avgCpuUsage,
avgMemoryUsage,
isLoading,
Expand Down Expand Up @@ -74,13 +74,10 @@ export function ServiceMetricList({
: null,
},
{
title: i18n.translate(
'xpack.apm.serviceMap.avgErrorsPerMinutePopoverMetric',
{
defaultMessage: 'Errors per minute (avg.)',
}
),
description: avgErrorsPerMinute?.toFixed(2),
title: i18n.translate('xpack.apm.serviceMap.errorRatePopoverMetric', {
defaultMessage: 'Error rate (avg.)',
}),
description: isNumber(avgErrorRate) ? asPercent(avgErrorRate, 1) : null,
},
{
title: i18n.translate('xpack.apm.serviceMap.avgCpuUsagePopoverMetric', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const ErrorRateChart = () => {
{
color: theme.euiColorVis7,
data: [],
legendValue: tickFormatY(mean(errorRates.map((rate) => rate.y))),
legendValue: tickFormatY(errorRateData?.average),
legendClickDisabled: true,
title: i18n.translate('xpack.apm.errorRateChart.avgLabel', {
defaultMessage: 'Avg.',
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/apm/server/lib/errors/get_error_rate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import mean from 'lodash.mean';
import {
ERROR_GROUP_ID,
PROCESSOR_EVENT,
SERVICE_ENVIRONMENT,
SERVICE_NAME,
} from '../../../common/elasticsearch_fieldnames';
import { ProcessorEvent } from '../../../common/processor_event';
Expand All @@ -20,17 +23,20 @@ import {
export async function getErrorRate({
serviceName,
groupId,
environment,
setup,
}: {
serviceName: string;
groupId?: string;
environment?: string;
setup: Setup & SetupTimeRange & SetupUIFilters;
}) {
const { start, end, uiFiltersES, client, indices } = setup;

const filter = [
{ term: { [SERVICE_NAME]: serviceName } },
{ range: rangeFilter(start, end) },
...(environment ? [{ term: { [SERVICE_ENVIRONMENT]: environment } }] : []),
...uiFiltersES,
];

Expand Down Expand Up @@ -101,8 +107,10 @@ export async function getErrorRate({
const relativeRate = errorCount / transactionCountByTimestamp[key];
return { x: key, y: relativeRate };
});
const average = mean((errorRates ?? []).map((errorRate) => errorRate.y));

return {
average,
noHits: transactions?.totalHits === 0,
errorRates,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { Setup, SetupTimeRange } from '../helpers/setup_request';
import { ESFilter } from '../../../typings/elasticsearch';
import { rangeFilter } from '../helpers/range_filter';
import {
METRIC_SYSTEM_CPU_PERCENT,
METRIC_SYSTEM_FREE_MEMORY,
METRIC_SYSTEM_TOTAL_MEMORY,
PROCESSOR_EVENT,
SERVICE_ENVIRONMENT,
SERVICE_NAME,
TRANSACTION_DURATION,
METRIC_SYSTEM_CPU_PERCENT,
METRIC_SYSTEM_FREE_MEMORY,
METRIC_SYSTEM_TOTAL_MEMORY,
} from '../../../common/elasticsearch_fieldnames';
import { ProcessorEvent } from '../../../common/processor_event';
import { ESFilter } from '../../../typings/elasticsearch';
import { getErrorRate } from '../errors/get_error_rate';
import { rangeFilter } from '../helpers/range_filter';
import { Setup, SetupTimeRange } from '../helpers/setup_request';
import { percentMemoryUsedScript } from '../metrics/by_agent/shared/memory';

interface Options {
Expand Down Expand Up @@ -57,7 +59,7 @@ export async function getServiceMapServiceNodeInfo({
cpuMetrics,
memoryMetrics,
] = await Promise.all([
getErrorMetrics(taskParams),
getErrorMetrics({ serviceName, setup, environment }),
getTransactionMetrics(taskParams),
getCpuMetrics(taskParams),
getMemoryMetrics(taskParams),
Expand All @@ -71,32 +73,24 @@ export async function getServiceMapServiceNodeInfo({
};
}

async function getErrorMetrics({ setup, minutes, filter }: TaskParameters) {
const { client, indices } = setup;

const response = await client.search({
index: indices['apm_oss.errorIndices'],
body: {
size: 0,
query: {
bool: {
filter: filter.concat({
term: {
[PROCESSOR_EVENT]: 'error',
},
}),
},
},
track_total_hits: true,
},
async function getErrorMetrics({
environment,
serviceName,
setup,
}: {
environment?: string;
serviceName: string;
setup: Options['setup'];
}) {
const groupId = undefined;
const { average, noHits } = await getErrorRate({
serviceName,
groupId,
environment,
setup: { ...setup, uiFiltersES: [] },
});

return {
avgErrorsPerMinute:
response.hits.total.value > 0
? response.hits.total.value / minutes
: null,
};
return { avgErrorRate: noHits ? null : average };
}

async function getTransactionMetrics({
Expand All @@ -117,7 +111,7 @@ async function getTransactionMetrics({
bool: {
filter: filter.concat({
term: {
[PROCESSOR_EVENT]: 'transaction',
[PROCESSOR_EVENT]: ProcessorEvent.transaction,
},
}),
},
Expand Down Expand Up @@ -157,7 +151,7 @@ async function getCpuMetrics({
filter: filter.concat([
{
term: {
[PROCESSOR_EVENT]: 'metric',
[PROCESSOR_EVENT]: ProcessorEvent.metric,
},
},
{
Expand Down Expand Up @@ -196,7 +190,7 @@ async function getMemoryMetrics({
filter: filter.concat([
{
term: {
[PROCESSOR_EVENT]: 'metric',
[PROCESSOR_EVENT]: ProcessorEvent.metric,
},
},
{
Expand Down

0 comments on commit f07d9fb

Please sign in to comment.