mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[APM] Don't use service tx metrics on transaction detail page (#159085)
This commit is contained in:
parent
08dbefd3bc
commit
74102e592f
7 changed files with 153 additions and 16 deletions
|
@ -242,6 +242,52 @@ describe('createRouter', () => {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns params for the best-matching path regardless of the order', () => {
|
||||
history.push('/services/opbeans-java/errors/foo?rangeFrom=now-15m&rangeTo=now');
|
||||
|
||||
expect(
|
||||
router.getParams(
|
||||
'/services/{serviceName}/errors',
|
||||
'/services/{serviceName}/errors/*',
|
||||
history.location
|
||||
).path
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
groupId: 'foo',
|
||||
})
|
||||
);
|
||||
|
||||
expect(
|
||||
router.getParams(
|
||||
'/services/{serviceName}/errors/*',
|
||||
'/services/{serviceName}/errors',
|
||||
history.location
|
||||
).path
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
groupId: 'foo',
|
||||
})
|
||||
);
|
||||
|
||||
expect(router.getParams('/*', history.location).path).toEqual(
|
||||
expect.objectContaining({
|
||||
groupId: 'foo',
|
||||
})
|
||||
);
|
||||
|
||||
expect(
|
||||
router.getParams(
|
||||
'/services/{serviceName}/errors',
|
||||
'/services/{serviceName}/errors/{groupId}',
|
||||
history.location
|
||||
).path
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
groupId: 'foo',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('matchRoutes', () => {
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { deepExactRt, mergeRt } from '@kbn/io-ts-utils';
|
||||
import { isLeft } from 'fp-ts/lib/Either';
|
||||
import { Location } from 'history';
|
||||
import { PathReporter } from 'io-ts/lib/PathReporter';
|
||||
import { compact, findLastIndex, merge, orderBy } from 'lodash';
|
||||
import qs from 'query-string';
|
||||
import {
|
||||
MatchedRoute,
|
||||
matchRoutes as matchRoutesConfig,
|
||||
RouteConfig as ReactRouterConfig,
|
||||
} from 'react-router-config';
|
||||
import qs from 'query-string';
|
||||
import { findLastIndex, merge, compact } from 'lodash';
|
||||
import { mergeRt, deepExactRt } from '@kbn/io-ts-utils';
|
||||
import { FlattenRoutesOf, Route, RouteWithPath, Router, RouteMap } from './types';
|
||||
import { FlattenRoutesOf, Route, RouteMap, Router, RouteWithPath } from './types';
|
||||
|
||||
function toReactRouterPath(path: string) {
|
||||
return path.replace(/(?:{([^\/]+)})/g, ':$1');
|
||||
|
@ -87,8 +87,18 @@ export function createRouter<TRoutes extends RouteMap>(routes: TRoutes): Router<
|
|||
let matches: Array<MatchedRoute<{}, ReactRouterConfig>> = [];
|
||||
let matchIndex: number = -1;
|
||||
|
||||
for (const path of paths) {
|
||||
const greedy = path.endsWith('/*') || args.length === 0;
|
||||
const pathsWithScore = paths.map((path) => {
|
||||
const greedy = path.endsWith('/*') || args.length === 0 ? 1 : 0;
|
||||
return {
|
||||
length: path.length,
|
||||
greedy,
|
||||
path,
|
||||
};
|
||||
});
|
||||
|
||||
const sortedPaths = orderBy(pathsWithScore, ['greedy', 'length'], ['desc', 'desc']);
|
||||
|
||||
for (const { path, greedy } of sortedPaths) {
|
||||
matches = matchRoutesConfig(reactRouterConfigs, toReactRouterPath(location.pathname));
|
||||
|
||||
matchIndex = greedy
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { APIReturnType } from '../../../../../public/services/rest/create_call_apm_api';
|
||||
import { synthtrace } from '../../../../synthtrace';
|
||||
import { opbeans } from '../../../fixtures/synthtrace/opbeans';
|
||||
|
||||
|
@ -32,15 +32,75 @@ describe('Transaction details', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
cy.loginAsViewerUser();
|
||||
cy.visitKibana(
|
||||
});
|
||||
|
||||
it('shows transaction name and transaction charts', () => {
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'/internal/apm/services/opbeans-java/transactions/charts/latency?*'
|
||||
).as('transactionLatencyRequest');
|
||||
|
||||
cy.intercept('GET', '/internal/apm/services/opbeans-java/throughput?*').as(
|
||||
'transactionThroughputRequest'
|
||||
);
|
||||
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'/internal/apm/services/opbeans-java/transactions/charts/error_rate?*'
|
||||
).as('transactionFailureRateRequest');
|
||||
|
||||
cy.visit(
|
||||
`/app/apm/services/opbeans-java/transactions/view?${new URLSearchParams({
|
||||
...timeRange,
|
||||
transactionName: 'GET /api/product',
|
||||
})}`
|
||||
);
|
||||
});
|
||||
|
||||
it('shows transaction name and transaction charts', () => {
|
||||
cy.wait([
|
||||
'@transactionLatencyRequest',
|
||||
'@transactionThroughputRequest',
|
||||
'@transactionFailureRateRequest',
|
||||
]).spread(
|
||||
(
|
||||
latencyInterception,
|
||||
throughputInterception,
|
||||
failureRateInterception
|
||||
) => {
|
||||
expect(latencyInterception.request.query.transactionName).to.be.eql(
|
||||
'GET /api/product'
|
||||
);
|
||||
|
||||
expect(
|
||||
(
|
||||
latencyInterception.response
|
||||
?.body as APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/latency'>
|
||||
).currentPeriod.latencyTimeseries[0].y
|
||||
).to.eql(1000 * 1000);
|
||||
|
||||
expect(throughputInterception.request.query.transactionName).to.be.eql(
|
||||
'GET /api/product'
|
||||
);
|
||||
|
||||
expect(
|
||||
(
|
||||
throughputInterception.response
|
||||
?.body as APIReturnType<'GET /internal/apm/services/{serviceName}/throughput'>
|
||||
).currentPeriod[0].y
|
||||
).to.eql(60);
|
||||
|
||||
expect(failureRateInterception.request.query.transactionName).to.be.eql(
|
||||
'GET /api/product'
|
||||
);
|
||||
|
||||
expect(
|
||||
(
|
||||
failureRateInterception.response
|
||||
?.body as APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate'>
|
||||
).currentPeriod.average
|
||||
).to.eql(1);
|
||||
}
|
||||
);
|
||||
|
||||
cy.contains('h2', 'GET /api/product');
|
||||
cy.getByTestSubj('latencyChart');
|
||||
cy.getByTestSubj('throughput');
|
||||
|
@ -49,6 +109,13 @@ describe('Transaction details', () => {
|
|||
});
|
||||
|
||||
it('shows top errors table', () => {
|
||||
cy.visitKibana(
|
||||
`/app/apm/services/opbeans-java/transactions/view?${new URLSearchParams({
|
||||
...timeRange,
|
||||
transactionName: 'GET /api/product',
|
||||
})}`
|
||||
);
|
||||
|
||||
cy.contains('Top 5 errors');
|
||||
cy.getByTestSubj('topErrorsForTransactionTable')
|
||||
.contains('a', '[MockError] Foo')
|
||||
|
@ -58,6 +125,15 @@ describe('Transaction details', () => {
|
|||
|
||||
describe('when navigating to a trace sample', () => {
|
||||
it('keeps the same trace sample after reloading the page', () => {
|
||||
cy.visitKibana(
|
||||
`/app/apm/services/opbeans-java/transactions/view?${new URLSearchParams(
|
||||
{
|
||||
...timeRange,
|
||||
transactionName: 'GET /api/product',
|
||||
}
|
||||
)}`
|
||||
);
|
||||
|
||||
cy.getByTestSubj('pagination-button-last').click();
|
||||
cy.url().then((url) => {
|
||||
cy.reload();
|
||||
|
|
|
@ -40,7 +40,7 @@ export function opbeans({ from, to }: { from: number; to: number }) {
|
|||
.transaction({ transactionName: 'GET /api/product' })
|
||||
.timestamp(timestamp)
|
||||
.duration(1000)
|
||||
.success()
|
||||
.failure()
|
||||
.errors(
|
||||
opbeansJava
|
||||
.error({ message: '[MockError] Foo', type: `Exception` })
|
||||
|
@ -55,7 +55,7 @@ export function opbeans({ from, to }: { from: number; to: number }) {
|
|||
})
|
||||
.timestamp(timestamp)
|
||||
.duration(50)
|
||||
.success()
|
||||
.failure()
|
||||
.destination('postgresql')
|
||||
),
|
||||
opbeansNode
|
||||
|
|
|
@ -67,7 +67,9 @@ export function ServiceOverviewThroughputChart({
|
|||
end,
|
||||
numBuckets: 100,
|
||||
kuery,
|
||||
type: ApmDocumentType.ServiceTransactionMetric,
|
||||
type: transactionName
|
||||
? ApmDocumentType.TransactionMetric
|
||||
: ApmDocumentType.ServiceTransactionMetric,
|
||||
});
|
||||
|
||||
const { transactionType, serviceName, transactionTypeStatus } =
|
||||
|
|
|
@ -78,7 +78,9 @@ export function FailedTransactionRateChart({
|
|||
end,
|
||||
numBuckets: 100,
|
||||
kuery,
|
||||
type: ApmDocumentType.ServiceTransactionMetric,
|
||||
type: transactionName
|
||||
? ApmDocumentType.TransactionMetric
|
||||
: ApmDocumentType.ServiceTransactionMetric,
|
||||
});
|
||||
|
||||
const { environment } = useEnvironmentsContext();
|
||||
|
|
|
@ -37,7 +37,6 @@ export function useTransactionLatencyChartsFetcher({
|
|||
'/services/{serviceName}',
|
||||
'/mobile-services/{serviceName}'
|
||||
);
|
||||
|
||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||
|
||||
const preferred = usePreferredDataSourceAndBucketSize({
|
||||
|
@ -45,7 +44,9 @@ export function useTransactionLatencyChartsFetcher({
|
|||
numBuckets: 100,
|
||||
start,
|
||||
end,
|
||||
type: ApmDocumentType.ServiceTransactionMetric,
|
||||
type: transactionName
|
||||
? ApmDocumentType.TransactionMetric
|
||||
: ApmDocumentType.ServiceTransactionMetric,
|
||||
});
|
||||
|
||||
const shouldUseDurationSummary =
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue