[APM] Add missing trace_id to transaction histogram (#27591)
* [APM] Add missing trace_id to transaction histogram * Handle 404 properly * Fix `unhandled` issue * Fix tests
This commit is contained in:
parent
c72dd3f2d9
commit
c7bd296ac4
|
@ -34,7 +34,7 @@ describe('StickyProperties', () => {
|
|||
{
|
||||
label: 'Handled',
|
||||
fieldName: 'error.exception.handled',
|
||||
val: 'true'
|
||||
val: true
|
||||
},
|
||||
{
|
||||
label: 'User ID',
|
||||
|
|
|
@ -101,7 +101,7 @@ function getPropertyValue({
|
|||
);
|
||||
}
|
||||
|
||||
return <PropertyValue>{val}</PropertyValue>;
|
||||
return <PropertyValue>{String(val)}</PropertyValue>;
|
||||
}
|
||||
|
||||
export function StickyProperties({
|
||||
|
|
|
@ -40,6 +40,7 @@ export async function loadTransactionDistribution({
|
|||
transactionName,
|
||||
transactionType = 'request',
|
||||
transactionId,
|
||||
traceId,
|
||||
kuery
|
||||
}: Required<IUrlParams>) {
|
||||
return callApi<ITransactionDistributionAPIResponse>({
|
||||
|
@ -50,6 +51,7 @@ export async function loadTransactionDistribution({
|
|||
start,
|
||||
end,
|
||||
transactionId,
|
||||
traceId,
|
||||
esFilterQuery: await getEncodedEsQuery(kuery)
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { KFetchError } from 'ui/kfetch/kfetch_error';
|
||||
import { TransactionAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/get_transaction';
|
||||
import { SpanListAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/spans/get_spans';
|
||||
import { Span } from 'x-pack/plugins/apm/typings/es_schemas/Span';
|
||||
|
@ -43,6 +44,7 @@ export async function loadTransaction({
|
|||
traceId,
|
||||
kuery
|
||||
}: IUrlParams) {
|
||||
try {
|
||||
const result = await callApi<TransactionAPIResponse>(
|
||||
{
|
||||
pathname: `/api/apm/services/${serviceName}/transactions/${transactionId}`,
|
||||
|
@ -57,6 +59,16 @@ export async function loadTransaction({
|
|||
camelcase: false
|
||||
}
|
||||
);
|
||||
|
||||
return addVersion(result);
|
||||
} catch (e) {
|
||||
const err: KFetchError = e;
|
||||
|
||||
// swallow 404 errors
|
||||
if (err.res.status === 404) {
|
||||
return;
|
||||
}
|
||||
|
||||
// re-throw all other errors
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ export function TransactionDistributionRequest({
|
|||
serviceName,
|
||||
transactionType,
|
||||
transactionId,
|
||||
traceId,
|
||||
start,
|
||||
end,
|
||||
transactionName,
|
||||
|
@ -66,6 +67,7 @@ export function TransactionDistributionRequest({
|
|||
serviceName,
|
||||
transactionType,
|
||||
transactionId,
|
||||
traceId,
|
||||
start,
|
||||
end,
|
||||
transactionName,
|
||||
|
|
|
@ -45,6 +45,7 @@ export function bucketFetcher(
|
|||
transactionName: string,
|
||||
transactionType: string,
|
||||
transactionId: string,
|
||||
traceId: string,
|
||||
bucketSize: number,
|
||||
setup: Setup
|
||||
): Promise<ESResponse> {
|
||||
|
@ -77,6 +78,7 @@ export function bucketFetcher(
|
|||
bool: {
|
||||
filter,
|
||||
should: [
|
||||
{ term: { [TRACE_ID]: traceId } },
|
||||
{ term: { [TRANSACTION_ID]: transactionId } },
|
||||
{ term: { [TRANSACTION_SAMPLED]: true } }
|
||||
]
|
||||
|
|
|
@ -13,6 +13,7 @@ export async function getBuckets(
|
|||
transactionName: string,
|
||||
transactionType: string,
|
||||
transactionId: string,
|
||||
traceId: string,
|
||||
bucketSize: number,
|
||||
setup: Setup
|
||||
) {
|
||||
|
@ -21,6 +22,7 @@ export async function getBuckets(
|
|||
transactionName,
|
||||
transactionType,
|
||||
transactionId,
|
||||
traceId,
|
||||
bucketSize,
|
||||
setup
|
||||
);
|
||||
|
|
|
@ -21,6 +21,7 @@ export async function getDistribution(
|
|||
transactionName: string,
|
||||
transactionType: string,
|
||||
transactionId: string,
|
||||
traceId: string,
|
||||
setup: Setup
|
||||
): Promise<ITransactionDistributionAPIResponse> {
|
||||
const bucketSize = await calculateBucketSize(
|
||||
|
@ -35,6 +36,7 @@ export async function getDistribution(
|
|||
transactionName,
|
||||
transactionType,
|
||||
transactionId,
|
||||
traceId,
|
||||
bucketSize,
|
||||
setup
|
||||
);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { SearchParams } from 'elasticsearch';
|
||||
import { ESFilter } from 'elasticsearch';
|
||||
import { oc } from 'ts-optchain';
|
||||
import { Transaction } from 'x-pack/plugins/apm/typings/es_schemas/Transaction';
|
||||
import {
|
||||
|
@ -23,13 +23,7 @@ export async function getTransaction(
|
|||
): Promise<TransactionAPIResponse> {
|
||||
const { start, end, esFilterQuery, client, config } = setup;
|
||||
|
||||
const params: SearchParams = {
|
||||
index: config.get('apm_oss.transactionIndices'),
|
||||
body: {
|
||||
size: 1,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
const filter: ESFilter[] = [
|
||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
||||
{ term: { [TRANSACTION_ID]: transactionId } },
|
||||
{
|
||||
|
@ -41,20 +35,28 @@ export async function getTransaction(
|
|||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
if (esFilterQuery) {
|
||||
filter.push(esFilterQuery);
|
||||
}
|
||||
|
||||
if (traceId) {
|
||||
filter.push({ term: { [TRACE_ID]: traceId } });
|
||||
}
|
||||
|
||||
const params = {
|
||||
index: config.get<string>('apm_oss.transactionIndices'),
|
||||
body: {
|
||||
size: 1,
|
||||
query: {
|
||||
bool: {
|
||||
filter
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (esFilterQuery) {
|
||||
params.body.query.bool.filter.push(esFilterQuery);
|
||||
}
|
||||
|
||||
if (traceId) {
|
||||
params.body.query.bool.filter.push({ term: { [TRACE_ID]: traceId } });
|
||||
}
|
||||
|
||||
const resp = await client<Transaction>('search', params);
|
||||
return oc(resp).hits.hits[0]._source();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import { Setup } from '../../helpers/setup_request';
|
|||
|
||||
export type SpanListAPIResponse = Span[];
|
||||
|
||||
// Deprecated and will be removed in 7.0. Only needed for backwards compatability pre 6.5 (introducition of v2 API and distributed tracing)
|
||||
export async function getSpans(
|
||||
transactionId: string,
|
||||
setup: Setup
|
||||
|
|
|
@ -12,7 +12,6 @@ import { initServicesApi } from '../services';
|
|||
// @ts-ignore
|
||||
import { initStatusApi } from '../status_check';
|
||||
import { initTracesApi } from '../traces';
|
||||
import { initTransactionsApi } from '../transactions';
|
||||
|
||||
describe('route handlers should fail with a Boom error', () => {
|
||||
let consoleErrorSpy: any;
|
||||
|
@ -76,8 +75,4 @@ describe('route handlers should fail with a Boom error', () => {
|
|||
describe('trace routes', async () => {
|
||||
await testRouteFailures(initTracesApi);
|
||||
});
|
||||
|
||||
describe('transaction routes', async () => {
|
||||
await testRouteFailures(initTransactionsApi);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -109,19 +109,24 @@ export function initTransactionGroupsApi(server: Server) {
|
|||
options: {
|
||||
validate: {
|
||||
query: withDefaultValidators({
|
||||
transactionId: Joi.string().default('')
|
||||
transactionId: Joi.string().default(''),
|
||||
traceId: Joi.string().default('')
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: req => {
|
||||
const setup = setupRequest(req);
|
||||
const { serviceName, transactionType, transactionName } = req.params;
|
||||
const { transactionId } = req.query as { transactionId: string };
|
||||
const { transactionId, traceId } = req.query as {
|
||||
transactionId: string;
|
||||
traceId: string;
|
||||
};
|
||||
return getDistribution(
|
||||
serviceName,
|
||||
transactionName,
|
||||
transactionType,
|
||||
transactionId,
|
||||
traceId,
|
||||
setup
|
||||
).catch(defaultErrorHandler);
|
||||
}
|
||||
|
|
|
@ -12,12 +12,6 @@ import { setupRequest } from '../lib/helpers/setup_request';
|
|||
import { getTransaction } from '../lib/transactions/get_transaction';
|
||||
import { getSpans } from '../lib/transactions/spans/get_spans';
|
||||
|
||||
const defaultErrorHandler = (err: Error) => {
|
||||
// tslint:disable-next-line
|
||||
console.error(err.stack);
|
||||
throw Boom.boomify(err, { statusCode: 400 });
|
||||
};
|
||||
|
||||
export function initTransactionsApi(server: Server) {
|
||||
server.route({
|
||||
method: 'GET',
|
||||
|
@ -29,13 +23,16 @@ export function initTransactionsApi(server: Server) {
|
|||
})
|
||||
}
|
||||
},
|
||||
handler: req => {
|
||||
handler: async req => {
|
||||
const { transactionId } = req.params;
|
||||
const { traceId } = req.query as { traceId: string };
|
||||
const setup = setupRequest(req);
|
||||
return getTransaction(transactionId, traceId, setup).catch(
|
||||
defaultErrorHandler
|
||||
);
|
||||
const transaction = await getTransaction(transactionId, traceId, setup);
|
||||
if (transaction) {
|
||||
return transaction;
|
||||
} else {
|
||||
throw Boom.notFound('Cannot find the requested page');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -51,7 +48,7 @@ export function initTransactionsApi(server: Server) {
|
|||
handler: req => {
|
||||
const { transactionId } = req.params;
|
||||
const setup = setupRequest(req);
|
||||
return getSpans(transactionId, setup).catch(defaultErrorHandler);
|
||||
return getSpans(transactionId, setup);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -82,8 +82,7 @@ uiModule.directive('monitoringMain', (breadcrumbs, license, kbnUrl, config) => {
|
|||
link(scope, _element, attributes, controller) {
|
||||
config.watch('k7design', (val) => scope.showPluginBreadcrumbs = !val);
|
||||
|
||||
function getSetupObj() {
|
||||
return {
|
||||
controller.setup({
|
||||
licenseService: license,
|
||||
breadcrumbsService: breadcrumbs,
|
||||
kbnUrlService: kbnUrl,
|
||||
|
@ -100,17 +99,10 @@ uiModule.directive('monitoringMain', (breadcrumbs, license, kbnUrl, config) => {
|
|||
pipelineVersions: get(scope, 'pageData.versions')
|
||||
},
|
||||
clusterName: get(scope, 'cluster.cluster_name')
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const setupObj = getSetupObj();
|
||||
controller.setup(setupObj);
|
||||
Object.keys(setupObj.attributes).forEach(key => {
|
||||
attributes.$observe(key, () => controller.setup(getSetupObj()));
|
||||
});
|
||||
scope.$watch('pageData.versions', versions => {
|
||||
controller.pipelineVersions = versions;
|
||||
});
|
||||
attributes.$observe('instance', instance => controller.instance = instance);
|
||||
attributes.$observe('resolver', resolver => controller.resolver = resolver);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -98,9 +98,6 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', {
|
|||
getPageData,
|
||||
reactNodeId: 'monitoringLogstashPipelineApp',
|
||||
$scope,
|
||||
options: {
|
||||
enableTimeFilter: false,
|
||||
},
|
||||
$injector
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue