diff --git a/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts b/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts new file mode 100644 index 0000000000000..7fcbe9e798188 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts @@ -0,0 +1,16 @@ +/* + * 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 { SetupTimeRange } from './setup_request'; + +export function calculateThroughput({ + start, + end, + value, +}: SetupTimeRange & { value: number }) { + const durationAsMinutes = (end - start) / 1000 / 60; + return value / durationAsMinutes; +} diff --git a/x-pack/plugins/apm/server/lib/observability_overview/get_transaction_coordinates.ts b/x-pack/plugins/apm/server/lib/observability_overview/get_transaction_coordinates.ts index fa4bf6144fb6f..f844a6ce1c345 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/get_transaction_coordinates.ts +++ b/x-pack/plugins/apm/server/lib/observability_overview/get_transaction_coordinates.ts @@ -12,6 +12,7 @@ import { rangeFilter } from '../../../common/utils/range_filter'; import { Coordinates } from '../../../../observability/typings/common'; import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { calculateThroughput } from '../helpers/calculate_throughput'; export async function getTransactionCoordinates({ setup, @@ -51,12 +52,10 @@ export async function getTransactionCoordinates({ }, }); - const deltaAsMinutes = (end - start) / 1000 / 60; - return ( aggregations?.distribution.buckets.map((bucket) => ({ x: bucket.key, - y: bucket.doc_count / deltaAsMinutes, + y: calculateThroughput({ start, end, value: bucket.doc_count }), })) || [] ); } diff --git a/x-pack/plugins/apm/server/lib/services/get_service_dependencies/index.ts b/x-pack/plugins/apm/server/lib/services/get_service_dependencies/index.ts index 0ac881aeac00e..2b209f8f6a80a 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_dependencies/index.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_dependencies/index.ts @@ -13,6 +13,7 @@ import { joinByKey } from '../../../../common/utils/join_by_key'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getMetrics } from './get_metrics'; import { getDestinationMap } from './get_destination_map'; +import { calculateThroughput } from '../../helpers/calculate_throughput'; export type ServiceDependencyItem = { name: string; @@ -51,7 +52,6 @@ export async function getServiceDependencies({ numBuckets: number; }): Promise { const { start, end } = setup; - const [allMetrics, destinationMap] = await Promise.all([ getMetrics({ setup, @@ -134,8 +134,6 @@ export async function getServiceDependencies({ } ); - const deltaAsMinutes = (end - start) / 60 / 1000; - const destMetrics = { latency: { value: @@ -150,11 +148,18 @@ export async function getServiceDependencies({ throughput: { value: mergedMetrics.value.count > 0 - ? mergedMetrics.value.count / deltaAsMinutes + ? calculateThroughput({ + start, + end, + value: mergedMetrics.value.count, + }) : null, timeseries: mergedMetrics.timeseries.map((point) => ({ x: point.x, - y: point.count > 0 ? point.count / deltaAsMinutes : null, + y: + point.count > 0 + ? calculateThroughput({ start, end, value: point.count }) + : null, })), }, errorRate: { diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instance_transaction_stats.ts b/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instance_transaction_stats.ts index c5e5269c4409e..118fbc64146a7 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instance_transaction_stats.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instance_transaction_stats.ts @@ -19,6 +19,7 @@ import { getProcessorEventForAggregatedTransactions, getTransactionDurationFieldForAggregatedTransactions, } from '../../helpers/aggregated_transactions'; +import { calculateThroughput } from '../../helpers/calculate_throughput'; export async function getServiceInstanceTransactionStats({ setup, @@ -104,7 +105,6 @@ export async function getServiceInstanceTransactionStats({ }, }); - const deltaAsMinutes = (end - start) / 60 / 1000; const bucketSizeInMinutes = bucketSize / 60; return ( @@ -128,7 +128,7 @@ export async function getServiceInstanceTransactionStats({ })), }, throughput: { - value: count / deltaAsMinutes, + value: calculateThroughput({ start, end, value: count }), timeseries: timeseries.buckets.map((dateBucket) => ({ x: dateBucket.key, y: dateBucket.doc_count / bucketSizeInMinutes, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts index 400c896e380b4..77642c1f3d65f 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts @@ -25,6 +25,7 @@ import { getLatencyAggregation, getLatencyValue, } from '../../helpers/latency_aggregation_type'; +import { calculateThroughput } from '../../helpers/calculate_throughput'; export type ServiceOverviewTransactionGroupSortField = | 'name' @@ -64,8 +65,6 @@ export async function getTransactionGroupsForPage({ transactionType: string; latencyAggregationType: LatencyAggregationType; }) { - const deltaAsMinutes = (end - start) / 1000 / 60; - const field = getTransactionDurationFieldForAggregatedTransactions( searchAggregatedTransactions ); @@ -121,7 +120,11 @@ export async function getTransactionGroupsForPage({ latencyAggregationType, aggregation: bucket.latency, }), - throughput: bucket.doc_count / deltaAsMinutes, + throughput: calculateThroughput({ + start, + end, + value: bucket.doc_count, + }), errorRate, }; }) ?? []; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts index b0b1cb09dd784..4b8b1aabbbbcc 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts @@ -6,6 +6,7 @@ import { EVENT_OUTCOME } from '../../../../common/elasticsearch_fieldnames'; import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; +import { calculateThroughput } from '../../helpers/calculate_throughput'; import { getLatencyValue } from '../../helpers/latency_aggregation_type'; import { TransactionGroupTimeseriesData } from './get_timeseries_data_for_transaction_groups'; import { TransactionGroupWithoutTimeseriesData } from './get_transaction_groups_for_page'; @@ -25,8 +26,6 @@ export function mergeTransactionGroupData({ latencyAggregationType: LatencyAggregationType; transactionType: string; }) { - const deltaAsMinutes = (end - start) / 1000 / 60; - return transactionGroups.map((transactionGroup) => { const groupBucket = timeseriesData.find( ({ key }) => key === transactionGroup.name @@ -52,7 +51,11 @@ export function mergeTransactionGroupData({ ...acc.throughput, timeseries: acc.throughput.timeseries.concat({ x: point.key, - y: point.doc_count / deltaAsMinutes, + y: calculateThroughput({ + start, + end, + value: point.doc_count, + }), }), }, errorRate: { diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts b/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts index efbc30169d178..d7cd13317fd73 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts @@ -22,6 +22,7 @@ import { getTransactionDurationFieldForAggregatedTransactions, } from '../../helpers/aggregated_transactions'; import { getBucketSize } from '../../helpers/get_bucket_size'; +import { calculateThroughput } from '../../helpers/calculate_throughput'; import { calculateTransactionErrorPercentage, getOutcomeAggregation, @@ -35,16 +36,6 @@ interface AggregationParams { const MAX_NUMBER_OF_SERVICES = 500; -function calculateAvgDuration({ - value, - deltaAsMinutes, -}: { - value: number; - deltaAsMinutes: number; -}) { - return value / deltaAsMinutes; -} - export async function getServiceTransactionStats({ setup, searchAggregatedTransactions, @@ -131,8 +122,6 @@ export async function getServiceTransactionStats({ }, }); - const deltaAsMinutes = (setup.end - setup.start) / 1000 / 60; - return ( response.aggregations?.services.buckets.map((bucket) => { const topTransactionTypeBucket = @@ -171,16 +160,18 @@ export async function getServiceTransactionStats({ ), }, transactionsPerMinute: { - value: calculateAvgDuration({ + value: calculateThroughput({ + start, + end, value: topTransactionTypeBucket.doc_count, - deltaAsMinutes, }), timeseries: topTransactionTypeBucket.timeseries.buckets.map( (dateBucket) => ({ x: dateBucket.key, - y: calculateAvgDuration({ + y: calculateThroughput({ + start, + end, value: dateBucket.doc_count, - deltaAsMinutes, }), }) ), diff --git a/x-pack/plugins/apm/server/lib/services/get_throughput.ts b/x-pack/plugins/apm/server/lib/services/get_throughput.ts index bde826a568da9..15ecc88a019db 100644 --- a/x-pack/plugins/apm/server/lib/services/get_throughput.ts +++ b/x-pack/plugins/apm/server/lib/services/get_throughput.ts @@ -16,6 +16,7 @@ import { getProcessorEventForAggregatedTransactions, } from '../helpers/aggregated_transactions'; import { getBucketSize } from '../helpers/get_bucket_size'; +import { calculateThroughput } from '../helpers/calculate_throughput'; import { Setup, SetupTimeRange } from '../helpers/setup_request'; interface Options { @@ -27,16 +28,15 @@ interface Options { type ESResponse = PromiseReturnType; -function transform(response: ESResponse, options: Options) { - const { end, start } = options.setup; - const deltaAsMinutes = (end - start) / 1000 / 60; +function transform(options: Options, response: ESResponse) { if (response.hits.total.value === 0) { return []; } + const { start, end } = options.setup; const buckets = response.aggregations?.throughput.buckets ?? []; - return buckets.map(({ key: x, doc_count: y }) => ({ + return buckets.map(({ key: x, doc_count: value }) => ({ x, - y: y / deltaAsMinutes, + y: calculateThroughput({ start, end, value }), })); } @@ -87,6 +87,6 @@ async function fetcher({ export async function getThroughput(options: Options) { return { - throughput: transform(await fetcher(options), options), + throughput: transform(options, await fetcher(options)), }; } diff --git a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts index 8dfb0a9f65878..dda6573ea93ef 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts @@ -100,9 +100,7 @@ export async function getThroughputCharts({ setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { - const { start, end } = setup; - const { bucketSize, intervalString } = getBucketSize({ start, end }); - const durationAsMinutes = (end - start) / 1000 / 60; + const { bucketSize, intervalString } = getBucketSize(setup); const response = await searchThroughput({ serviceName, @@ -117,7 +115,7 @@ export async function getThroughputCharts({ throughputTimeseries: getThroughputBuckets({ throughputResultBuckets: response.aggregations?.throughput.buckets, bucketSize, - durationAsMinutes, + setupTimeRange: setup, }), }; } diff --git a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts index 7e43a0d76f70a..35d1b0e901dee 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts @@ -7,18 +7,21 @@ import { sortBy } from 'lodash'; import { NOT_AVAILABLE_LABEL } from '../../../../common/i18n'; import { ThroughputChartsResponse } from '.'; +import { calculateThroughput } from '../../helpers/calculate_throughput'; +import { SetupTimeRange } from '../../helpers/setup_request'; type ThroughputResultBuckets = Required['aggregations']['throughput']['buckets']; export function getThroughputBuckets({ throughputResultBuckets = [], bucketSize, - durationAsMinutes, + setupTimeRange, }: { throughputResultBuckets?: ThroughputResultBuckets; bucketSize: number; - durationAsMinutes: number; + setupTimeRange: SetupTimeRange; }) { + const { start, end } = setupTimeRange; const buckets = throughputResultBuckets.map( ({ key: resultKey, timeseries }) => { const dataPoints = timeseries.buckets.map((bucket) => { @@ -38,7 +41,7 @@ export function getThroughputBuckets({ .reduce((a, b) => a + b, 0); // calculate average throughput - const avg = docCountTotal / durationAsMinutes; + const avg = calculateThroughput({ start, end, value: docCountTotal }); return { key, dataPoints, avg }; }