-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[APM] Service overview: Add throughput chart (#84439)
- v8.17.0
- v8.16.2
- v8.16.1
- v8.16.0
- v8.15.5
- v8.15.4
- v8.15.3
- v8.15.2
- v8.15.1
- v8.15.0
- v8.14.3
- v8.14.2
- v8.14.1
- v8.14.0
- v8.13.4
- v8.13.3
- v8.13.2
- v8.13.1
- v8.13.0
- v8.12.2
- v8.12.1
- v8.12.0
- v8.11.4
- v8.11.3
- v8.11.2
- v8.11.1
- v8.11.0
- v8.10.4
- v8.10.3
- v8.10.2
- v8.10.1
- v8.10.0
- v8.9.2
- v8.9.1
- v8.9.0
- v8.8.2
- v8.8.1
- v8.8.0
- v8.7.1
- v8.7.0
- v8.6.2
- v8.6.1
- v8.6.0
- v8.5.3
- v8.5.2
- v8.5.1
- v8.5.0
- v8.4.3
- v8.4.2
- v8.4.1
- v8.4.0
- v8.3.3
- v8.3.2
- v8.3.1
- v8.3.0
- v8.2.3
- v8.2.2
- v8.2.1
- v8.2.0
- v8.1.3
- v8.1.2
- v8.1.1
- v8.1.0
- v8.0.1
- v8.0.0
- v8.0.0-rc2
- v8.0.0-rc1
- v8.0.0-beta1
- v8.0.0-alpha2
- v8.0.0-alpha1
- test-depl-20231025084603
- test-depl-20231013154558
- deploy-fix-test-ci
- deploy-fix@1728886420
- deploy-fix@1722233551
- deploy-fix@1721023892
- deploy-fix@1720419201
- deploy-fix@1718000036
- deploy-fix@1717401777
- deploy-fix@1708322739
- deploy-fix@1707717945
- deploy-fix@1701687168
- deploy-fix@1699260155
- deploy-fix@1698657637
- deploy@1735539127
- deploy@1734934371
- deploy@1734329529
- deploy@1733724770
- deploy@1733120035
- deploy@1732515196
- deploy@1731910526
- deploy@1731305644
- deploy@1730700921
- deploy@1730095989
- deploy@1729491328
- deploy@1728886420
- deploy@1728281754
- deploy@1727676838
- deploy@1727071987
- deploy@1726473511
- deploy@1725862301
- deploy@1725257503
- deploy@1724652827
- deploy@1724047965
- deploy@1723443177
- deploy@1722838314
- deploy@1722233551
- deploy@1721628835
- deploy@1721023892
- deploy@1720419201
- deploy@1719814351
- deploy@1719209622
- deploy@1718616070
- deploy@1718000036
- deploy@1717401777
- deploy@1717395230
- deploy@1716800745
- deploy@1716790412
- deploy@1716185667
- deploy@1715580861
- deploy@1714976069
- deploy@1714371303
- deploy@1713766425
- deploy@1713161715
- deploy@1712566963
- deploy@1711952105
- deploy@1711370131
- deploy@1710741924
- deploy@1710146776
- deploy@1710137117
- deploy@1709533819
- deploy@1709532332
- deploy@1708927574
- deploy@1708322739
- deploy@1707717945
- deploy@1707113127
- deploy@1706508321
- deploy@1705903520
- deploy@1705306975
- deploy@1705298718
- deploy@1704693922
- deploy@1704089101
- deploy@1703484304
- deploy@1702903357
- deploy@1702879551
- deploy@1702367069
- deploy@1702284899
- deploy@1701687168
- deploy@1701160888
- deploy@1700491293
- deploy@1699865290
- deploy@1699260155
- deploy@1698657637
- deploy@1698046713
- deploy@1697564183
- deploy@1697232175
- deploy@1697028216
- deploy@1696873111
- deploy@1696618725
- deploy@1696508231
- deploy@1696415195
- deploy@1696328885
- deploy@1695286747
- deploy@1694683198
- deploy@1694506029
- deploy@1694162455
- deploy@1694087994
- deploy@1693866333
- deploy@1693860790
- deploy@1693853982
- deploy@1693609987
- deploy@1693594780
Showing
26 changed files
with
750 additions
and
161 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
.../plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* 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 { EuiPanel, EuiTitle } from '@elastic/eui'; | ||
import { i18n } from '@kbn/i18n'; | ||
import React from 'react'; | ||
import { useParams } from 'react-router-dom'; | ||
import { asTransactionRate } from '../../../../common/utils/formatters'; | ||
import { useFetcher } from '../../../hooks/useFetcher'; | ||
import { useTheme } from '../../../hooks/useTheme'; | ||
import { useUrlParams } from '../../../hooks/useUrlParams'; | ||
import { useApmService } from '../../../hooks/use_apm_service'; | ||
import { callApmApi } from '../../../services/rest/createCallApmApi'; | ||
import { TimeseriesChart } from '../../shared/charts/timeseries_chart'; | ||
|
||
export function ServiceOverviewThroughputChart({ | ||
height, | ||
}: { | ||
height?: number; | ||
}) { | ||
const theme = useTheme(); | ||
const { serviceName } = useParams<{ serviceName?: string }>(); | ||
const { urlParams, uiFilters } = useUrlParams(); | ||
const { transactionType } = useApmService(); | ||
const { start, end } = urlParams; | ||
|
||
const { data, status } = useFetcher(() => { | ||
if (serviceName && transactionType && start && end) { | ||
return callApmApi({ | ||
endpoint: 'GET /api/apm/services/{serviceName}/throughput', | ||
params: { | ||
path: { | ||
serviceName, | ||
}, | ||
query: { | ||
start, | ||
end, | ||
transactionType, | ||
uiFilters: JSON.stringify(uiFilters), | ||
}, | ||
}, | ||
}); | ||
} | ||
}, [serviceName, start, end, uiFilters, transactionType]); | ||
|
||
return ( | ||
<EuiPanel> | ||
<EuiTitle size="xs"> | ||
<h2> | ||
{i18n.translate('xpack.apm.serviceOverview.throughtputChartTitle', { | ||
defaultMessage: 'Traffic', | ||
})} | ||
</h2> | ||
</EuiTitle> | ||
<TimeseriesChart | ||
id="throughput" | ||
height={height} | ||
showAnnotations={false} | ||
fetchStatus={status} | ||
timeseries={[ | ||
{ | ||
data: data?.throughput ?? [], | ||
type: 'linemark', | ||
color: theme.eui.euiColorVis0, | ||
title: i18n.translate( | ||
'xpack.apm.serviceOverview.throughputChart.currentPeriodLabel', | ||
{ | ||
defaultMessage: 'Current period', | ||
} | ||
), | ||
}, | ||
]} | ||
yLabelFormat={asTransactionRate} | ||
/> | ||
</EuiPanel> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
x-pack/plugins/apm/public/context/apm_service_context.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* 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 { getTransactionType } from './apm_service_context'; | ||
|
||
describe('getTransactionType', () => { | ||
describe('with transaction type in url', () => { | ||
it('returns the transaction type in the url ', () => { | ||
expect( | ||
getTransactionType({ | ||
transactionTypes: ['worker', 'request'], | ||
urlParams: { transactionType: 'custom' }, | ||
agentName: 'nodejs', | ||
}) | ||
).toBe('custom'); | ||
}); | ||
}); | ||
|
||
describe('with no transaction types', () => { | ||
it('returns undefined', () => { | ||
expect( | ||
getTransactionType({ | ||
transactionTypes: [], | ||
urlParams: {}, | ||
}) | ||
).toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe('with a non-rum agent', () => { | ||
describe('with default transaction type', () => { | ||
it('returns "request"', () => { | ||
expect( | ||
getTransactionType({ | ||
transactionTypes: ['worker', 'request'], | ||
urlParams: {}, | ||
agentName: 'nodejs', | ||
}) | ||
).toEqual('request'); | ||
}); | ||
}); | ||
|
||
describe('with no default transaction type', () => { | ||
it('returns the first type', () => { | ||
expect( | ||
getTransactionType({ | ||
transactionTypes: ['worker', 'custom'], | ||
urlParams: {}, | ||
agentName: 'nodejs', | ||
}) | ||
).toEqual('worker'); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('with a rum agent', () => { | ||
it('returns "page-load"', () => { | ||
expect( | ||
getTransactionType({ | ||
transactionTypes: ['http-request', 'page-load'], | ||
urlParams: {}, | ||
agentName: 'js-base', | ||
}) | ||
).toEqual('page-load'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* 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 React, { createContext, ReactNode } from 'react'; | ||
import { isRumAgentName } from '../../common/agent_name'; | ||
import { | ||
TRANSACTION_PAGE_LOAD, | ||
TRANSACTION_REQUEST, | ||
} from '../../common/transaction_types'; | ||
import { useServiceTransactionTypes } from '../hooks/use_service_transaction_types'; | ||
import { useUrlParams } from '../hooks/useUrlParams'; | ||
import { useServiceAgentName } from '../hooks/use_service_agent_name'; | ||
import { IUrlParams } from './UrlParamsContext/types'; | ||
|
||
export const APMServiceContext = createContext<{ | ||
agentName?: string; | ||
transactionType?: string; | ||
transactionTypes: string[]; | ||
}>({ transactionTypes: [] }); | ||
|
||
export function ApmServiceContextProvider({ | ||
children, | ||
}: { | ||
children: ReactNode; | ||
}) { | ||
const { urlParams } = useUrlParams(); | ||
const { agentName } = useServiceAgentName(); | ||
const transactionTypes = useServiceTransactionTypes(); | ||
const transactionType = getTransactionType({ | ||
urlParams, | ||
transactionTypes, | ||
agentName, | ||
}); | ||
|
||
return ( | ||
<APMServiceContext.Provider | ||
value={{ agentName, transactionType, transactionTypes }} | ||
children={children} | ||
/> | ||
); | ||
} | ||
|
||
export function getTransactionType({ | ||
urlParams, | ||
transactionTypes, | ||
agentName, | ||
}: { | ||
urlParams: IUrlParams; | ||
transactionTypes: string[]; | ||
agentName?: string; | ||
}) { | ||
if (urlParams.transactionType) { | ||
return urlParams.transactionType; | ||
} | ||
|
||
if (!agentName || transactionTypes.length === 0) { | ||
return; | ||
} | ||
|
||
// The default transaction type is "page-load" for RUM agents and "request" for all others | ||
const defaultTransactionType = isRumAgentName(agentName) | ||
? TRANSACTION_PAGE_LOAD | ||
: TRANSACTION_REQUEST; | ||
|
||
// If the default transaction type is not in transactionTypes the first in the list is returned | ||
return transactionTypes.includes(defaultTransactionType) | ||
? defaultTransactionType | ||
: transactionTypes[0]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* 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 { ESFilter } from '../../../../../typings/elasticsearch'; | ||
import { PromiseReturnType } from '../../../../observability/typings/common'; | ||
import { | ||
SERVICE_NAME, | ||
TRANSACTION_TYPE, | ||
} from '../../../common/elasticsearch_fieldnames'; | ||
import { rangeFilter } from '../../../common/utils/range_filter'; | ||
import { | ||
getDocumentTypeFilterForAggregatedTransactions, | ||
getProcessorEventForAggregatedTransactions, | ||
} from '../helpers/aggregated_transactions'; | ||
import { getBucketSize } from '../helpers/get_bucket_size'; | ||
import { Setup, SetupTimeRange } from '../helpers/setup_request'; | ||
|
||
interface Options { | ||
searchAggregatedTransactions: boolean; | ||
serviceName: string; | ||
setup: Setup & SetupTimeRange; | ||
transactionType: string; | ||
} | ||
|
||
type ESResponse = PromiseReturnType<typeof fetcher>; | ||
|
||
function transform(response: ESResponse) { | ||
const buckets = response.aggregations?.throughput?.buckets ?? []; | ||
return buckets.map(({ key: x, doc_count: y }) => ({ x, y })); | ||
} | ||
|
||
async function fetcher({ | ||
searchAggregatedTransactions, | ||
serviceName, | ||
setup, | ||
transactionType, | ||
}: Options) { | ||
const { start, end, apmEventClient } = setup; | ||
const { intervalString } = getBucketSize({ start, end }); | ||
const filter: ESFilter[] = [ | ||
{ term: { [SERVICE_NAME]: serviceName } }, | ||
{ term: { [TRANSACTION_TYPE]: transactionType } }, | ||
{ range: rangeFilter(start, end) }, | ||
...getDocumentTypeFilterForAggregatedTransactions( | ||
searchAggregatedTransactions | ||
), | ||
...setup.esFilter, | ||
]; | ||
|
||
const params = { | ||
apm: { | ||
events: [ | ||
getProcessorEventForAggregatedTransactions( | ||
searchAggregatedTransactions | ||
), | ||
], | ||
}, | ||
body: { | ||
size: 0, | ||
query: { bool: { filter } }, | ||
aggs: { | ||
throughput: { | ||
date_histogram: { | ||
field: '@timestamp', | ||
fixed_interval: intervalString, | ||
min_doc_count: 0, | ||
extended_bounds: { min: start, max: end }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
return apmEventClient.search(params); | ||
} | ||
|
||
export async function getThroughput(options: Options) { | ||
return { | ||
throughput: transform(await fetcher(options)), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
250 changes: 250 additions & 0 deletions
250
x-pack/test/apm_api_integration/basic/tests/services/__snapshots__/throughput.snap
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
85 changes: 85 additions & 0 deletions
85
x-pack/test/apm_api_integration/basic/tests/services/throughput.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* 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 expect from '@kbn/expect'; | ||
import qs from 'querystring'; | ||
import { first, last } from 'lodash'; | ||
import archives_metadata from '../../../common/archives_metadata'; | ||
import { FtrProviderContext } from '../../../common/ftr_provider_context'; | ||
|
||
export default function ApiTest({ getService }: FtrProviderContext) { | ||
const supertest = getService('supertest'); | ||
const esArchiver = getService('esArchiver'); | ||
|
||
const archiveName = 'apm_8.0.0'; | ||
const metadata = archives_metadata[archiveName]; | ||
|
||
describe('Throughput', () => { | ||
describe('when data is not loaded', () => { | ||
it('handles the empty state', async () => { | ||
const response = await supertest.get( | ||
`/api/apm/services/opbeans-java/throughput?${qs.stringify({ | ||
start: metadata.start, | ||
end: metadata.end, | ||
uiFilters: encodeURIComponent('{}'), | ||
transactionType: 'request', | ||
})}` | ||
); | ||
expect(response.status).to.be(200); | ||
expect(response.body.throughput.length).to.be(0); | ||
}); | ||
}); | ||
|
||
describe('when data is loaded', () => { | ||
before(() => esArchiver.load(archiveName)); | ||
after(() => esArchiver.unload(archiveName)); | ||
|
||
describe('returns the service throughput', () => { | ||
let throughputResponse: { | ||
throughput: Array<{ x: number; y: number | null }>; | ||
}; | ||
before(async () => { | ||
const response = await supertest.get( | ||
`/api/apm/services/opbeans-java/throughput?${qs.stringify({ | ||
start: metadata.start, | ||
end: metadata.end, | ||
uiFilters: encodeURIComponent('{}'), | ||
transactionType: 'request', | ||
})}` | ||
); | ||
throughputResponse = response.body; | ||
}); | ||
|
||
it('returns some data', () => { | ||
expect(throughputResponse.throughput.length).to.be.greaterThan(0); | ||
|
||
const nonNullDataPoints = throughputResponse.throughput.filter(({ y }) => y !== null); | ||
|
||
expect(nonNullDataPoints.length).to.be.greaterThan(0); | ||
}); | ||
|
||
it('has the correct start date', () => { | ||
expectSnapshot( | ||
new Date(first(throughputResponse.throughput)?.x ?? NaN).toISOString() | ||
).toMatchInline(`"2020-09-29T14:30:00.000Z"`); | ||
}); | ||
|
||
it('has the correct end date', () => { | ||
expectSnapshot( | ||
new Date(last(throughputResponse.throughput)?.x ?? NaN).toISOString() | ||
).toMatchInline(`"2020-09-29T15:00:00.000Z"`); | ||
}); | ||
|
||
it('has the correct number of buckets', () => { | ||
expectSnapshot(throughputResponse.throughput.length).toMatchInline(`61`); | ||
}); | ||
|
||
it('has the correct throughput', () => { | ||
expectSnapshot(throughputResponse.throughput).toMatch(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} |