From b877cef7a2774904abc852a10f91fb045d318a6f Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Wed, 29 May 2019 10:32:28 +0200 Subject: [PATCH 1/6] [APM]: Inferred types for aggregations Previously, aggregations returned by the ESClient were 'any' by default, and the return type had to be explicitly defined by the consumer to get any type safety. This leads to both type duplication and errors because of wrong assumptions. This change infers the aggregation return type from the parameters passed to ESClient.search. --- .../apm/public/hooks/useTransactionList.ts | 10 +- .../lib/errors/distribution/get_buckets.ts | 9 +- .../apm/server/lib/errors/get_error_groups.ts | 61 ++++----- .../get_trace_errors_per_transaction.ts | 18 +-- .../by_agent/java/heap_memory/fetcher.ts | 9 +- .../by_agent/java/heap_memory/index.ts | 15 ++- .../by_agent/java/non_heap_memory/fetcher.ts | 8 +- .../by_agent/java/non_heap_memory/index.ts | 13 +- .../by_agent/java/thread_count/fetcher.ts | 7 +- .../by_agent/java/thread_count/index.ts | 12 +- .../metrics/by_agent/shared/cpu/fetcher.ts | 10 +- .../lib/metrics/by_agent/shared/cpu/index.ts | 12 +- .../metrics/by_agent/shared/memory/fetcher.ts | 8 +- .../metrics/by_agent/shared/memory/index.ts | 13 +- .../metrics/transform_metrics_chart.test.ts | 34 +++-- .../lib/metrics/transform_metrics_chart.ts | 57 ++++++--- .../plugins/apm/server/lib/metrics/types.ts | 52 ++++---- .../apm/server/lib/services/get_service.ts | 16 +-- .../get_services/get_services_items.ts | 26 +--- .../server/lib/transaction_groups/fetcher.ts | 29 +---- .../lib/transaction_groups/transform.ts | 13 +- .../charts/get_anomaly_data/fetcher.ts | 28 +--- .../charts/get_anomaly_data/index.ts | 14 +- .../mock-responses/mlAnomalyResponse.ts | 4 +- .../charts/get_anomaly_data/transform.test.ts | 24 ++-- .../charts/get_anomaly_data/transform.ts | 10 +- .../charts/get_timeseries_data/fetcher.ts | 55 +------- .../mock-responses/timeseries_response.ts | 4 +- .../get_timeseries_data/transform.test.ts | 2 +- .../charts/get_timeseries_data/transform.ts | 16 +-- .../distribution/calculate_bucket_size.ts | 12 +- .../distribution/get_buckets/fetcher.ts | 23 +--- .../distribution/get_buckets/transform.ts | 15 ++- .../server/lib/ui_filters/get_environments.ts | 10 +- x-pack/plugins/apm/typings/common.ts | 6 + x-pack/plugins/apm/typings/elasticsearch.ts | 120 ++++++++++++++++-- 36 files changed, 348 insertions(+), 427 deletions(-) diff --git a/x-pack/plugins/apm/public/hooks/useTransactionList.ts b/x-pack/plugins/apm/public/hooks/useTransactionList.ts index f100e3de4fdbf..423d4c69953f2 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionList.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionList.ts @@ -22,14 +22,20 @@ const getRelativeImpact = ( ); function getWithRelativeImpact(items: TransactionListAPIResponse) { - const impacts = items.map(({ impact }) => impact); + const impacts = items + .map(({ impact }) => impact) + .filter(impact => impact !== null) as number[]; + const impactMin = Math.min(...impacts); const impactMax = Math.max(...impacts); return items.map(item => { return { ...item, - impactRelative: getRelativeImpact(item.impact, impactMin, impactMax) + impactRelative: + item.impact !== null + ? getRelativeImpact(item.impact, impactMin, impactMax) + : null }; }); } diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts index 14849371c4ceb..5e18e27ac670d 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { BucketAgg, ESFilter } from 'elasticsearch'; +import { ESFilter } from 'elasticsearch'; import { ERROR_GROUP_ID, PROCESSOR_EVENT, @@ -61,13 +61,8 @@ export async function getBuckets({ } }; - interface Aggs { - distribution: { - buckets: Array>; - }; - } + const resp = await client.search(params); - const resp = await client.search(params); const buckets = resp.aggregations.distribution.buckets.map(bucket => ({ key: bucket.key, count: bucket.doc_count diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts index a76578f7d07c6..5f16f9979fa63 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; import { idx } from '@kbn/elastic-idx'; import { ERROR_CULPRIT, @@ -37,7 +36,10 @@ export async function getErrorGroups({ }) { const { start, end, uiFiltersES, client, config } = setup; - const params: SearchParams = { + // sort buckets by last occurrence of error + const sortByLatestOccurrence = sortField === 'latestOccurrenceAt'; + + const params = { index: config.get('apm_oss.errorIndices'), body: { size: 0, @@ -56,7 +58,11 @@ export async function getErrorGroups({ terms: { field: ERROR_GROUP_ID, size: 500, - order: { _count: sortDirection } + order: sortByLatestOccurrence + ? { + max_timestamp: sortDirection + } + : { _count: sortDirection } }, aggs: { sample: { @@ -72,24 +78,22 @@ export async function getErrorGroups({ sort: [{ '@timestamp': 'desc' }], size: 1 } - } + }, + ...(sortByLatestOccurrence + ? { + max_timestamp: { + max: { + field: '@timestamp' + } + } + } + : {}) } } } } }; - // sort buckets by last occurrence of error - if (sortField === 'latestOccurrenceAt') { - params.body.aggs.error_groups.terms.order = { - max_timestamp: sortDirection - }; - - params.body.aggs.error_groups.aggs.max_timestamp = { - max: { field: '@timestamp' } - }; - } - interface SampleError { '@timestamp': APMError['@timestamp']; error: { @@ -105,31 +109,10 @@ export async function getErrorGroups({ }; } - interface Bucket { - key: string; - doc_count: number; - sample: { - hits: { - total: number; - max_score: number | null; - hits: Array<{ - _source: SampleError; - }>; - }; - }; - } - - interface Aggs { - error_groups: { - buckets: Bucket[]; - }; - } - - const resp = await client.search(params); - const buckets = idx(resp, _ => _.aggregations.error_groups.buckets) || []; + const resp = await client.search(params); - const hits = buckets.map(bucket => { - const source = bucket.sample.hits.hits[0]._source; + const hits = resp.aggregations.error_groups.buckets.map(bucket => { + const source = bucket.sample.hits.hits[0]._source as SampleError; const message = idx(source, _ => _.error.log.message) || idx(source, _ => _.error.exception[0].message); diff --git a/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts b/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts index a40477deaea43..9d5be70df7205 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; import { PROCESSOR_EVENT, TRACE_ID, @@ -17,25 +16,14 @@ export interface ErrorsPerTransaction { [transactionId: string]: number; } -interface TraceErrorsAggBucket { - key: string; - doc_count: number; -} - -interface TraceErrorsAggResponse { - transactions: { - buckets: TraceErrorsAggBucket[]; - }; -} - export async function getTraceErrorsPerTransaction( traceId: string, setup: Setup ): Promise { const { start, end, client, config } = setup; - const params: SearchParams = { - index: [config.get('apm_oss.errorIndices')], + const params = { + index: config.get('apm_oss.errorIndices'), body: { size: 0, query: { @@ -57,7 +45,7 @@ export async function getTraceErrorsPerTransaction( } }; - const resp = await client.search(params); + const resp = await client.search(params); return resp.aggregations.transactions.buckets.reduce( (acc, bucket) => ({ diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts index dd2826e4ea9c5..49f6607f6cc34 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts @@ -12,16 +12,9 @@ import { METRIC_JAVA_HEAP_MEMORY_USED } from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { MetricsAggs, MetricSeriesKeys, AggValue } from '../../../types'; import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; import { rangeFilter } from '../../../../helpers/range_filter'; -export interface HeapMemoryMetrics extends MetricSeriesKeys { - heapMemoryMax: AggValue; - heapMemoryCommitted: AggValue; - heapMemoryUsed: AggValue; -} - export async function fetch(setup: Setup, serviceName: string) { const { start, end, uiFiltersES, client, config } = setup; @@ -60,5 +53,5 @@ export async function fetch(setup: Setup, serviceName: string) { } }; - return client.search>(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts index 50c3d05f76105..599043a8efb7c 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts @@ -7,13 +7,11 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch, HeapMemoryMetrics } from './fetcher'; -import { ChartBase } from '../../../types'; +import { fetch } from './fetcher'; import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; +import { ChartBase, MetricSearchResponse } from '../../../types'; -// TODO: i18n for titles - -const chartBase: ChartBase = { +const chartBase = { title: i18n.translate('xpack.apm.agentMetrics.java.heapMemoryChartTitle', { defaultMessage: 'Heap Memory' }), @@ -49,6 +47,9 @@ const chartBase: ChartBase = { }; export async function getHeapMemoryChart(setup: Setup, serviceName: string) { - const result = await fetch(setup, serviceName); - return transformDataToMetricsChart(result, chartBase); + const result = (await fetch(setup, serviceName)) as MetricSearchResponse< + keyof typeof chartBase.series + >; + + return transformDataToMetricsChart(result, chartBase as ChartBase); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts index 84ee3a3864734..48293de27c346 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts @@ -12,15 +12,9 @@ import { METRIC_JAVA_NON_HEAP_MEMORY_USED } from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { MetricsAggs, MetricSeriesKeys, AggValue } from '../../../types'; import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; import { rangeFilter } from '../../../../helpers/range_filter'; -export interface NonHeapMemoryMetrics extends MetricSeriesKeys { - nonHeapMemoryCommitted: AggValue; - nonHeapMemoryUsed: AggValue; -} - export async function fetch(setup: Setup, serviceName: string) { const { start, end, uiFiltersES, client, config } = setup; @@ -61,5 +55,5 @@ export async function fetch(setup: Setup, serviceName: string) { } }; - return client.search>(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts index 2490449c3cc7c..eb6e7d652faa4 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts @@ -7,11 +7,11 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch, NonHeapMemoryMetrics } from './fetcher'; -import { ChartBase } from '../../../types'; +import { fetch } from './fetcher'; import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; +import { MetricSearchResponse, ChartBase } from '../../../types'; -const chartBase: ChartBase = { +const chartBase = { title: i18n.translate('xpack.apm.agentMetrics.java.nonHeapMemoryChartTitle', { defaultMessage: 'Non-Heap Memory' }), @@ -41,6 +41,9 @@ const chartBase: ChartBase = { }; export async function getNonHeapMemoryChart(setup: Setup, serviceName: string) { - const result = await fetch(setup, serviceName); - return transformDataToMetricsChart(result, chartBase); + const result = (await fetch(setup, serviceName)) as MetricSearchResponse< + keyof typeof chartBase.series + >; + + return transformDataToMetricsChart(result, chartBase as ChartBase); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts index a74208cc8218c..516badecb346d 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts @@ -10,14 +10,9 @@ import { METRIC_JAVA_THREAD_COUNT } from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { MetricsAggs, MetricSeriesKeys, AggValue } from '../../../types'; import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; import { rangeFilter } from '../../../../helpers/range_filter'; -export interface ThreadCountMetrics extends MetricSeriesKeys { - threadCount: AggValue; -} - export async function fetch(setup: Setup, serviceName: string) { const { start, end, uiFiltersES, client, config } = setup; @@ -51,5 +46,5 @@ export async function fetch(setup: Setup, serviceName: string) { } }; - return client.search>(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts index db6158ff99487..6296018d324b9 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts @@ -7,11 +7,11 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch, ThreadCountMetrics } from './fetcher'; -import { ChartBase } from '../../../types'; +import { fetch } from './fetcher'; +import { ChartBase, MetricSearchResponse } from '../../../types'; import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; -const chartBase: ChartBase = { +const chartBase = { title: i18n.translate('xpack.apm.agentMetrics.java.threadCountChartTitle', { defaultMessage: 'Thread Count' }), @@ -35,6 +35,8 @@ const chartBase: ChartBase = { }; export async function getThreadCountChart(setup: Setup, serviceName: string) { - const result = await fetch(setup, serviceName); - return transformDataToMetricsChart(result, chartBase); + const result = (await fetch(setup, serviceName)) as MetricSearchResponse< + keyof typeof chartBase.series + >; + return transformDataToMetricsChart(result, chartBase as ChartBase); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts index 0da5859666a51..813e1b05d3a35 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts @@ -11,17 +11,9 @@ import { SERVICE_NAME } from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { MetricsAggs, MetricSeriesKeys, AggValue } from '../../../types'; import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; import { rangeFilter } from '../../../../helpers/range_filter'; -export interface CPUMetrics extends MetricSeriesKeys { - systemCPUAverage: AggValue; - systemCPUMax: AggValue; - processCPUAverage: AggValue; - processCPUMax: AggValue; -} - export async function fetch(setup: Setup, serviceName: string) { const { start, end, uiFiltersES, client, config } = setup; @@ -58,5 +50,5 @@ export async function fetch(setup: Setup, serviceName: string) { } }; - return client.search>(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts index f7fe92d578e93..1f5671dd4fb5c 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts @@ -7,11 +7,11 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch, CPUMetrics } from './fetcher'; -import { ChartBase } from '../../../types'; +import { fetch } from './fetcher'; import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; +import { MetricSearchResponse, ChartBase } from '../../../types'; -const chartBase: ChartBase = { +const chartBase = { title: i18n.translate('xpack.apm.serviceDetails.metrics.cpuUsageChartTitle', { defaultMessage: 'CPU usage' }), @@ -47,6 +47,8 @@ const chartBase: ChartBase = { }; export async function getCPUChartData(setup: Setup, serviceName: string) { - const result = await fetch(setup, serviceName); - return transformDataToMetricsChart(result, chartBase); + const result = (await fetch(setup, serviceName)) as MetricSearchResponse< + keyof typeof chartBase.series + >; + return transformDataToMetricsChart(result, chartBase as ChartBase); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts index 96b3160600111..8737b6fdad714 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts @@ -11,15 +11,9 @@ import { METRIC_SYSTEM_TOTAL_MEMORY } from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { MetricsAggs, MetricSeriesKeys, AggValue } from '../../../types'; import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; import { rangeFilter } from '../../../../helpers/range_filter'; -export interface MemoryMetrics extends MetricSeriesKeys { - memoryUsedAvg: AggValue; - memoryUsedMax: AggValue; -} - const percentUsedScript = { lang: 'expression', source: `1 - doc['${METRIC_SYSTEM_FREE_MEMORY}'] / doc['${METRIC_SYSTEM_TOTAL_MEMORY}']` @@ -69,5 +63,5 @@ export async function fetch(setup: Setup, serviceName: string) { } }; - return client.search>(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts index fe9637ab34e69..27607fb2171ee 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts @@ -6,11 +6,11 @@ import { i18n } from '@kbn/i18n'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch, MemoryMetrics } from './fetcher'; -import { ChartBase } from '../../../types'; +import { fetch } from './fetcher'; +import { ChartBase, MetricSearchResponse } from '../../../types'; import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; -const chartBase: ChartBase = { +const chartBase = { title: i18n.translate( 'xpack.apm.serviceDetails.metrics.memoryUsageChartTitle', { @@ -35,6 +35,9 @@ const chartBase: ChartBase = { }; export async function getMemoryChartData(setup: Setup, serviceName: string) { - const result = await fetch(setup, serviceName); - return transformDataToMetricsChart(result, chartBase); + const result = (await fetch(setup, serviceName)) as MetricSearchResponse< + keyof typeof chartBase.series + >; + + return transformDataToMetricsChart(result, chartBase as ChartBase); } diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts index e6fff34b37bc4..8ca7f525fe8b8 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts @@ -3,22 +3,15 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { AggregationSearchResponse } from 'elasticsearch'; -import { MetricsAggs, MetricSeriesKeys, AggValue } from './types'; import { transformDataToMetricsChart } from './transform_metrics_chart'; import { ChartType, YUnit } from '../../../typings/timeseries'; +import { MetricSearchResponse } from './types'; test('transformDataToMetricsChart should transform an ES result into a chart object', () => { - interface TestKeys extends MetricSeriesKeys { - a: AggValue; - b: AggValue; - c: AggValue; - } + type R = MetricSearchResponse<'a' | 'b' | 'c'>; - type R = AggregationSearchResponse>; - - const response = { - hits: { total: 5000 } as R['hits'], + const response = ({ + hits: { total: 5000 }, aggregations: { a: { value: 1000 }, b: { value: 1000 }, @@ -29,24 +22,27 @@ test('transformDataToMetricsChart should transform an ES result into a chart obj a: { value: 10 }, b: { value: 10 }, c: { value: 10 }, - key: 1 - } as R['aggregations']['timeseriesData']['buckets'][0], + key: 1, + doc_count: 0 + }, { a: { value: 20 }, b: { value: 20 }, c: { value: 20 }, - key: 2 - } as R['aggregations']['timeseriesData']['buckets'][0], + key: 2, + doc_count: 0 + }, { a: { value: 30 }, b: { value: 30 }, c: { value: 30 }, - key: 3 - } as R['aggregations']['timeseriesData']['buckets'][0] + key: 3, + doc_count: 0 + } ] } - } as R['aggregations'] - } as R; + } + } as unknown) as R; const chartBase = { title: 'Test Chart Title', diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index 9936b6883a1c7..22ed499195e9b 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -3,9 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { AggregationSearchResponse } from 'elasticsearch'; import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { ChartBase, MetricsAggs, MetricSeriesKeys } from './types'; +import { ChartBase, MetricSearchResponse } from './types'; const colors = [ theme.euiColorVis0, @@ -20,9 +19,19 @@ const colors = [ export type GenericMetricsChart = ReturnType< typeof transformDataToMetricsChart >; -export function transformDataToMetricsChart( - result: AggregationSearchResponse>, - chartBase: ChartBase + +type TimeseriesBucket = { + key: number; + doc_count: number; +} & { + [key: string]: { + value: number; + }; +}; + +export function transformDataToMetricsChart( + result: MetricSearchResponse, + chartBase: ChartBase ) { const { aggregations, hits } = result; const { timeseriesData } = aggregations; @@ -32,20 +41,28 @@ export function transformDataToMetricsChart( key: chartBase.key, yUnit: chartBase.yUnit, totalHits: hits.total, - series: Object.keys(chartBase.series).map((seriesKey, i) => ({ - title: chartBase.series[seriesKey].title, - key: seriesKey, - type: chartBase.type, - color: chartBase.series[seriesKey].color || colors[i], - overallValue: aggregations[seriesKey].value, - data: timeseriesData.buckets.map(bucket => { - const { value } = bucket[seriesKey]; - const y = value === null || isNaN(value) ? null : value; - return { - x: bucket.key, - y - }; - }) - })) + series: Object.keys(chartBase.series).map((seriesKey, i) => { + const agg = aggregations[seriesKey]; + + if (!(agg && 'value' in agg)) { + throw new Error('No value found for metric aggregation'); + } + + return { + title: chartBase.series[seriesKey].title, + key: seriesKey, + type: chartBase.type, + color: chartBase.series[seriesKey].color || colors[i], + overallValue: agg.value, + data: (timeseriesData.buckets as TimeseriesBucket[]).map(bucket => { + const { value } = bucket[seriesKey]; + const y = value === null || isNaN(value) ? null : value; + return { + x: bucket.key, + y + }; + }) + }; + }) }; } diff --git a/x-pack/plugins/apm/server/lib/metrics/types.ts b/x-pack/plugins/apm/server/lib/metrics/types.ts index f234b44733444..453e9cab5aaea 100644 --- a/x-pack/plugins/apm/server/lib/metrics/types.ts +++ b/x-pack/plugins/apm/server/lib/metrics/types.ts @@ -4,37 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ +import { + PromiseReturnType, + IndexAsString, + Omit +} from '../../../typings/common'; import { ChartType, YUnit } from '../../../typings/timeseries'; +import { fetch as cpuFetch } from './by_agent/shared/cpu/fetcher'; -export interface AggValue { - value: number | null; -} +type CpuSearchResponse = PromiseReturnType; -export interface MetricSeriesKeys { - [key: string]: AggValue; -} +export type MetricSearchResponse = Omit< + CpuSearchResponse, + 'aggregations' +> & { + aggregations: IndexAsString< + { [key in MetricNames]: { value: number } } & { + timeseriesData: { + buckets: Array< + { + key: number; + doc_count: number; + } & { [key in MetricNames]: { value: number } } + >; + }; + } + >; +}; -export interface ChartBase { +export interface ChartBase { title: string; key: string; type: ChartType; yUnit: YUnit; - series: { - [key in keyof T]: { + series: IndexAsString<{ + [key: string]: { title: string; color?: string; - } - }; + }; + }>; } - -export type MetricsAggs = { - timeseriesData: { - buckets: Array< - { - key_as_string: string; // timestamp as string - key: number; // timestamp as epoch milliseconds - doc_count: number; - } & T - >; - }; -} & T; diff --git a/x-pack/plugins/apm/server/lib/services/get_service.ts b/x-pack/plugins/apm/server/lib/services/get_service.ts index 7cbb1825ef7eb..42264b70e2ecb 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service.ts @@ -3,8 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { BucketAgg } from 'elasticsearch'; import { idx } from '@kbn/elastic-idx'; import { PROCESSOR_EVENT, @@ -48,19 +46,11 @@ export async function getService(serviceName: string, setup: Setup) { } }; - interface Aggs { - types: { - buckets: BucketAgg[]; - }; - agents: { - buckets: BucketAgg[]; - }; - } - - const { aggregations } = await client.search(params); + const { aggregations } = await client.search(params); const buckets = idx(aggregations, _ => _.types.buckets) || []; const types = buckets.map(bucket => bucket.key); - const agentName = idx(aggregations, _ => _.agents.buckets[0].key); + const agentName = idx(aggregations, _ => _.agents.buckets[0].key) || ''; + return { serviceName, types, diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts index 35747a88bb806..a9affcce1c515 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { BucketAgg } from 'elasticsearch'; import { idx } from '@kbn/elastic-idx'; import { PROCESSOR_EVENT, @@ -65,33 +64,14 @@ export async function getServicesItems(setup: Setup) { } }; - interface ServiceBucket extends BucketAgg { - avg: { - value: number; - }; - agents: { - buckets: BucketAgg[]; - }; - events: { - buckets: BucketAgg[]; - }; - environments: { - buckets: BucketAgg[]; - }; - } - - interface Aggs extends BucketAgg { - services: { - buckets: ServiceBucket[]; - }; - } - - const resp = await client.search(params); + const resp = await client.search<{}, typeof params>(params); const aggs = resp.aggregations; + const serviceBuckets = idx(aggs, _ => _.services.buckets) || []; const items = serviceBuckets.map(bucket => { const eventTypes = bucket.events.buckets; + const transactions = eventTypes.find(e => e.key === 'transaction'); const totalTransactions = idx(transactions, _ => _.doc_count) || 0; diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index 13c3c3bfb2539..ea66fa0ff399e 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -4,42 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; import { TRANSACTION_DURATION, TRANSACTION_NAME } from '../../../common/elasticsearch_fieldnames'; import { PromiseReturnType, StringMap } from '../../../typings/common'; -import { Transaction } from '../../../typings/es_schemas/ui/Transaction'; import { Setup } from '../helpers/setup_request'; -interface Bucket { - key: string; - doc_count: number; - avg: { value: number }; - p95: { values: { '95.0': number } }; - sum: { value: number }; - sample: { - hits: { - total: number; - max_score: number | null; - hits: Array<{ - _source: Transaction; - }>; - }; - }; -} - -interface Aggs { - transactions: { - buckets: Bucket[]; - }; -} - export type ESResponse = PromiseReturnType; export function transactionGroupsFetcher(setup: Setup, bodyQuery: StringMap) { const { client, config } = setup; - const params: SearchParams = { + const params = { index: config.get('apm_oss.transactionIndices'), body: { size: 0, @@ -72,5 +47,5 @@ export function transactionGroupsFetcher(setup: Setup, bodyQuery: StringMap) { } }; - return client.search(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/transform.ts b/x-pack/plugins/apm/server/lib/transaction_groups/transform.ts index dbef10672c988..62d212d07d2a7 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/transform.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/transform.ts @@ -6,16 +6,23 @@ import moment from 'moment'; import { idx } from '@kbn/elastic-idx'; +import { Transaction } from '../../../typings/es_schemas/ui/Transaction'; import { ESResponse } from './fetcher'; function calculateRelativeImpacts(transactionGroups: ITransactionGroup[]) { - const values = transactionGroups.map(({ impact }) => impact); + const values = transactionGroups + .map(({ impact }) => impact) + .filter(value => value !== null) as number[]; + const max = Math.max(...values); const min = Math.min(...values); return transactionGroups.map(bucket => ({ ...bucket, - impact: ((bucket.impact - min) / (max - min)) * 100 || 0 + impact: + bucket.impact !== null + ? ((bucket.impact - min) / (max - min)) * 100 || 0 + : 0 })); } @@ -27,7 +34,7 @@ function getTransactionGroup( const averageResponseTime = bucket.avg.value; const transactionsPerMinute = bucket.doc_count / minutes; const impact = bucket.sum.value; - const sample = bucket.sample.hits.hits[0]._source; + const sample = bucket.sample.hits.hits[0]._source as Transaction; return { name: bucket.key, diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts index 6fcf50b148318..8e859b39b8c46 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts @@ -8,28 +8,11 @@ import { getMlIndex } from '../../../../../common/ml_job_constants'; import { PromiseReturnType } from '../../../../../typings/common'; import { Setup } from '../../../helpers/setup_request'; -export interface ESBucket { - key_as_string: string; // timestamp as string - key: number; // timestamp - doc_count: number; - anomaly_score: { - value: number | null; - }; - lower: { - value: number | null; - }; - upper: { - value: number | null; - }; -} - -interface Aggs { - ml_avg_response_times: { - buckets: ESBucket[]; - }; -} +export type ESResponse = Exclude< + PromiseReturnType, + undefined +>; -export type ESResponse = PromiseReturnType; export async function anomalySeriesFetcher({ serviceName, transactionType, @@ -91,7 +74,8 @@ export async function anomalySeriesFetcher({ }; try { - return await client.search(params); + const response = await client.search(params); + return response; } catch (err) { const isHttpError = 'statusCode' in err; if (isHttpError) { diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts index f3227140c692b..7b5b77e2a2ddc 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts @@ -55,10 +55,12 @@ export async function getAnomalySeries({ setup }); - return anomalySeriesTransform( - esResponse, - mlBucketSize, - bucketSize, - timeSeriesDates - ); + return esResponse + ? anomalySeriesTransform( + esResponse, + mlBucketSize, + bucketSize, + timeSeriesDates + ) + : undefined; } diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/mock-responses/mlAnomalyResponse.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/mock-responses/mlAnomalyResponse.ts index eaea107e5ef2d..c04cf95526d4b 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/mock-responses/mlAnomalyResponse.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/mock-responses/mlAnomalyResponse.ts @@ -6,7 +6,7 @@ import { ESResponse } from '../fetcher'; -export const mlAnomalyResponse: ESResponse = { +export const mlAnomalyResponse: ESResponse = ({ took: 3, timed_out: false, _shards: { @@ -124,4 +124,4 @@ export const mlAnomalyResponse: ESResponse = { ] } } -}; +} as unknown) as ESResponse; diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.test.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.test.ts index bbcab297f3a93..eab68a2bda974 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.test.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.test.ts @@ -5,7 +5,7 @@ */ import { idx } from '@kbn/elastic-idx'; -import { ESBucket, ESResponse } from './fetcher'; +import { ESResponse } from './fetcher'; import { mlAnomalyResponse } from './mock-responses/mlAnomalyResponse'; import { anomalySeriesTransform, replaceFirstAndLastBucket } from './transform'; @@ -46,7 +46,7 @@ describe('anomalySeriesTransform', () => { key: 20000, anomaly_score: { value: 90 } } - ] as ESBucket[]); + ]); const getMlBucketSize = 5; const bucketSize = 5; @@ -72,7 +72,7 @@ describe('anomalySeriesTransform', () => { key: 5000, anomaly_score: { value: 90 } } - ] as ESBucket[]); + ]); const getMlBucketSize = 10; const bucketSize = 5; @@ -112,7 +112,7 @@ describe('anomalySeriesTransform', () => { upper: { value: 45 }, lower: { value: 40 } } - ] as ESBucket[]); + ]); const mlBucketSize = 10; const bucketSize = 5; @@ -151,7 +151,7 @@ describe('anomalySeriesTransform', () => { upper: { value: 25 }, lower: { value: 20 } } - ] as ESBucket[]); + ]); const getMlBucketSize = 10; const bucketSize = 5; @@ -190,7 +190,7 @@ describe('anomalySeriesTransform', () => { upper: { value: null }, lower: { value: null } } - ] as ESBucket[]); + ]); const getMlBucketSize = 10; const bucketSize = 5; @@ -234,10 +234,10 @@ describe('replaceFirstAndLastBucket', () => { lower: 30, upper: 40 } - ] as any; + ]; const timeSeriesDates = [10, 15]; - expect(replaceFirstAndLastBucket(buckets, timeSeriesDates)).toEqual([ + expect(replaceFirstAndLastBucket(buckets as any, timeSeriesDates)).toEqual([ { x: 10, lower: 10, upper: 20 }, { x: 15, lower: 30, upper: 40 } ]); @@ -271,8 +271,8 @@ describe('replaceFirstAndLastBucket', () => { }); }); -function getESResponse(buckets: ESBucket[]): ESResponse { - return { +function getESResponse(buckets: any): ESResponse { + return ({ took: 3, timed_out: false, _shards: { @@ -288,7 +288,7 @@ function getESResponse(buckets: ESBucket[]): ESResponse { }, aggregations: { ml_avg_response_times: { - buckets: buckets.map(bucket => { + buckets: buckets.map((bucket: any) => { return { ...bucket, lower: { value: idx(bucket, _ => _.lower.value) || null }, @@ -300,5 +300,5 @@ function getESResponse(buckets: ESBucket[]): ESResponse { }) } } - }; + } as unknown) as ESResponse; } diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.ts index 211918fc2417d..27cb122addfb1 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/transform.ts @@ -7,10 +7,12 @@ import { first, last } from 'lodash'; import { idx } from '@kbn/elastic-idx'; import { Coordinate, RectCoordinate } from '../../../../../typings/timeseries'; -import { ESBucket, ESResponse } from './fetcher'; +import { ESResponse } from './fetcher'; type IBucket = ReturnType; -function getBucket(bucket: ESBucket) { +function getBucket( + bucket: ESResponse['aggregations']['ml_avg_response_times']['buckets'][0] +) { return { x: bucket.key, anomalyScore: bucket.anomaly_score.value, @@ -28,10 +30,6 @@ export function anomalySeriesTransform( bucketSize: number, timeSeriesDates: number[] ) { - if (!response) { - return; - } - const buckets = ( idx(response, _ => _.aggregations.ml_avg_response_times.buckets) || [] ).map(getBucket); diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts index ceb19b865177d..626fe57e46cf5 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESFilter, SearchParams } from 'elasticsearch'; +import { ESFilter } from 'elasticsearch'; import { PROCESSOR_EVENT, SERVICE_NAME, @@ -18,53 +18,6 @@ import { getBucketSize } from '../../../helpers/get_bucket_size'; import { rangeFilter } from '../../../helpers/range_filter'; import { Setup } from '../../../helpers/setup_request'; -interface ResponseTimeBucket { - key_as_string: string; - key: number; - doc_count: number; - avg: { - value: number | null; - }; - pct: { - values: { - '95.0': number | 'NaN'; - '99.0': number | 'NaN'; - }; - }; -} - -interface TransactionResultBucket { - /** - * transaction result eg. 2xx - */ - key: string; - doc_count: number; - timeseries: { - buckets: Array<{ - key_as_string: string; - /** - * timestamp in ms - */ - key: number; - doc_count: number; - }>; - }; -} - -interface Aggs { - response_times: { - buckets: ResponseTimeBucket[]; - }; - transaction_results: { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: TransactionResultBucket[]; - }; - overall_avg_duration: { - value: number; - }; -} - export type ESResponse = PromiseReturnType; export function timeseriesFetcher({ serviceName, @@ -96,8 +49,8 @@ export function timeseriesFetcher({ filter.push({ term: { [TRANSACTION_TYPE]: transactionType } }); } - const params: SearchParams = { - index: config.get('apm_oss.transactionIndices'), + const params = { + index: config.get('apm_oss.transactionIndices'), body: { size: 0, query: { bool: { filter } }, @@ -134,5 +87,5 @@ export function timeseriesFetcher({ } }; - return client.search(params); + return client.search<{}, typeof params>(params); } diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/mock-responses/timeseries_response.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/mock-responses/timeseries_response.ts index 075ede23fb38e..8f70f007a3f1d 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/mock-responses/timeseries_response.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/mock-responses/timeseries_response.ts @@ -6,7 +6,7 @@ import { ESResponse } from '../fetcher'; -export const timeseriesResponse: ESResponse = { +export const timeseriesResponse = ({ took: 368, timed_out: false, _shards: { @@ -2826,4 +2826,4 @@ export const timeseriesResponse: ESResponse = { value: 32861.15660262639 } } -}; +} as unknown) as ESResponse; diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.test.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.test.ts index a584cd70e2f8b..1da800ae21ab2 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.test.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.test.ts @@ -96,7 +96,7 @@ describe('getTpmBuckets', () => { } ]; const bucketSize = 10; - expect(getTpmBuckets(buckets, bucketSize)).toEqual([ + expect(getTpmBuckets(buckets as any, bucketSize)).toEqual([ { dataPoints: [ { x: 0, y: 0 }, diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts index 6d639eb7f9ffd..e3978217f260b 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts @@ -10,19 +10,7 @@ import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n'; import { Coordinate } from '../../../../../typings/timeseries'; import { ESResponse } from './fetcher'; -export interface ApmTimeSeriesResponse { - totalHits: number; - responseTimes: { - avg: Coordinate[]; - p95: Coordinate[]; - p99: Coordinate[]; - }; - tpmBuckets: Array<{ - key: string; - dataPoints: Coordinate[]; - }>; - overallAvgDuration?: number; -} +export type ApmTimeSeriesResponse = ReturnType; export function timeseriesTransformer({ timeseriesResponse, @@ -30,7 +18,7 @@ export function timeseriesTransformer({ }: { timeseriesResponse: ESResponse; bucketSize: number; -}): ApmTimeSeriesResponse { +}) { const aggs = timeseriesResponse.aggregations; const overallAvgDuration = idx(aggs, _ => _.overall_avg_duration.value); const responseTimeBuckets = idx(aggs, _ => _.response_times.buckets); diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts index 3e2a285f864e9..b2542110abc87 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; import { PROCESSOR_EVENT, SERVICE_NAME, @@ -22,8 +21,8 @@ export async function calculateBucketSize( ) { const { start, end, uiFiltersES, client, config } = setup; - const params: SearchParams = { - index: config.get('apm_oss.transactionIndices'), + const params = { + index: config.get('apm_oss.transactionIndices'), body: { size: 0, query: { @@ -56,13 +55,8 @@ export async function calculateBucketSize( } }; - interface Aggs { - stats: { - max: number; - }; - } + const resp = await client.search(params); - const resp = await client.search(params); const minBucketSize: number = config.get('xpack.apm.minimumBucketSize'); const bucketTargetCount: number = config.get('xpack.apm.bucketTargetCount'); const max = resp.aggregations.stats.max; diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts index e67d7db075df1..03aafd39c1749 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchResponse } from 'elasticsearch'; import { PROCESSOR_EVENT, SERVICE_NAME, @@ -15,29 +14,9 @@ import { TRANSACTION_SAMPLED, TRANSACTION_TYPE } from '../../../../../common/elasticsearch_fieldnames'; -import { PromiseReturnType } from '../../../../../typings/common'; -import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction'; import { rangeFilter } from '../../../helpers/range_filter'; import { Setup } from '../../../helpers/setup_request'; -interface Bucket { - key: number; - doc_count: number; - sample: SearchResponse<{ - transaction: Pick; - trace: { - id: string; - }; - }>; -} - -interface Aggs { - distribution: { - buckets: Bucket[]; - }; -} - -export type ESResponse = PromiseReturnType; export function bucketFetcher( serviceName: string, transactionName: string, @@ -95,5 +74,5 @@ export function bucketFetcher( } }; - return client.search(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts index 07e5004655e7f..2da9cdcb3a54f 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts @@ -6,7 +6,11 @@ import { isEmpty } from 'lodash'; import { idx } from '@kbn/elastic-idx'; -import { ESResponse } from './fetcher'; +import { PromiseReturnType } from '../../../../../typings/common'; +import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction'; +import { bucketFetcher } from './fetcher'; + +type DistributionBucketResponse = PromiseReturnType; function getDefaultSample(buckets: IBucket[]) { const samples = buckets @@ -23,9 +27,12 @@ function getDefaultSample(buckets: IBucket[]) { export type IBucket = ReturnType; function getBucket( - bucket: ESResponse['aggregations']['distribution']['buckets'][0] + bucket: DistributionBucketResponse['aggregations']['distribution']['buckets'][0] ) { - const sampleSource = idx(bucket, _ => _.sample.hits.hits[0]._source); + const sampleSource = idx( + bucket, + _ => _.sample.hits.hits[0]._source as Transaction + ); const isSampled = idx(sampleSource, _ => _.transaction.sampled); const sample = { traceId: idx(sampleSource, _ => _.trace.id), @@ -39,7 +46,7 @@ function getBucket( }; } -export function bucketTransformer(response: ESResponse) { +export function bucketTransformer(response: DistributionBucketResponse) { const buckets = response.aggregations.distribution.buckets.map(getBucket); return { diff --git a/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts b/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts index 71658da91bb37..f8310b9da77a7 100644 --- a/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts +++ b/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { BucketAgg, ESFilter } from 'elasticsearch'; +import { ESFilter } from 'elasticsearch'; import { idx } from '@kbn/elastic-idx'; import { PROCESSOR_EVENT, @@ -57,13 +57,7 @@ export async function getEnvironments(setup: Setup, serviceName?: string) { } }; - interface Aggs extends BucketAgg { - environments: { - buckets: BucketAgg[]; - }; - } - - const resp = await client.search(params); + const resp = await client.search(params); const aggs = resp.aggregations; const environmentsBuckets = idx(aggs, _ => _.environments.buckets) || []; diff --git a/x-pack/plugins/apm/typings/common.ts b/x-pack/plugins/apm/typings/common.ts index 6abbcc5413bd2..42c9d90f809aa 100644 --- a/x-pack/plugins/apm/typings/common.ts +++ b/x-pack/plugins/apm/typings/common.ts @@ -20,3 +20,9 @@ export type PromiseReturnType = Func extends ( ) => Promise ? Value : Func; + +export type IndexAsString = { + [k: string]: Map[keyof Map]; +} & Map; + +export type Omit = Pick>; diff --git a/x-pack/plugins/apm/typings/elasticsearch.ts b/x-pack/plugins/apm/typings/elasticsearch.ts index 1fa52da1e26da..abfbf7b244733 100644 --- a/x-pack/plugins/apm/typings/elasticsearch.ts +++ b/x-pack/plugins/apm/typings/elasticsearch.ts @@ -4,24 +4,118 @@ * you may not use this file except in compliance with the Elastic License. */ -import { StringMap } from './common'; +import { StringMap, IndexAsString } from './common'; declare module 'elasticsearch' { // extending SearchResponse to be able to have typed aggregations - export interface AggregationSearchResponse - extends SearchResponse { - aggregations: Aggs; - } - export interface BucketAgg { - key: T; - doc_count: number; - } + type AggregationType = + | 'date_histogram' + | 'histogram' + | 'terms' + | 'avg' + | 'top_hits' + | 'max' + | 'min' + | 'percentiles' + | 'sum' + | 'extended_stats'; - export interface TermsAggsBucket { - key: string; - doc_count: number; - } + type AggOptions = AggregationOptionMap & { + [key: string]: any; + }; + + // eslint-disable-next-line @typescript-eslint/prefer-interface + export type AggregationOptionMap = { + aggs?: { + [aggregationName: string]: { + [T in AggregationType]?: AggOptions & AggregationOptionMap + }; + }; + }; + + // eslint-disable-next-line @typescript-eslint/prefer-interface + type BucketAggregation = { + buckets: Array< + { + key: KeyType; + key_as_string: string; + doc_count: number; + } & (SubAggregationMap extends { aggs: any } + ? AggregationResultMap + : {}) + >; + }; + + type AggregationResultMap = IndexAsString< + { + [AggregationName in keyof AggregationOption]: { + avg: { + value: number | null; + }; + max: { + value: number | null; + }; + min: { + value: number | null; + }; + sum: { + value: number | null; + }; + terms: BucketAggregation; + date_histogram: BucketAggregation< + AggregationOption[AggregationName], + number + >; + histogram: BucketAggregation< + AggregationOption[AggregationName], + number + >; + top_hits: { + hits: { + total: number; + max_score: number | null; + hits: Array<{ + _source: AggregationOption[AggregationName] extends { + Mapping: any; + } + ? AggregationOption[AggregationName]['Mapping'] + : never; + }>; + }; + }; + percentiles: { + values: { + [key: string]: number; + }; + }; + extended_stats: { + count: number; + min: number; + max: number; + avg: number; + sum: number; + sum_of_squares: number; + variance: number; + std_deviation: number; + std_deviation_bounds: { + upper: number; + lower: number; + }; + }; + }[AggregationType & keyof AggregationOption[AggregationName]] + } + >; + + export type AggregationSearchResponse = Pick< + SearchResponse, + Exclude, 'aggregations'> + > & + (SearchParams extends { body: Required } + ? { + aggregations: AggregationResultMap; + } + : {}); export interface ESFilter { [key: string]: { From bd4bf4895564676bc9954729dfbe0a2ac397f499 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Wed, 12 Jun 2019 14:13:46 +0200 Subject: [PATCH 2/6] Fix idx error --- .../transactions/distribution/get_buckets/transform.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts index 2da9cdcb3a54f..c17b388cabb19 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts @@ -29,10 +29,10 @@ export type IBucket = ReturnType; function getBucket( bucket: DistributionBucketResponse['aggregations']['distribution']['buckets'][0] ) { - const sampleSource = idx( - bucket, - _ => _.sample.hits.hits[0]._source as Transaction - ); + const sampleSource = idx(bucket, _ => _.sample.hits.hits[0]._source) as + | Transaction + | undefined; + const isSampled = idx(sampleSource, _ => _.transaction.sampled); const sample = { traceId: idx(sampleSource, _ => _.trace.id), From d6b0d1ea690ae6bbe0a5ac61921ee4d64408c0a6 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Thu, 13 Jun 2019 15:19:25 +0200 Subject: [PATCH 3/6] Safeguard against querying against non-existing indices in functional tests --- .../apm/server/lib/errors/get_error_groups.ts | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts index 5f16f9979fa63..5adc5c440f9d2 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts @@ -111,21 +111,25 @@ export async function getErrorGroups({ const resp = await client.search(params); - const hits = resp.aggregations.error_groups.buckets.map(bucket => { - const source = bucket.sample.hits.hits[0]._source as SampleError; - const message = - idx(source, _ => _.error.log.message) || - idx(source, _ => _.error.exception[0].message); + // aggregations can be undefined when no matching indices are found. + // this is an exception rather than the rule so the ES type does not account for this. + const hits = (idx(resp, _ => _.aggregations.error_groups.buckets) || []).map( + bucket => { + const source = bucket.sample.hits.hits[0]._source as SampleError; + const message = + idx(source, _ => _.error.log.message) || + idx(source, _ => _.error.exception[0].message); - return { - message, - occurrenceCount: bucket.doc_count, - culprit: idx(source, _ => _.error.culprit), - groupId: idx(source, _ => _.error.grouping_key), - latestOccurrenceAt: source['@timestamp'], - handled: idx(source, _ => _.error.exception[0].handled) - }; - }); + return { + message, + occurrenceCount: bucket.doc_count, + culprit: idx(source, _ => _.error.culprit), + groupId: idx(source, _ => _.error.grouping_key), + latestOccurrenceAt: source['@timestamp'], + handled: idx(source, _ => _.error.exception[0].handled) + }; + } + ); return hits; } From 676a69fb7bb6c3a80e645be3eedd6c9d257ecd54 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Sat, 15 Jun 2019 22:49:12 +0200 Subject: [PATCH 4/6] Improve metric typings --- .../by_agent/java/heap_memory/fetcher.ts | 57 ------------- .../by_agent/java/heap_memory/index.ts | 82 +++++++++++-------- .../by_agent/java/non_heap_memory/fetcher.ts | 59 ------------- .../by_agent/java/non_heap_memory/index.ts | 75 ++++++++++------- .../by_agent/java/thread_count/fetcher.ts | 50 ----------- .../by_agent/java/thread_count/index.ts | 55 ++++++++----- .../metrics/by_agent/shared/cpu/fetcher.ts | 54 ------------ .../lib/metrics/by_agent/shared/cpu/index.ts | 82 +++++++++++-------- .../metrics/by_agent/shared/memory/fetcher.ts | 67 --------------- .../metrics/by_agent/shared/memory/index.ts | 68 ++++++++++----- .../metrics/fetch_and_transform_metrics.ts | 80 ++++++++++++++++++ .../metrics/transform_metrics_chart.test.ts | 7 +- .../lib/metrics/transform_metrics_chart.ts | 45 ++++++---- .../plugins/apm/server/lib/metrics/types.ts | 31 +------ x-pack/plugins/apm/typings/elasticsearch.ts | 20 ++--- 15 files changed, 341 insertions(+), 491 deletions(-) delete mode 100644 x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts delete mode 100644 x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts delete mode 100644 x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts delete mode 100644 x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts delete mode 100644 x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts create mode 100644 x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts deleted file mode 100644 index 49f6607f6cc34..0000000000000 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/fetcher.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 { - SERVICE_AGENT_NAME, - PROCESSOR_EVENT, - SERVICE_NAME, - METRIC_JAVA_HEAP_MEMORY_MAX, - METRIC_JAVA_HEAP_MEMORY_COMMITTED, - METRIC_JAVA_HEAP_MEMORY_USED -} from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; -import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; -import { rangeFilter } from '../../../../helpers/range_filter'; - -export async function fetch(setup: Setup, serviceName: string) { - const { start, end, uiFiltersES, client, config } = setup; - - const aggs = { - heapMemoryMax: { avg: { field: METRIC_JAVA_HEAP_MEMORY_MAX } }, - heapMemoryCommitted: { - avg: { field: METRIC_JAVA_HEAP_MEMORY_COMMITTED } - }, - heapMemoryUsed: { avg: { field: METRIC_JAVA_HEAP_MEMORY_USED } } - }; - - const params = { - index: config.get('apm_oss.metricsIndices'), - body: { - size: 0, - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - { term: { [PROCESSOR_EVENT]: 'metric' } }, - { term: { [SERVICE_AGENT_NAME]: 'java' } }, - { - range: rangeFilter(start, end) - }, - ...uiFiltersES - ] - } - }, - aggs: { - timeseriesData: { - date_histogram: getMetricsDateHistogramParams(start, end), - aggs - }, - ...aggs - } - } - }; - - return client.search(params); -} diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts index 599043a8efb7c..48c7ee29a16a3 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts @@ -6,50 +6,62 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; +import { + METRIC_JAVA_HEAP_MEMORY_MAX, + METRIC_JAVA_HEAP_MEMORY_COMMITTED, + METRIC_JAVA_HEAP_MEMORY_USED, + SERVICE_AGENT_NAME +} from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch } from './fetcher'; -import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; -import { ChartBase, MetricSearchResponse } from '../../../types'; +import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; +import { ChartBase } from '../../../types'; -const chartBase = { +const series = { + heapMemoryUsed: { + title: i18n.translate('xpack.apm.agentMetrics.java.heapMemorySeriesUsed', { + defaultMessage: 'Avg. used' + }), + color: theme.euiColorVis0 + }, + heapMemoryCommitted: { + title: i18n.translate( + 'xpack.apm.agentMetrics.java.heapMemorySeriesCommitted', + { + defaultMessage: 'Avg. committed' + } + ), + color: theme.euiColorVis1 + }, + heapMemoryMax: { + title: i18n.translate('xpack.apm.agentMetrics.java.heapMemorySeriesMax', { + defaultMessage: 'Avg. limit' + }), + color: theme.euiColorVis2 + } +}; + +const chartBase: ChartBase = { title: i18n.translate('xpack.apm.agentMetrics.java.heapMemoryChartTitle', { defaultMessage: 'Heap Memory' }), key: 'heap_memory_area_chart', type: 'area', yUnit: 'bytes', - series: { - heapMemoryUsed: { - title: i18n.translate( - 'xpack.apm.agentMetrics.java.heapMemorySeriesUsed', - { - defaultMessage: 'Avg. used' - } - ), - color: theme.euiColorVis0 - }, - heapMemoryCommitted: { - title: i18n.translate( - 'xpack.apm.agentMetrics.java.heapMemorySeriesCommitted', - { - defaultMessage: 'Avg. committed' - } - ), - color: theme.euiColorVis1 - }, - heapMemoryMax: { - title: i18n.translate('xpack.apm.agentMetrics.java.heapMemorySeriesMax', { - defaultMessage: 'Avg. limit' - }), - color: theme.euiColorVis2 - } - } + series }; export async function getHeapMemoryChart(setup: Setup, serviceName: string) { - const result = (await fetch(setup, serviceName)) as MetricSearchResponse< - keyof typeof chartBase.series - >; - - return transformDataToMetricsChart(result, chartBase as ChartBase); + return fetchAndTransformMetrics({ + setup, + serviceName, + chartBase, + aggs: { + heapMemoryMax: { avg: { field: METRIC_JAVA_HEAP_MEMORY_MAX } }, + heapMemoryCommitted: { + avg: { field: METRIC_JAVA_HEAP_MEMORY_COMMITTED } + }, + heapMemoryUsed: { avg: { field: METRIC_JAVA_HEAP_MEMORY_USED } } + }, + additionalFilters: [{ term: { [SERVICE_AGENT_NAME]: 'java' } }] + }); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts deleted file mode 100644 index 48293de27c346..0000000000000 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/fetcher.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 { - SERVICE_AGENT_NAME, - PROCESSOR_EVENT, - SERVICE_NAME, - METRIC_JAVA_NON_HEAP_MEMORY_MAX, - METRIC_JAVA_NON_HEAP_MEMORY_COMMITTED, - METRIC_JAVA_NON_HEAP_MEMORY_USED -} from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; -import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; -import { rangeFilter } from '../../../../helpers/range_filter'; - -export async function fetch(setup: Setup, serviceName: string) { - const { start, end, uiFiltersES, client, config } = setup; - - const aggs = { - nonHeapMemoryMax: { avg: { field: METRIC_JAVA_NON_HEAP_MEMORY_MAX } }, - nonHeapMemoryCommitted: { - avg: { field: METRIC_JAVA_NON_HEAP_MEMORY_COMMITTED } - }, - nonHeapMemoryUsed: { - avg: { field: METRIC_JAVA_NON_HEAP_MEMORY_USED } - } - }; - - const params = { - index: config.get('apm_oss.metricsIndices'), - body: { - size: 0, - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - { term: { [PROCESSOR_EVENT]: 'metric' } }, - { term: { [SERVICE_AGENT_NAME]: 'java' } }, - { - range: rangeFilter(start, end) - }, - ...uiFiltersES - ] - } - }, - aggs: { - timeseriesData: { - date_histogram: getMetricsDateHistogramParams(start, end), - aggs - }, - ...aggs - } - } - }; - - return client.search(params); -} diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts index eb6e7d652faa4..446d9258b4310 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts @@ -6,44 +6,61 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; +import { + METRIC_JAVA_NON_HEAP_MEMORY_MAX, + METRIC_JAVA_NON_HEAP_MEMORY_COMMITTED, + METRIC_JAVA_NON_HEAP_MEMORY_USED, + SERVICE_AGENT_NAME +} from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch } from './fetcher'; -import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; -import { MetricSearchResponse, ChartBase } from '../../../types'; +import { ChartBase } from '../../../types'; +import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; -const chartBase = { +const series = { + nonHeapMemoryUsed: { + title: i18n.translate( + 'xpack.apm.agentMetrics.java.nonHeapMemorySeriesUsed', + { + defaultMessage: 'Avg. used' + } + ), + color: theme.euiColorVis0 + }, + nonHeapMemoryCommitted: { + title: i18n.translate( + 'xpack.apm.agentMetrics.java.nonHeapMemorySeriesCommitted', + { + defaultMessage: 'Avg. committed' + } + ), + color: theme.euiColorVis1 + } +}; + +const chartBase: ChartBase = { title: i18n.translate('xpack.apm.agentMetrics.java.nonHeapMemoryChartTitle', { defaultMessage: 'Non-Heap Memory' }), key: 'non_heap_memory_area_chart', type: 'area', yUnit: 'bytes', - series: { - nonHeapMemoryUsed: { - title: i18n.translate( - 'xpack.apm.agentMetrics.java.nonHeapMemorySeriesUsed', - { - defaultMessage: 'Avg. used' - } - ), - color: theme.euiColorVis0 - }, - nonHeapMemoryCommitted: { - title: i18n.translate( - 'xpack.apm.agentMetrics.java.nonHeapMemorySeriesCommitted', - { - defaultMessage: 'Avg. committed' - } - ), - color: theme.euiColorVis1 - } - } + series }; export async function getNonHeapMemoryChart(setup: Setup, serviceName: string) { - const result = (await fetch(setup, serviceName)) as MetricSearchResponse< - keyof typeof chartBase.series - >; - - return transformDataToMetricsChart(result, chartBase as ChartBase); + return fetchAndTransformMetrics({ + setup, + serviceName, + chartBase, + aggs: { + nonHeapMemoryMax: { avg: { field: METRIC_JAVA_NON_HEAP_MEMORY_MAX } }, + nonHeapMemoryCommitted: { + avg: { field: METRIC_JAVA_NON_HEAP_MEMORY_COMMITTED } + }, + nonHeapMemoryUsed: { + avg: { field: METRIC_JAVA_NON_HEAP_MEMORY_USED } + } + }, + additionalFilters: [{ term: { [SERVICE_AGENT_NAME]: 'java' } }] + }); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts deleted file mode 100644 index 516badecb346d..0000000000000 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/fetcher.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 { - SERVICE_AGENT_NAME, - PROCESSOR_EVENT, - SERVICE_NAME, - METRIC_JAVA_THREAD_COUNT -} from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; -import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; -import { rangeFilter } from '../../../../helpers/range_filter'; - -export async function fetch(setup: Setup, serviceName: string) { - const { start, end, uiFiltersES, client, config } = setup; - - const aggs = { - threadCount: { avg: { field: METRIC_JAVA_THREAD_COUNT } }, - threadCountMax: { max: { field: METRIC_JAVA_THREAD_COUNT } } - }; - - const params = { - index: config.get('apm_oss.metricsIndices'), - body: { - size: 0, - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - { term: { [PROCESSOR_EVENT]: 'metric' } }, - { term: { [SERVICE_AGENT_NAME]: 'java' } }, - { range: rangeFilter(start, end) }, - ...uiFiltersES - ] - } - }, - aggs: { - timeseriesData: { - date_histogram: getMetricsDateHistogramParams(start, end), - aggs - }, - ...aggs - } - } - }; - - return client.search(params); -} diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts index 6296018d324b9..5f53cde44d622 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts @@ -6,37 +6,48 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; +import { + METRIC_JAVA_THREAD_COUNT, + SERVICE_AGENT_NAME +} from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch } from './fetcher'; -import { ChartBase, MetricSearchResponse } from '../../../types'; -import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; +import { ChartBase } from '../../../types'; +import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; -const chartBase = { +const series = { + threadCount: { + title: i18n.translate('xpack.apm.agentMetrics.java.threadCount', { + defaultMessage: 'Avg. count' + }), + color: theme.euiColorVis0 + }, + threadCountMax: { + title: i18n.translate('xpack.apm.agentMetrics.java.threadCountMax', { + defaultMessage: 'Max count' + }), + color: theme.euiColorVis1 + } +}; + +const chartBase: ChartBase = { title: i18n.translate('xpack.apm.agentMetrics.java.threadCountChartTitle', { defaultMessage: 'Thread Count' }), key: 'thread_count_line_chart', type: 'linemark', yUnit: 'number', - series: { - threadCount: { - title: i18n.translate('xpack.apm.agentMetrics.java.threadCount', { - defaultMessage: 'Avg. count' - }), - color: theme.euiColorVis0 - }, - threadCountMax: { - title: i18n.translate('xpack.apm.agentMetrics.java.threadCountMax', { - defaultMessage: 'Max count' - }), - color: theme.euiColorVis1 - } - } + series }; export async function getThreadCountChart(setup: Setup, serviceName: string) { - const result = (await fetch(setup, serviceName)) as MetricSearchResponse< - keyof typeof chartBase.series - >; - return transformDataToMetricsChart(result, chartBase as ChartBase); + return fetchAndTransformMetrics({ + setup, + serviceName, + chartBase, + aggs: { + threadCount: { avg: { field: METRIC_JAVA_THREAD_COUNT } }, + threadCountMax: { max: { field: METRIC_JAVA_THREAD_COUNT } } + }, + additionalFilters: [{ term: { [SERVICE_AGENT_NAME]: 'java' } }] + }); } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts deleted file mode 100644 index 813e1b05d3a35..0000000000000 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/fetcher.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 { - METRIC_PROCESS_CPU_PERCENT, - METRIC_SYSTEM_CPU_PERCENT, - PROCESSOR_EVENT, - SERVICE_NAME -} from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; -import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; -import { rangeFilter } from '../../../../helpers/range_filter'; - -export async function fetch(setup: Setup, serviceName: string) { - const { start, end, uiFiltersES, client, config } = setup; - - const aggs = { - systemCPUAverage: { avg: { field: METRIC_SYSTEM_CPU_PERCENT } }, - systemCPUMax: { max: { field: METRIC_SYSTEM_CPU_PERCENT } }, - processCPUAverage: { avg: { field: METRIC_PROCESS_CPU_PERCENT } }, - processCPUMax: { max: { field: METRIC_PROCESS_CPU_PERCENT } } - }; - - const params = { - index: config.get('apm_oss.metricsIndices'), - body: { - size: 0, - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - { term: { [PROCESSOR_EVENT]: 'metric' } }, - { - range: rangeFilter(start, end) - }, - ...uiFiltersES - ] - } - }, - aggs: { - timeseriesData: { - date_histogram: getMetricsDateHistogramParams(start, end), - aggs - }, - ...aggs - } - } - }; - - return client.search(params); -} diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts index 1f5671dd4fb5c..67f69456e9e1b 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts @@ -6,49 +6,63 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; +import { + METRIC_SYSTEM_CPU_PERCENT, + METRIC_PROCESS_CPU_PERCENT +} from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch } from './fetcher'; -import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; -import { MetricSearchResponse, ChartBase } from '../../../types'; +import { ChartBase } from '../../../types'; +import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; -const chartBase = { +const series = { + systemCPUMax: { + title: i18n.translate('xpack.apm.chart.cpuSeries.systemMaxLabel', { + defaultMessage: 'System max' + }), + color: theme.euiColorVis1 + }, + systemCPUAverage: { + title: i18n.translate('xpack.apm.chart.cpuSeries.systemAverageLabel', { + defaultMessage: 'System average' + }), + color: theme.euiColorVis0 + }, + processCPUMax: { + title: i18n.translate('xpack.apm.chart.cpuSeries.processMaxLabel', { + defaultMessage: 'Process max' + }), + color: theme.euiColorVis7 + }, + processCPUAverage: { + title: i18n.translate('xpack.apm.chart.cpuSeries.processAverageLabel', { + defaultMessage: 'Process average' + }), + color: theme.euiColorVis5 + } +}; + +const chartBase: ChartBase = { title: i18n.translate('xpack.apm.serviceDetails.metrics.cpuUsageChartTitle', { defaultMessage: 'CPU usage' }), key: 'cpu_usage_chart', type: 'linemark', yUnit: 'percent', - series: { - systemCPUMax: { - title: i18n.translate('xpack.apm.chart.cpuSeries.systemMaxLabel', { - defaultMessage: 'System max' - }), - color: theme.euiColorVis1 - }, - systemCPUAverage: { - title: i18n.translate('xpack.apm.chart.cpuSeries.systemAverageLabel', { - defaultMessage: 'System average' - }), - color: theme.euiColorVis0 - }, - processCPUMax: { - title: i18n.translate('xpack.apm.chart.cpuSeries.processMaxLabel', { - defaultMessage: 'Process max' - }), - color: theme.euiColorVis7 - }, - processCPUAverage: { - title: i18n.translate('xpack.apm.chart.cpuSeries.processAverageLabel', { - defaultMessage: 'Process average' - }), - color: theme.euiColorVis5 - } - } + series }; export async function getCPUChartData(setup: Setup, serviceName: string) { - const result = (await fetch(setup, serviceName)) as MetricSearchResponse< - keyof typeof chartBase.series - >; - return transformDataToMetricsChart(result, chartBase as ChartBase); + const metricsChart = await fetchAndTransformMetrics({ + setup, + serviceName, + chartBase, + aggs: { + systemCPUAverage: { avg: { field: METRIC_SYSTEM_CPU_PERCENT } }, + systemCPUMax: { max: { field: METRIC_SYSTEM_CPU_PERCENT } }, + processCPUAverage: { avg: { field: METRIC_PROCESS_CPU_PERCENT } }, + processCPUMax: { max: { field: METRIC_PROCESS_CPU_PERCENT } } + } + }); + + return metricsChart; } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts deleted file mode 100644 index 8737b6fdad714..0000000000000 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/fetcher.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 { - PROCESSOR_EVENT, - SERVICE_NAME, - METRIC_SYSTEM_FREE_MEMORY, - METRIC_SYSTEM_TOTAL_MEMORY -} from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; -import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; -import { rangeFilter } from '../../../../helpers/range_filter'; - -const percentUsedScript = { - lang: 'expression', - source: `1 - doc['${METRIC_SYSTEM_FREE_MEMORY}'] / doc['${METRIC_SYSTEM_TOTAL_MEMORY}']` -}; - -export async function fetch(setup: Setup, serviceName: string) { - const { start, end, uiFiltersES, client, config } = setup; - - const aggs = { - memoryUsedAvg: { avg: { script: percentUsedScript } }, - memoryUsedMax: { max: { script: percentUsedScript } } - }; - - const params = { - index: config.get('apm_oss.metricsIndices'), - body: { - size: 0, - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - { term: { [PROCESSOR_EVENT]: 'metric' } }, - { - range: rangeFilter(start, end) - }, - { - exists: { - field: METRIC_SYSTEM_FREE_MEMORY - } - }, - { - exists: { - field: METRIC_SYSTEM_TOTAL_MEMORY - } - }, - ...uiFiltersES - ] - } - }, - aggs: { - timeseriesData: { - date_histogram: getMetricsDateHistogramParams(start, end), - aggs - }, - ...aggs - } - } - }; - - return client.search(params); -} diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts index 27607fb2171ee..e372a62a7ce05 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts @@ -5,12 +5,28 @@ */ import { i18n } from '@kbn/i18n'; +import { + METRIC_SYSTEM_FREE_MEMORY, + METRIC_SYSTEM_TOTAL_MEMORY +} from '../../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../helpers/setup_request'; -import { fetch } from './fetcher'; -import { ChartBase, MetricSearchResponse } from '../../../types'; -import { transformDataToMetricsChart } from '../../../transform_metrics_chart'; +import { ChartBase } from '../../../types'; +import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; -const chartBase = { +const series = { + memoryUsedMax: { + title: i18n.translate('xpack.apm.chart.memorySeries.systemMaxLabel', { + defaultMessage: 'Max' + }) + }, + memoryUsedAvg: { + title: i18n.translate('xpack.apm.chart.memorySeries.systemAverageLabel', { + defaultMessage: 'Average' + }) + } +}; + +const chartBase: ChartBase = { title: i18n.translate( 'xpack.apm.serviceDetails.metrics.memoryUsageChartTitle', { @@ -20,24 +36,34 @@ const chartBase = { key: 'memory_usage_chart', type: 'linemark', yUnit: 'percent', - series: { - memoryUsedMax: { - title: i18n.translate('xpack.apm.chart.memorySeries.systemMaxLabel', { - defaultMessage: 'Max' - }) - }, - memoryUsedAvg: { - title: i18n.translate('xpack.apm.chart.memorySeries.systemAverageLabel', { - defaultMessage: 'Average' - }) - } - } + series }; -export async function getMemoryChartData(setup: Setup, serviceName: string) { - const result = (await fetch(setup, serviceName)) as MetricSearchResponse< - keyof typeof chartBase.series - >; +const percentUsedScript = { + lang: 'expression', + source: `1 - doc['${METRIC_SYSTEM_FREE_MEMORY}'] / doc['${METRIC_SYSTEM_TOTAL_MEMORY}']` +}; - return transformDataToMetricsChart(result, chartBase as ChartBase); +export async function getMemoryChartData(setup: Setup, serviceName: string) { + return fetchAndTransformMetrics({ + setup, + serviceName, + chartBase, + aggs: { + memoryUsedAvg: { avg: { script: percentUsedScript } }, + memoryUsedMax: { max: { script: percentUsedScript } } + }, + additionalFilters: [ + { + exists: { + field: METRIC_SYSTEM_FREE_MEMORY + } + }, + { + exists: { + field: METRIC_SYSTEM_TOTAL_MEMORY + } + } + ] + }); } diff --git a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts new file mode 100644 index 0000000000000..c370bb2384a57 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts @@ -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 { + PROCESSOR_EVENT, + SERVICE_NAME +} from '../../../common/elasticsearch_fieldnames'; +import { Setup } from '../helpers/setup_request'; +import { getMetricsDateHistogramParams } from '../helpers/metrics'; +import { rangeFilter } from '../helpers/range_filter'; +import { ChartBase } from './types'; +import { transformDataToMetricsChart } from './transform_metrics_chart'; + +interface Aggs { + [key: string]: { + min?: any; + max?: any; + sum?: any; + avg?: any; + }; +} + +interface Filter { + exists?: { + field: string; + }; + term?: { + [key: string]: string; + }; +} + +export async function fetchAndTransformMetrics({ + setup, + serviceName, + chartBase, + aggs, + additionalFilters = [] +}: { + setup: Setup; + serviceName: string; + chartBase: ChartBase; + aggs: T; + additionalFilters?: Filter[]; +}) { + const { start, end, uiFiltersES, client, config } = setup; + + const params = { + index: config.get('apm_oss.metricsIndices'), + body: { + size: 0, + query: { + bool: { + filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + { term: { [PROCESSOR_EVENT]: 'metric' } }, + { + range: rangeFilter(start, end) + }, + ...additionalFilters, + ...uiFiltersES + ] + } + }, + aggs: { + timeseriesData: { + date_histogram: getMetricsDateHistogramParams(start, end), + aggs + }, + ...aggs + } + } + }; + + const response = await client.search(params); + + return transformDataToMetricsChart(response, chartBase); +} diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts index 8ca7f525fe8b8..e077105e9b2e5 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts @@ -5,12 +5,9 @@ */ import { transformDataToMetricsChart } from './transform_metrics_chart'; import { ChartType, YUnit } from '../../../typings/timeseries'; -import { MetricSearchResponse } from './types'; test('transformDataToMetricsChart should transform an ES result into a chart object', () => { - type R = MetricSearchResponse<'a' | 'b' | 'c'>; - - const response = ({ + const response = { hits: { total: 5000 }, aggregations: { a: { value: 1000 }, @@ -42,7 +39,7 @@ test('transformDataToMetricsChart should transform an ES result into a chart obj ] } } - } as unknown) as R; + } as any; const chartBase = { title: 'Test Chart Title', diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index 22ed499195e9b..f53f886d8a74d 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { ChartBase, MetricSearchResponse } from './types'; +import { AggregationSearchResponse, AggregatedValue } from 'elasticsearch'; +import { ChartBase } from './types'; const colors = [ theme.euiColorVis0, @@ -20,17 +21,31 @@ export type GenericMetricsChart = ReturnType< typeof transformDataToMetricsChart >; -type TimeseriesBucket = { - key: number; - doc_count: number; -} & { - [key: string]: { - value: number; +interface AggregatedParams { + body: { + aggs: { + timeseriesData: { + date_histogram: any; + aggs: { + min?: any; + max?: any; + sum?: any; + avg?: any; + }; + }; + } & { + [key: string]: { + min?: any; + max?: any; + sum?: any; + avg?: any; + }; + }; }; -}; +} -export function transformDataToMetricsChart( - result: MetricSearchResponse, +export function transformDataToMetricsChart( + result: AggregationSearchResponse, chartBase: ChartBase ) { const { aggregations, hits } = result; @@ -42,11 +57,7 @@ export function transformDataToMetricsChart( yUnit: chartBase.yUnit, totalHits: hits.total, series: Object.keys(chartBase.series).map((seriesKey, i) => { - const agg = aggregations[seriesKey]; - - if (!(agg && 'value' in agg)) { - throw new Error('No value found for metric aggregation'); - } + const agg = aggregations[seriesKey] as AggregatedValue; return { title: chartBase.series[seriesKey].title, @@ -54,8 +65,8 @@ export function transformDataToMetricsChart( type: chartBase.type, color: chartBase.series[seriesKey].color || colors[i], overallValue: agg.value, - data: (timeseriesData.buckets as TimeseriesBucket[]).map(bucket => { - const { value } = bucket[seriesKey]; + data: timeseriesData.buckets.map(bucket => { + const { value } = bucket[seriesKey] as AggregatedValue; const y = value === null || isNaN(value) ? null : value; return { x: bucket.key, diff --git a/x-pack/plugins/apm/server/lib/metrics/types.ts b/x-pack/plugins/apm/server/lib/metrics/types.ts index 453e9cab5aaea..622b37162d9dc 100644 --- a/x-pack/plugins/apm/server/lib/metrics/types.ts +++ b/x-pack/plugins/apm/server/lib/metrics/types.ts @@ -3,44 +3,17 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { - PromiseReturnType, - IndexAsString, - Omit -} from '../../../typings/common'; import { ChartType, YUnit } from '../../../typings/timeseries'; -import { fetch as cpuFetch } from './by_agent/shared/cpu/fetcher'; - -type CpuSearchResponse = PromiseReturnType; - -export type MetricSearchResponse = Omit< - CpuSearchResponse, - 'aggregations' -> & { - aggregations: IndexAsString< - { [key in MetricNames]: { value: number } } & { - timeseriesData: { - buckets: Array< - { - key: number; - doc_count: number; - } & { [key in MetricNames]: { value: number } } - >; - }; - } - >; -}; export interface ChartBase { title: string; key: string; type: ChartType; yUnit: YUnit; - series: IndexAsString<{ + series: { [key: string]: { title: string; color?: string; }; - }>; + }; } diff --git a/x-pack/plugins/apm/typings/elasticsearch.ts b/x-pack/plugins/apm/typings/elasticsearch.ts index abfbf7b244733..4ba936f480155 100644 --- a/x-pack/plugins/apm/typings/elasticsearch.ts +++ b/x-pack/plugins/apm/typings/elasticsearch.ts @@ -47,21 +47,17 @@ declare module 'elasticsearch' { >; }; + interface AggregatedValue { + value: number | null; + } + type AggregationResultMap = IndexAsString< { [AggregationName in keyof AggregationOption]: { - avg: { - value: number | null; - }; - max: { - value: number | null; - }; - min: { - value: number | null; - }; - sum: { - value: number | null; - }; + avg: AggregatedValue; + max: AggregatedValue; + min: AggregatedValue; + sum: AggregatedValue; terms: BucketAggregation; date_histogram: BucketAggregation< AggregationOption[AggregationName], From dc9e9362cd1db9e3cfb4fb70f2fbb7578ac9043e Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Sun, 16 Jun 2019 12:38:42 +0200 Subject: [PATCH 5/6] Automatically infer params from function arguments --- .../apm/server/lib/errors/distribution/get_buckets.ts | 2 +- x-pack/plugins/apm/server/lib/errors/get_error_groups.ts | 2 +- .../server/lib/errors/get_trace_errors_per_transaction.ts | 2 +- x-pack/plugins/apm/server/lib/helpers/es_client.ts | 8 ++++---- .../apm/server/lib/metrics/fetch_and_transform_metrics.ts | 2 +- x-pack/plugins/apm/server/lib/services/get_service.ts | 2 +- .../lib/services/get_services/get_services_items.ts | 2 +- .../plugins/apm/server/lib/transaction_groups/fetcher.ts | 2 +- .../lib/transactions/charts/get_anomaly_data/fetcher.ts | 2 +- .../transactions/charts/get_timeseries_data/fetcher.ts | 2 +- .../lib/transactions/distribution/get_buckets/fetcher.ts | 2 +- .../plugins/apm/server/lib/ui_filters/get_environments.ts | 2 +- 12 files changed, 15 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts index 5e18e27ac670d..233bc143a8df8 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts @@ -61,7 +61,7 @@ export async function getBuckets({ } }; - const resp = await client.search(params); + const resp = await client.search(params); const buckets = resp.aggregations.distribution.buckets.map(bucket => ({ key: bucket.key, diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts index 5adc5c440f9d2..33a93fa986db3 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts @@ -109,7 +109,7 @@ export async function getErrorGroups({ }; } - const resp = await client.search(params); + const resp = await client.search(params); // aggregations can be undefined when no matching indices are found. // this is an exception rather than the rule so the ES type does not account for this. diff --git a/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts b/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts index 9d5be70df7205..25b74cafae69e 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts @@ -45,7 +45,7 @@ export async function getTraceErrorsPerTransaction( } }; - const resp = await client.search(params); + const resp = await client.search(params); return resp.aggregations.transactions.buckets.reduce( (acc, bucket) => ({ diff --git a/x-pack/plugins/apm/server/lib/helpers/es_client.ts b/x-pack/plugins/apm/server/lib/helpers/es_client.ts index 208e33893e589..420c7087c8032 100644 --- a/x-pack/plugins/apm/server/lib/helpers/es_client.ts +++ b/x-pack/plugins/apm/server/lib/helpers/es_client.ts @@ -90,10 +90,10 @@ export function getESClient(req: Legacy.Request) { const query = (req.query as unknown) as APMRequestQuery; return { - search: async ( - params: SearchParams, + search: async ( + params: U, apmOptions?: APMOptions - ): Promise> => { + ): Promise> => { const nextParams = await getParamsForSearchRequest( req, params, @@ -112,7 +112,7 @@ export function getESClient(req: Legacy.Request) { } return cluster.callWithRequest(req, 'search', nextParams) as Promise< - AggregationSearchResponse + AggregationSearchResponse >; }, index: (params: IndexDocumentParams) => { diff --git a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts index c370bb2384a57..eefa1e0ef201a 100644 --- a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts @@ -74,7 +74,7 @@ export async function fetchAndTransformMetrics({ } }; - const response = await client.search(params); + const response = await client.search(params); return transformDataToMetricsChart(response, chartBase); } diff --git a/x-pack/plugins/apm/server/lib/services/get_service.ts b/x-pack/plugins/apm/server/lib/services/get_service.ts index 42264b70e2ecb..d39397fedd154 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service.ts @@ -46,7 +46,7 @@ export async function getService(serviceName: string, setup: Setup) { } }; - const { aggregations } = await client.search(params); + const { aggregations } = await client.search(params); const buckets = idx(aggregations, _ => _.types.buckets) || []; const types = buckets.map(bucket => bucket.key); const agentName = idx(aggregations, _ => _.agents.buckets[0].key) || ''; diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts index a9affcce1c515..75410b70e0139 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts @@ -64,7 +64,7 @@ export async function getServicesItems(setup: Setup) { } }; - const resp = await client.search<{}, typeof params>(params); + const resp = await client.search(params); const aggs = resp.aggregations; const serviceBuckets = idx(aggs, _ => _.services.buckets) || []; diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index ea66fa0ff399e..b909d5ff62a74 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -47,5 +47,5 @@ export function transactionGroupsFetcher(setup: Setup, bodyQuery: StringMap) { } }; - return client.search(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts index 8e859b39b8c46..b8af24b840d99 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts @@ -74,7 +74,7 @@ export async function anomalySeriesFetcher({ }; try { - const response = await client.search(params); + const response = await client.search(params); return response; } catch (err) { const isHttpError = 'statusCode' in err; diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts index 626fe57e46cf5..8ccf1af568535 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts @@ -87,5 +87,5 @@ export function timeseriesFetcher({ } }; - return client.search<{}, typeof params>(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts index 03aafd39c1749..d265aa5173d2f 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts @@ -74,5 +74,5 @@ export function bucketFetcher( } }; - return client.search(params); + return client.search(params); } diff --git a/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts b/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts index f8310b9da77a7..93a82bf6db85b 100644 --- a/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts +++ b/x-pack/plugins/apm/server/lib/ui_filters/get_environments.ts @@ -57,7 +57,7 @@ export async function getEnvironments(setup: Setup, serviceName?: string) { } }; - const resp = await client.search(params); + const resp = await client.search(params); const aggs = resp.aggregations; const environmentsBuckets = idx(aggs, _ => _.environments.buckets) || []; From 8ac37e617cad8a9b8ee6a9484783a22aa785dcf7 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Mon, 17 Jun 2019 09:12:15 +0200 Subject: [PATCH 6/6] Remove unnecessary type hints --- .../plugins/apm/server/lib/metrics/transform_metrics_chart.ts | 2 +- .../lib/transactions/distribution/calculate_bucket_size.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index f53f886d8a74d..1acac008c8bf8 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -57,7 +57,7 @@ export function transformDataToMetricsChart( yUnit: chartBase.yUnit, totalHits: hits.total, series: Object.keys(chartBase.series).map((seriesKey, i) => { - const agg = aggregations[seriesKey] as AggregatedValue; + const agg = aggregations[seriesKey]; return { title: chartBase.series[seriesKey].title, diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts index b2542110abc87..20f69a0bd4d8c 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.ts @@ -55,7 +55,7 @@ export async function calculateBucketSize( } }; - const resp = await client.search(params); + const resp = await client.search(params); const minBucketSize: number = config.get('xpack.apm.minimumBucketSize'); const bucketTargetCount: number = config.get('xpack.apm.bucketTargetCount');