Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions x-pack/legacy/plugins/apm/common/projections/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { SearchParams } from 'elasticsearch';
import { ESSearchRequest, ESSearchBody } from '../../typings/elasticsearch';
import {
AggregationOptionsByType,
AggregationInputMap
} from '../../typings/elasticsearch/aggregations';

export type Projection = Omit<SearchParams, 'body' | 'aggs'> & {
body: {
query: any;
} & {
export type Projection = Omit<ESSearchRequest, 'body'> & {
body: Omit<ESSearchBody, 'aggs'> & {
aggs?: {
[key: string]: {
terms: any;
terms: AggregationOptionsByType['terms'];
aggs?: AggregationInputMap;
};
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ describe('mergeProjection', () => {
});

it('merges plain objects', () => {
const termsAgg = { terms: { field: 'bar' } };
expect(
mergeProjection(
{ body: { query: {}, aggs: { foo: { terms: { field: 'bar' } } } } },
{ body: { query: {}, aggs: { foo: termsAgg } } },
{
body: {
aggs: { foo: { aggs: { bar: { terms: { field: 'baz' } } } } }
aggs: {
foo: { ...termsAgg, aggs: { bar: { terms: { field: 'baz' } } } }
}
}
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { merge, isPlainObject } from 'lodash';
import { DeepPartial } from 'utility-types';
import { AggregationInputMap } from '../../../../typings/elasticsearch/aggregations';
import {
ESSearchRequest,
ESSearchBody
} from '../../../../typings/elasticsearch';
import { Projection } from '../../typings';

type PlainObject = Record<string | number | symbol, any>;

type SourceProjection = Omit<DeepPartial<ESSearchRequest>, 'body'> & {
body: Omit<DeepPartial<ESSearchBody>, 'aggs'> & {
aggs?: AggregationInputMap;
};
};

type DeepMerge<T, U> = U extends PlainObject
? (T extends PlainObject
? (Omit<T, keyof U> &
Expand All @@ -19,10 +31,10 @@ type DeepMerge<T, U> = U extends PlainObject
: U)
: U;

export function mergeProjection<T extends Projection, U>(
target: T,
source: U
): DeepMerge<T, U> {
export function mergeProjection<
T extends Projection,
U extends SourceProjection
>(target: T, source: U): DeepMerge<T, U> {
return merge({}, target, source, (a, b) => {
if (isPlainObject(a) && isPlainObject(b)) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const ErrorGroupOverview: React.SFC = () => {

const { data: errorGroupListData } = useFetcher(
callApmApi => {
const normalizedSortDirection = sortDirection === 'asc' ? 'asc' : 'desc';

if (serviceName && start && end) {
return callApmApi({
pathname: '/api/apm/services/{serviceName}/errors',
Expand All @@ -60,7 +62,7 @@ const ErrorGroupOverview: React.SFC = () => {
start,
end,
sortField,
sortDirection,
sortDirection: normalizedSortDirection,
uiFilters: JSON.stringify(uiFilters)
}
}
Expand Down
2 changes: 1 addition & 1 deletion x-pack/legacy/plugins/apm/public/services/rest/ml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import { npStart } from 'ui/new_platform';
import { ESFilter } from 'elasticsearch';
import { HttpServiceBase } from 'kibana/public';
import {
PROCESSOR_EVENT,
Expand All @@ -14,6 +13,7 @@ import {
} from '../../../common/elasticsearch_fieldnames';
import { getMlJobId, getMlPrefix } from '../../../common/ml_job_constants';
import { callApi } from './callApi';
import { ESFilter } from '../../../typings/elasticsearch';

interface MlResponseItem {
id: string;
Expand Down
2 changes: 1 addition & 1 deletion x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import { Moment } from 'moment-timezone';
import React from 'react';
import { render, waitForElement } from 'react-testing-library';
import { MemoryRouter } from 'react-router-dom';
import { ESFilter } from 'elasticsearch';
import { LocationProvider } from '../context/LocationContext';
import { PromiseReturnType } from '../../typings/common';
import { ESFilter } from '../../typings/elasticsearch';

export function toJson(wrapper: ReactWrapper) {
return enzymeToJson(wrapper, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ESFilter } from 'elasticsearch';
import { idx } from '@kbn/elastic-idx';
import { ESFilter } from '../../../../typings/elasticsearch';
import {
ERROR_GROUP_ID,
PROCESSOR_EVENT,
Expand Down
22 changes: 13 additions & 9 deletions x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { APMError } from '../../../typings/es_schemas/ui/APMError';
import { Setup } from '../helpers/setup_request';
import { getErrorGroupsProjection } from '../../../common/projections/errors';
import { mergeProjection } from '../../../common/projections/util/merge_projection';
import { SortOptions } from '../../../typings/elasticsearch/aggregations';

export type ErrorGroupListAPIResponse = PromiseReturnType<
typeof getErrorGroups
Expand All @@ -30,7 +31,7 @@ export async function getErrorGroups({
}: {
serviceName: string;
sortField?: string;
sortDirection?: string;
sortDirection?: 'asc' | 'desc';
setup: Setup;
}) {
const { client } = setup;
Expand All @@ -40,18 +41,21 @@ export async function getErrorGroups({

const projection = getErrorGroupsProjection({ setup, serviceName });

const order: SortOptions = sortByLatestOccurrence
? {
max_timestamp: sortDirection
}
: { _count: sortDirection };

const params = mergeProjection(projection, {
body: {
size: 0,
aggs: {
error_groups: {
terms: {
...projection.body.aggs.error_groups.terms,
size: 500,
order: sortByLatestOccurrence
? {
max_timestamp: sortDirection
}
: { _count: sortDirection }
order
},
aggs: {
sample: {
Expand All @@ -64,7 +68,7 @@ export async function getErrorGroups({
ERROR_GROUP_ID,
'@timestamp'
],
sort: [{ '@timestamp': 'desc' }],
sort: [{ '@timestamp': 'desc' as const }],
size: 1
}
},
Expand Down Expand Up @@ -98,13 +102,13 @@ export async function getErrorGroups({
};
}

const resp = await client.search(params);
const resp = await client.search<SampleError, typeof params>(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.
const hits = (idx(resp, _ => _.aggregations.error_groups.buckets) || []).map(
bucket => {
const source = bucket.sample.hits.hits[0]._source as SampleError;
const source = bucket.sample.hits.hits[0]._source;
const message =
idx(source, _ => _.error.log.message) ||
idx(source, _ => _.error.exception[0].message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ESFilter } from 'elasticsearch';
import { getEnvironmentUiFilterES } from '../get_environment_ui_filter_es';
import { ENVIRONMENT_NOT_DEFINED } from '../../../../../common/environment_filter_values';
import { SERVICE_ENVIRONMENT } from '../../../../../common/elasticsearch_fieldnames';
import { ESFilter } from '../../../../../typings/elasticsearch';

describe('getEnvironmentUiFilterES', () => {
it('should return undefined, when environment is undefined', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ESFilter } from 'elasticsearch';
import { ESFilter } from '../../../../typings/elasticsearch';
import { ENVIRONMENT_NOT_DEFINED } from '../../../../common/environment_filter_values';
import { SERVICE_ENVIRONMENT } from '../../../../common/elasticsearch_fieldnames';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ESFilter } from 'elasticsearch';
import { Server } from 'hapi';
import { idx } from '@kbn/elastic-idx';
import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query';
import { ESFilter } from '../../../../typings/elasticsearch';
import { ISavedObject } from '../../../../public/services/rest/savedObjects';
import { StaticIndexPattern } from '../../../../../../../../src/legacy/core_plugins/data/public';
import { getAPMIndexPattern } from '../../../lib/index_pattern';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { Server } from 'hapi';
import { ESFilter } from 'elasticsearch';
import { ESFilter } from '../../../../typings/elasticsearch';
import { UIFilters } from '../../../../typings/ui-filters';
import { getEnvironmentUiFilterES } from './get_environment_ui_filter_es';
import { getKueryUiFilterES } from './get_kuery_ui_filter_es';
Expand Down
20 changes: 12 additions & 8 deletions x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import {
SearchParams,
IndexDocumentParams,
IndicesDeleteParams,
IndicesCreateParams,
AggregationSearchResponseWithTotalHitsAsObject
IndicesCreateParams
} from 'elasticsearch';
import { Legacy } from 'kibana';
import { cloneDeep, has, isString, set } from 'lodash';
import { OBSERVER_VERSION_MAJOR } from '../../../common/elasticsearch_fieldnames';
import { StringMap } from '../../../typings/common';
import {
ESSearchResponse,
ESSearchRequest
} from '../../../typings/elasticsearch';

// `type` was deprecated in 7.0
export type APMIndexDocumentParams<T> = Omit<IndexDocumentParams<T>, 'type'>;
Expand Down Expand Up @@ -92,10 +95,13 @@ export function getESClient(req: Legacy.Request) {
const query = req.query as StringMap;

return {
search: async <Hits = unknown, U extends SearchParams = {}>(
params: U,
search: async <
TDocument = unknown,
TSearchRequest extends ESSearchRequest = {}
>(
params: TSearchRequest,
apmOptions?: APMOptions
): Promise<AggregationSearchResponseWithTotalHitsAsObject<Hits, U>> => {
): Promise<ESSearchResponse<TDocument, TSearchRequest>> => {
const nextParams = await getParamsForSearchRequest(
req,
params,
Expand All @@ -117,9 +123,7 @@ export function getESClient(req: Legacy.Request) {
req,
'search',
nextParams
) as unknown) as Promise<
AggregationSearchResponseWithTotalHitsAsObject<Hits, U>
>;
) as unknown) as Promise<ESSearchResponse<TDocument, TSearchRequest>>;
},
index: <Body>(params: APMIndexDocumentParams<Body>) => {
return cluster.callWithRequest(req, 'index', params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('setupRequest', () => {
it('should call callWithRequest with default args', async () => {
const { mockRequest, callWithRequestSpy } = getMockRequest();
const { client } = await setupRequest(mockRequest);
await client.search({ index: 'apm-*', body: { foo: 'bar' } });
await client.search({ index: 'apm-*', body: { foo: 'bar' } } as any);
expect(callWithRequestSpy).toHaveBeenCalledWith(mockRequest, 'search', {
index: 'apm-*',
body: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export async function fetchAndTransformGcMetrics({
}

const series = aggregations.per_pool.buckets.map((poolBucket, i) => {
const label = poolBucket.key;
const label = poolBucket.key as string;
const timeseriesData = poolBucket.over_time;

const data = (idx(timeseriesData, _ => _.buckets) || []).map(bucket => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { Unionize } from 'utility-types';
import { Setup } from '../helpers/setup_request';
import { getMetricsDateHistogramParams } from '../helpers/metrics';
import { ChartBase } from './types';
import { transformDataToMetricsChart } from './transform_metrics_chart';
import { getMetricsProjection } from '../../../common/projections/metrics';
import { mergeProjection } from '../../../common/projections/util/merge_projection';
import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations';

interface Aggs {
[key: string]: {
min?: any;
max?: any;
sum?: any;
avg?: any;
};
[key: string]: Unionize<{
min: AggregationOptionsByType['min'];
max: AggregationOptionsByType['max'];
sum: AggregationOptionsByType['sum'];
avg: AggregationOptionsByType['avg'];
}>;
}

interface Filter {
Expand Down
Loading