Skip to content

Commit

Permalink
unit tests for fetch functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
walterra committed Jul 1, 2021
1 parent 700bd03 commit 2642aab
Show file tree
Hide file tree
Showing 10 changed files with 513 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,34 @@
* 2.0.
*/

import type { estypes } from '@elastic/elasticsearch';

import type { ElasticsearchClient } from 'src/core/server';

import {
fetchTransactionDurationCorrelation,
getTransactionDurationCorrelationRequest,
BucketCorrelation,
} from './query_correlation';

const params = { index: 'apm-*' };
const expectations = [1, 3, 5];
const ranges = [{ to: 1 }, { from: 1, to: 3 }, { from: 3, to: 5 }, { from: 5 }];
const fractions = [1, 2, 4, 5];
const totalDocCount = 1234;

describe('query_correlation', () => {
describe('getTransactionDurationCorrelationRequest()', () => {
it('applies options to the returned query with aggregations for correlations and k-test', () => {
const index = 'apm-*';
const expectations = [1, 3, 5];
const ranges = [
{ to: 1 },
{ from: 1, to: 3 },
{ from: 3, to: 5 },
{ from: 5 },
];
const fractions = [1, 2, 4, 5];
const totalDocCount = 1234;

const query = getTransactionDurationCorrelationRequest(
{ index },
params,
expectations,
ranges,
fractions,
totalDocCount
);

expect(query.index).toBe(index);
expect(query.index).toBe(params.index);

expect(query?.body?.aggs?.latency_ranges?.range?.field).toBe(
'transaction.duration.us'
Expand All @@ -54,4 +54,50 @@ describe('query_correlation', () => {
).toEqual(fractions);
});
});

describe('fetchTransactionDurationCorrelation()', () => {
it('returns the data from the aggregations', async () => {
const latencyRangesBuckets = [{ to: 1 }, { from: 1, to: 2 }, { from: 2 }];
const transactionDurationCorrelationValue = 0.45;
const KsTestLess = 0.01;

const esClientSearchMock = jest.fn((req: estypes.SearchRequest): {
body: estypes.SearchResponse;
} => {
return {
body: ({
aggregations: {
latency_ranges: {
buckets: latencyRangesBuckets,
},
transaction_duration_correlation: {
value: transactionDurationCorrelationValue,
},
ks_test: { less: KsTestLess },
},
} as unknown) as estypes.SearchResponse,
};
});

const esClientMock = ({
search: esClientSearchMock,
} as unknown) as ElasticsearchClient;

const resp = await fetchTransactionDurationCorrelation(
esClientMock,
params,
expectations,
ranges,
fractions,
totalDocCount
);

expect(resp).toEqual({
correlation: transactionDurationCorrelationValue,
ksTest: KsTestLess,
ranges: latencyRangesBuckets,
});
expect(esClientSearchMock).toHaveBeenCalledTimes(1);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
* 2.0.
*/

import type { estypes } from '@elastic/elasticsearch';

import type { ElasticsearchClient } from 'src/core/server';

import {
fetchTransactionDurationFieldCandidates,
getRandomDocsRequest,
hasPrefixToInclude,
shouldBeExcluded,
} from './query_field_candidates';

const params = { index: 'apm-*' };

describe('query_field_candidates', () => {
describe('shouldBeExcluded()', () => {
it('does not exclude a completely custom field name', () => {
Expand Down Expand Up @@ -38,7 +45,7 @@ describe('query_field_candidates', () => {

describe('getRandomDocsRequest()', () => {
it('returns the most basic request body for a sample of random documents', () => {
const req = getRandomDocsRequest({ index: 'apm-*' });
const req = getRandomDocsRequest(params);

expect(req).toEqual({
body: {
Expand All @@ -63,8 +70,81 @@ describe('query_field_candidates', () => {
size: 1000,
track_total_hits: true,
},
index: 'apm-*',
index: params.index,
});
});
});

describe('fetchTransactionDurationFieldCandidates()', () => {
it('returns field candidates and total hits', async () => {
const totalHits = 1234;

const esClientFieldCapsMock = jest.fn(() => ({
body: {
fields: {
myIpFieldName: { ip: {} },
myKeywordFieldName: { keyword: {} },
myUnpopulatedKeywordFieldName: { keyword: {} },
myNumericFieldName: { number: {} },
},
},
}));
const esClientSearchMock = jest.fn((req: estypes.SearchRequest): {
body: estypes.SearchResponse;
} => {
return {
body: ({
hits: {
hits: [
{
fields: {
myIpFieldName: '1.1.1.1',
myKeywordFieldName: 'myKeywordFieldValue',
myNumericFieldName: 1234,
},
},
],
total: { value: totalHits },
},
} as unknown) as estypes.SearchResponse,
};
});

const esClientMock = ({
fieldCaps: esClientFieldCapsMock,
search: esClientSearchMock,
} as unknown) as ElasticsearchClient;

const resp = await fetchTransactionDurationFieldCandidates(
esClientMock,
params
);

expect(resp).toEqual({
fieldCandidates: [
// default field candidates
'service.version',
'service.node.name',
'service.framework.version',
'service.language.version',
'service.runtime.version',
'kubernetes.pod.name',
'kubernetes.pod.uid',
'container.id',
'source.ip',
'client.ip',
'host.ip',
'service.environment',
'process.args',
'http.response.status_code',
// field candidates identified by sample documents
'myIpFieldName',
'myKeywordFieldName',
],
totalHits,
});
expect(esClientFieldCapsMock).toHaveBeenCalledTimes(1);
expect(esClientSearchMock).toHaveBeenCalledTimes(1);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,74 @@
* 2.0.
*/

import { getTermsAggRequest } from './query_field_value_pairs';
import type { estypes } from '@elastic/elasticsearch';

import type { ElasticsearchClient } from 'src/core/server';

import type { AsyncSearchProviderProgress } from '../../../../common/search_strategies/correlations/types';

import {
fetchTransactionDurationFieldValuePairs,
getTermsAggRequest,
} from './query_field_value_pairs';

const params = { index: 'apm-*' };

describe('query_field_value_pairs', () => {
describe('getTermsAggRequest()', () => {
it('returns the most basic request body for a terms aggregation', () => {
const req = getTermsAggRequest({ index: 'apm-*' }, 'myFieldName');
expect(req?.body?.aggs?.attribute_terms?.terms?.field).toBe(
'myFieldName'
const fieldName = 'myFieldName';
const req = getTermsAggRequest(params, fieldName);
expect(req?.body?.aggs?.attribute_terms?.terms?.field).toBe(fieldName);
});
});

describe('fetchTransactionDurationFieldValuePairs()', () => {
it('returns field/value pairs for field candidates', async () => {
const fieldCandidates = [
'myFieldCandidate1',
'myFieldCandidate2',
'myFieldCandidate3',
];
const progress = {
loadedFieldValuePairs: 0,
} as AsyncSearchProviderProgress;

const esClientSearchMock = jest.fn((req: estypes.SearchRequest): {
body: estypes.SearchResponse;
} => {
return {
body: ({
aggregations: {
attribute_terms: {
buckets: [{ key: 'myValue1' }, { key: 'myValue2' }],
},
},
} as unknown) as estypes.SearchResponse,
};
});

const esClientMock = ({
search: esClientSearchMock,
} as unknown) as ElasticsearchClient;

const resp = await fetchTransactionDurationFieldValuePairs(
esClientMock,
params,
fieldCandidates,
progress
);

expect(progress.loadedFieldValuePairs).toBe(1);
expect(resp).toEqual([
{ field: 'myFieldCandidate1', value: 'myValue1' },
{ field: 'myFieldCandidate1', value: 'myValue2' },
{ field: 'myFieldCandidate2', value: 'myValue1' },
{ field: 'myFieldCandidate2', value: 'myValue2' },
{ field: 'myFieldCandidate3', value: 'myValue1' },
{ field: 'myFieldCandidate3', value: 'myValue2' },
]);
expect(esClientSearchMock).toHaveBeenCalledTimes(3);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const fetchTransactionDurationFieldValuePairs = async (
): Promise<FieldValuePairs> => {
const fieldValuePairs: FieldValuePairs = [];

let fieldValuePairsProgress = 0;
let fieldValuePairsProgress = 1;

for (let i = 0; i < fieldCandidates.length; i++) {
const fieldName = fieldCandidates[i];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,61 @@
* 2.0.
*/

import { getTransactionDurationRangesRequest } from './query_fractions';
import type { estypes } from '@elastic/elasticsearch';

import type { ElasticsearchClient } from 'src/core/server';

import {
fetchTransactionDurationFractions,
getTransactionDurationRangesRequest,
} from './query_fractions';

const params = { index: 'apm-*' };
const ranges = [{ to: 1 }, { from: 1, to: 3 }, { from: 3, to: 5 }, { from: 5 }];

describe('query_fractions', () => {
describe('getTransactionDurationRangesRequest()', () => {
it('returns the request body for the transaction duration ranges aggregation', () => {
const ranges = [
{ to: 1 },
{ from: 1, to: 3 },
{ from: 3, to: 5 },
{ from: 5 },
];

const req = getTransactionDurationRangesRequest(
{ index: 'apm-*' },
ranges
);
const req = getTransactionDurationRangesRequest(params, ranges);

expect(req?.body?.aggs?.latency_ranges?.range?.field).toBe(
'transaction.duration.us'
);
expect(req?.body?.aggs?.latency_ranges?.range?.ranges).toEqual(ranges);
});
});

describe('fetchTransactionDurationFractions()', () => {
it('computes the actual percentile bucket counts and actual fractions', async () => {
const esClientSearchMock = jest.fn((req: estypes.SearchRequest): {
body: estypes.SearchResponse;
} => {
return {
body: ({
aggregations: {
latency_ranges: {
buckets: [{ doc_count: 1 }, { doc_count: 2 }],
},
},
} as unknown) as estypes.SearchResponse,
};
});

const esClientMock = ({
search: esClientSearchMock,
} as unknown) as ElasticsearchClient;

const resp = await fetchTransactionDurationFractions(
esClientMock,
params,
ranges
);

expect(resp).toEqual({
fractions: [0.3333333333333333, 0.6666666666666666],
totalDocCount: 3,
});
expect(esClientSearchMock).toHaveBeenCalledTimes(1);
});
});
});
Loading

0 comments on commit 2642aab

Please sign in to comment.