Skip to content

Commit

Permalink
[APM] Use observer.hostname instead of observer.name
Browse files Browse the repository at this point in the history
`observer.name` is not guaranteed to be set. Using `observer.hostname` _should_ allow us to
approximate the amount of APM Server instances.

Additionally, some of the logic was rewritten to A) reflect updates to APM Server's
implementation, and B) make it more robust by querying a static date range.
  • Loading branch information
dgieselaar committed Aug 27, 2020
1 parent 789b67f commit eceb500
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 189 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x-pack/plugins/apm/common/elasticsearch_fieldnames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const USER_AGENT_NAME = 'user_agent.name';

export const DESTINATION_ADDRESS = 'destination.address';

export const OBSERVER_NAME = 'observer.name';
export const OBSERVER_HOSTNAME = 'observer.hostname';
export const OBSERVER_VERSION_MAJOR = 'observer.version_major';
export const OBSERVER_LISTENING = 'observer.listening';
export const PROCESSOR_EVENT = 'processor.event';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { AGENT_NAME } from '../../../../common/elasticsearch_fieldnames';
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
import { tasks } from './tasks';

Expand All @@ -21,100 +20,76 @@ describe('data telemetry collection tasks', () => {
describe('aggregated_transactions', () => {
const task = tasks.find((t) => t.name === 'aggregated_transactions');

it('returns aggregated transaction counts', async () => {
// This mock implementation returns different values based on the parameters,
// which should simulate all the queries that are done. For most of them we'll
// simulate the number of buckets by using the length of the key, but for a
// couple we'll simulate being paginated by returning an after_key.
const search = jest.fn().mockImplementation((params) => {
const isRumResult =
params.body.query.bool.filter &&
params.body.query.bool.filter.some(
(filter: any) =>
filter.terms && filter.terms[AGENT_NAME]?.includes('rum-js')
);
const isNonRumResult =
params.body.query.bool.filter &&
params.body.query.bool.filter.some(
(filter: any) =>
filter.terms && !filter.terms[AGENT_NAME]?.includes('rum-js')
);
const isPagedResult =
!!params.body.aggs?.current_implementation?.composite.after ||
!!params.body.aggs?.no_observer_name?.composite.after;
const isTotalResult = 'track_total_hits' in params.body;
const key = Object.keys(params.body.aggs ?? [])[0];

if (isRumResult) {
if (isTotalResult) {
return Promise.resolve({ hits: { total: { value: 3000 } } });
}
}

if (isNonRumResult) {
if (isTotalResult) {
return Promise.resolve({ hits: { total: { value: 2000 } } });
}
}
describe('without transactions', () => {
it('returns an empty result', async () => {
const search = jest.fn().mockReturnValueOnce({
hits: {
hits: [],
total: {
value: 0,
},
},
});

if (isPagedResult && key) {
return Promise.resolve({
hits: { total: { value: key.length } },
aggregations: { [key]: { buckets: [{}] } },
});
}
expect(await task?.executor({ indices, search } as any)).toEqual({});
});
});

if (isTotalResult) {
return Promise.resolve({ hits: { total: { value: 1000 } } });
}
it('returns aggregated transaction counts', async () => {
const search = jest
.fn()
// The first call to `search` asks for a transaction to get
// a fixed date range.
.mockReturnValueOnce({
hits: {
hits: [{ _source: { '@timestamp': new Date().toISOString() } }],
},
total: {
value: 1,
},
})
// Later calls are all composite aggregations. We return 2 pages of
// results to test if scrolling works.
.mockImplementation((params) => {
let arrayLength = 1000;
let nextAfter: Record<string, any> = { after_key: {} };

if (params.body.aggs.transaction_metric_groups.composite.after) {
arrayLength = 250;
nextAfter = {};
}

if (
key === 'current_implementation' ||
(key === 'no_observer_name' && !isPagedResult)
) {
return Promise.resolve({
hits: { total: { value: key.length } },
aggregations: {
[key]: { after_key: {}, buckets: key.split('').map((_) => ({})) },
hits: {
total: {
value: 5000,
},
},
});
}

if (key) {
return Promise.resolve({
hits: { total: { value: key.length } },
aggregations: {
[key]: { buckets: key.split('').map((_) => ({})) },
transaction_metric_groups: {
buckets: new Array(arrayLength),
...nextAfter,
},
},
});
}
});
});

expect(await task?.executor({ indices, search } as any)).toEqual({
aggregated_transactions: {
current_implementation: {
expected_metric_document_count: 23,
transaction_count: 1000,
expected_metric_document_count: 1250,
transaction_count: 5000,
ratio: 0.25,
},
no_observer_name: {
expected_metric_document_count: 17,
transaction_count: 1000,
},
no_rum: {
expected_metric_document_count: 6,
transaction_count: 2000,
},
no_rum_no_observer_name: {
expected_metric_document_count: 23,
transaction_count: 2000,
},
only_rum: {
expected_metric_document_count: 8,
transaction_count: 3000,
expected_metric_document_count: 1250,
transaction_count: 5000,
ratio: 0.25,
},
only_rum_no_observer_name: {
expected_metric_document_count: 25,
transaction_count: 3000,
with_country: {
expected_metric_document_count: 1250,
transaction_count: 5000,
ratio: 0.25,
},
},
});
Expand Down
Loading

0 comments on commit eceb500

Please sign in to comment.