kibana/x-pack/plugins/apm/server/routes/transaction_groups.ts
Søren Louv-Jansen 4ddcd1d2a6
[APM] Fix anomalies not showing up on transaction charts (#76930)
* [APM] Fix anomalies not showing up on transaction charts

* Added API tests to check transaction groups charts for anomaly data

* Improve test names and assertions from PR feedback

* Updated the transaction groups chart API to make `environment` a
required param while making `uiFilters` optional

* updates the basic API tests for transaction_groups/charts with the
required `environment` param

* makes uiFIltersES default to [] on core setup and removes SetupUIFilters type

* fixes vertical shade

* - replaces uiFiltersES with esFilter & uiFilters and cleans up related code around these
- deduplicates the required environment in the transaction_groups/charts API

* updates basic apm_api_integration tests

* pr feedback

* updates api test snapshots with correct anomaly data

* removed environment query param from useTransactionCharts and ensures
it's included in uiFilters returned from useUrlParams

Co-authored-by: Oliver Gupte <olivergupte@gmail.com>
2020-10-02 00:45:50 -07:00

233 lines
6.1 KiB
TypeScript

/*
* 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 * as t from 'io-ts';
import Boom from 'boom';
import { setupRequest } from '../lib/helpers/setup_request';
import { getTransactionCharts } from '../lib/transactions/charts';
import { getTransactionDistribution } from '../lib/transactions/distribution';
import { getTransactionBreakdown } from '../lib/transactions/breakdown';
import { getTransactionGroupList } from '../lib/transaction_groups';
import { createRoute } from './create_route';
import { uiFiltersRt, rangeRt } from './default_api_types';
import { getTransactionSampleForGroup } from '../lib/transaction_groups/get_transaction_sample_for_group';
import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions';
import { getErrorRate } from '../lib/transaction_groups/get_error_rate';
export const transactionGroupsRoute = createRoute(() => ({
path: '/api/apm/services/{serviceName}/transaction_groups',
params: {
path: t.type({
serviceName: t.string,
}),
query: t.intersection([
t.type({
transactionType: t.string,
}),
uiFiltersRt,
rangeRt,
]),
},
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
const { serviceName } = context.params.path;
const { transactionType } = context.params.query;
const searchAggregatedTransactions = await getSearchAggregatedTransactions(
setup
);
return getTransactionGroupList(
{
type: 'top_transactions',
serviceName,
transactionType,
searchAggregatedTransactions,
},
setup
);
},
}));
export const transactionGroupsChartsRoute = createRoute(() => ({
path: '/api/apm/services/{serviceName}/transaction_groups/charts',
params: {
path: t.type({
serviceName: t.string,
}),
query: t.intersection([
t.partial({
transactionType: t.string,
transactionName: t.string,
}),
uiFiltersRt,
rangeRt,
]),
},
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
const logger = context.logger;
const { serviceName } = context.params.path;
const { transactionType, transactionName } = context.params.query;
if (!setup.uiFilters.environment) {
throw Boom.badRequest(
`environment is a required property of the ?uiFilters JSON for transaction_groups/charts.`
);
}
const searchAggregatedTransactions = await getSearchAggregatedTransactions(
setup
);
const options = {
serviceName,
transactionType,
transactionName,
setup,
searchAggregatedTransactions,
logger,
};
return getTransactionCharts(options);
},
}));
export const transactionGroupsDistributionRoute = createRoute(() => ({
path: '/api/apm/services/{serviceName}/transaction_groups/distribution',
params: {
path: t.type({
serviceName: t.string,
}),
query: t.intersection([
t.type({
transactionType: t.string,
transactionName: t.string,
}),
t.partial({
transactionId: t.string,
traceId: t.string,
}),
uiFiltersRt,
rangeRt,
]),
},
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
const { serviceName } = context.params.path;
const {
transactionType,
transactionName,
transactionId = '',
traceId = '',
} = context.params.query;
const searchAggregatedTransactions = await getSearchAggregatedTransactions(
setup
);
return getTransactionDistribution({
serviceName,
transactionType,
transactionName,
transactionId,
traceId,
setup,
searchAggregatedTransactions,
});
},
}));
export const transactionGroupsBreakdownRoute = createRoute(() => ({
path: '/api/apm/services/{serviceName}/transaction_groups/breakdown',
params: {
path: t.type({
serviceName: t.string,
}),
query: t.intersection([
t.type({
transactionType: t.string,
}),
t.partial({
transactionName: t.string,
}),
uiFiltersRt,
rangeRt,
]),
},
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
const { serviceName } = context.params.path;
const { transactionName, transactionType } = context.params.query;
return getTransactionBreakdown({
serviceName,
transactionName,
transactionType,
setup,
});
},
}));
export const transactionSampleForGroupRoute = createRoute(() => ({
path: `/api/apm/transaction_sample`,
params: {
query: t.intersection([
uiFiltersRt,
rangeRt,
t.type({ serviceName: t.string, transactionName: t.string }),
]),
},
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
const { transactionName, serviceName } = context.params.query;
return {
transaction: await getTransactionSampleForGroup({
setup,
serviceName,
transactionName,
}),
};
},
}));
export const transactionGroupsErrorRateRoute = createRoute(() => ({
path: '/api/apm/services/{serviceName}/transaction_groups/error_rate',
params: {
path: t.type({
serviceName: t.string,
}),
query: t.intersection([
uiFiltersRt,
rangeRt,
t.partial({
transactionType: t.string,
transactionName: t.string,
}),
]),
},
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
const { params } = context;
const { serviceName } = params.path;
const { transactionType, transactionName } = params.query;
const searchAggregatedTransactions = await getSearchAggregatedTransactions(
setup
);
return getErrorRate({
serviceName,
transactionType,
transactionName,
setup,
searchAggregatedTransactions,
});
},
}));