Skip to content

Commit bc6eaae

Browse files
Merge branch 'master' into search-remove-popup
2 parents 25d5e37 + d89e6d3 commit bc6eaae

File tree

57 files changed

+134454
-144
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+134454
-144
lines changed

src/plugins/kibana_usage_collection/server/collectors/ui_metric/index.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ describe('telemetry_ui_metric', () => {
7373
{ id: 'testAppName:testKeyName1', attributes: { count: 3 } },
7474
{ id: 'testAppName:testKeyName2', attributes: { count: 5 } },
7575
{ id: 'testAppName2:testKeyName3', attributes: { count: 1 } },
76+
{
77+
id:
78+
'kibana-user_agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0',
79+
attributes: { count: 1 },
80+
},
7681
],
7782
total: 3,
7883
} as any;
@@ -86,6 +91,12 @@ describe('telemetry_ui_metric', () => {
8691
{ key: 'testKeyName2', value: 5 },
8792
],
8893
testAppName2: [{ key: 'testKeyName3', value: 1 }],
94+
'kibana-user_agent': [
95+
{
96+
key: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0',
97+
value: 1,
98+
},
99+
],
89100
});
90101
});
91102
});

src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ export function registerUiMetricUsageCollector(
6666
attributes: { count },
6767
} = rawUiMetric;
6868

69-
const [appName, metricType] = id.split(':');
69+
const [appName, ...metricType] = id.split(':');
7070

71-
const pair = { key: metricType, value: count };
71+
const pair = { key: metricType.join(':'), value: count };
7272
return {
7373
...accum,
7474
[appName]: [...(accum[appName] || []), pair],

x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugins/apm/common/elasticsearch_fieldnames.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export const POD_NAME = 'kubernetes.pod.name';
9797
export const CLIENT_GEO_COUNTRY_ISO_CODE = 'client.geo.country_iso_code';
9898

9999
// RUM Labels
100-
export const TRANSACTION_URL = 'transaction.page.url';
100+
export const TRANSACTION_URL = 'url.full';
101101
export const CLIENT_GEO = 'client.geo';
102102
export const USER_AGENT_DEVICE = 'user_agent.device.name';
103103
export const USER_AGENT_OS = 'user_agent.os.name';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
### Updating functional tests archives
2+
3+
Some of our API tests use an archive generated by the [`esarchiver`](https://www.elastic.co/guide/en/kibana/current/development-functional-tests.html) script. Updating the main archive (`apm_8.0.0`) is a scripted process, where a 30m snapshot is downloaded from a cluster running the [APM Integration Testing server](https://github.com/elastic/apm-integration-testing). The script will copy the generated archives into the `fixtures/es_archiver` folders of our test suites (currently `basic` and `trial`). It will also generate a file that contains metadata about the archive, that can be imported to get the time range of the snapshot.
4+
5+
Usage:
6+
`node x-pack/plugins/apm/scripts/create-functional-tests-archive --es-url=https://admin:changeme@localhost:9200 --kibana-url=https://localhost:5601`
7+
8+

x-pack/plugins/apm/scripts/aggregate-latency-metrics/index.ts

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import { Client } from '@elastic/elasticsearch';
87
import { argv } from 'yargs';
98
import pLimit from 'p-limit';
109
import pRetry from 'p-retry';
11-
import { parse, format } from 'url';
1210
import { set } from '@elastic/safer-lodash-set';
1311
import { uniq, without, merge, flatten } from 'lodash';
1412
import * as histogram from 'hdr-histogram-js';
15-
import { ESSearchResponse } from '../../typings/elasticsearch';
1613
import {
1714
HOST_NAME,
1815
SERVICE_NAME,
@@ -28,6 +25,8 @@ import {
2825
} from '../../common/elasticsearch_fieldnames';
2926
import { stampLogger } from '../shared/stamp-logger';
3027
import { createOrUpdateIndex } from '../shared/create-or-update-index';
28+
import { parseIndexUrl } from '../shared/parse_index_url';
29+
import { ESClient, getEsClient } from '../shared/get_es_client';
3130

3231
// This script will try to estimate how many latency metric documents
3332
// will be created based on the available transaction documents.
@@ -125,41 +124,18 @@ export async function aggregateLatencyMetrics() {
125124
const source = String(argv.source ?? '');
126125
const dest = String(argv.dest ?? '');
127126

128-
function getClientOptionsFromIndexUrl(
129-
url: string
130-
): { node: string; index: string } {
131-
const parsed = parse(url);
132-
const { pathname, ...rest } = parsed;
127+
const sourceOptions = parseIndexUrl(source);
133128

134-
return {
135-
node: format(rest),
136-
index: pathname!.replace('/', ''),
137-
};
138-
}
139-
140-
const sourceOptions = getClientOptionsFromIndexUrl(source);
141-
142-
const sourceClient = new Client({
143-
node: sourceOptions.node,
144-
ssl: {
145-
rejectUnauthorized: false,
146-
},
147-
requestTimeout: 120000,
148-
});
129+
const sourceClient = getEsClient({ node: sourceOptions.node });
149130

150-
let destClient: Client | undefined;
131+
let destClient: ESClient | undefined;
151132
let destOptions: { node: string; index: string } | undefined;
152133

153134
const uploadMetrics = !!dest;
154135

155136
if (uploadMetrics) {
156-
destOptions = getClientOptionsFromIndexUrl(dest);
157-
destClient = new Client({
158-
node: destOptions.node,
159-
ssl: {
160-
rejectUnauthorized: false,
161-
},
162-
});
137+
destOptions = parseIndexUrl(dest);
138+
destClient = getEsClient({ node: destOptions.node });
163139

164140
const mappings = (
165141
await sourceClient.indices.getMapping({
@@ -298,10 +274,9 @@ export async function aggregateLatencyMetrics() {
298274
},
299275
};
300276

301-
const response = (await sourceClient.search(params))
302-
.body as ESSearchResponse<unknown, typeof params>;
277+
const response = await sourceClient.search(params);
303278

304-
const { aggregations } = response;
279+
const { aggregations } = response.body;
305280

306281
if (!aggregations) {
307282
return buckets;
@@ -333,10 +308,9 @@ export async function aggregateLatencyMetrics() {
333308
},
334309
};
335310

336-
const response = (await sourceClient.search(params))
337-
.body as ESSearchResponse<unknown, typeof params>;
311+
const response = await sourceClient.search(params);
338312

339-
return response.hits.total.value;
313+
return response.body.hits.total.value;
340314
}
341315

342316
const [buckets, numberOfTransactionDocuments] = await Promise.all([
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
// compile typescript on the fly
8+
// eslint-disable-next-line import/no-extraneous-dependencies
9+
require('@babel/register')({
10+
extensions: ['.js', '.ts'],
11+
plugins: ['@babel/plugin-proposal-optional-chaining'],
12+
presets: [
13+
'@babel/typescript',
14+
['@babel/preset-env', { targets: { node: 'current' } }],
15+
],
16+
});
17+
18+
require('./create-functional-tests-archive/index.ts');
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { argv } from 'yargs';
8+
import { execSync } from 'child_process';
9+
import moment from 'moment';
10+
import path from 'path';
11+
import fs from 'fs';
12+
import { stampLogger } from '../shared/stamp-logger';
13+
14+
async function run() {
15+
stampLogger();
16+
17+
const archiveName = 'apm_8.0.0';
18+
19+
// include important APM data and ML data
20+
const indices =
21+
'apm-*-transaction,apm-*-span,apm-*-error,apm-*-metric,.ml-anomalies*,.ml-config';
22+
23+
const esUrl = argv['es-url'] as string | undefined;
24+
25+
if (!esUrl) {
26+
throw new Error('--es-url is not set');
27+
}
28+
const kibanaUrl = argv['kibana-url'] as string | undefined;
29+
30+
if (!kibanaUrl) {
31+
throw new Error('--kibana-url is not set');
32+
}
33+
const gte = moment().subtract(1, 'hour').toISOString();
34+
const lt = moment(gte).add(30, 'minutes').toISOString();
35+
36+
// eslint-disable-next-line no-console
37+
console.log(`Archiving from ${gte} to ${lt}...`);
38+
39+
// APM data uses '@timestamp' (ECS), ML data uses 'timestamp'
40+
41+
const rangeQueries = [
42+
{
43+
range: {
44+
'@timestamp': {
45+
gte,
46+
lt,
47+
},
48+
},
49+
},
50+
{
51+
range: {
52+
timestamp: {
53+
gte,
54+
lt,
55+
},
56+
},
57+
},
58+
];
59+
60+
// some of the data is timeless/content
61+
const query = {
62+
bool: {
63+
should: [
64+
...rangeQueries,
65+
{
66+
bool: {
67+
must_not: [
68+
{
69+
exists: {
70+
field: '@timestamp',
71+
},
72+
},
73+
{
74+
exists: {
75+
field: 'timestamp',
76+
},
77+
},
78+
],
79+
},
80+
},
81+
],
82+
minimum_should_match: 1,
83+
},
84+
};
85+
86+
const archivesDir = path.join(__dirname, '.archives');
87+
const root = path.join(__dirname, '../../../../..');
88+
89+
// create the archive
90+
91+
execSync(
92+
`node scripts/es_archiver save ${archiveName} ${indices} --dir=${archivesDir} --kibana-url=${kibanaUrl} --es-url=${esUrl} --query='${JSON.stringify(
93+
query
94+
)}'`,
95+
{
96+
cwd: root,
97+
stdio: 'inherit',
98+
}
99+
);
100+
101+
const targetDirs = ['trial', 'basic'];
102+
103+
// copy the archives to the test fixtures
104+
105+
await Promise.all(
106+
targetDirs.map(async (target) => {
107+
const targetPath = path.resolve(
108+
__dirname,
109+
'../../../../test/apm_api_integration/',
110+
target
111+
);
112+
const targetArchivesPath = path.resolve(
113+
targetPath,
114+
'fixtures/es_archiver',
115+
archiveName
116+
);
117+
118+
if (!fs.existsSync(targetArchivesPath)) {
119+
fs.mkdirSync(targetArchivesPath);
120+
}
121+
122+
fs.copyFileSync(
123+
path.join(archivesDir, archiveName, 'data.json.gz'),
124+
path.join(targetArchivesPath, 'data.json.gz')
125+
);
126+
fs.copyFileSync(
127+
path.join(archivesDir, archiveName, 'mappings.json'),
128+
path.join(targetArchivesPath, 'mappings.json')
129+
);
130+
131+
const currentConfig = {};
132+
133+
// get the current metadata and extend/override metadata for the new archive
134+
const configFilePath = path.join(targetPath, 'archives_metadata.ts');
135+
136+
try {
137+
Object.assign(currentConfig, (await import(configFilePath)).default);
138+
} catch (error) {
139+
// do nothing
140+
}
141+
142+
const newConfig = {
143+
...currentConfig,
144+
[archiveName]: {
145+
start: gte,
146+
end: lt,
147+
},
148+
};
149+
150+
fs.writeFileSync(
151+
configFilePath,
152+
`export default ${JSON.stringify(newConfig, null, 2)}`,
153+
{ encoding: 'utf-8' }
154+
);
155+
})
156+
);
157+
158+
fs.unlinkSync(path.join(archivesDir, archiveName, 'data.json.gz'));
159+
fs.unlinkSync(path.join(archivesDir, archiveName, 'mappings.json'));
160+
fs.rmdirSync(path.join(archivesDir, archiveName));
161+
fs.rmdirSync(archivesDir);
162+
163+
// run ESLint on the generated metadata files
164+
165+
execSync('node scripts/eslint **/*/archives_metadata.ts --fix', {
166+
cwd: root,
167+
stdio: 'inherit',
168+
});
169+
}
170+
171+
run()
172+
.then(() => {
173+
process.exit(0);
174+
})
175+
.catch((err) => {
176+
// eslint-disable-next-line no-console
177+
console.log(err);
178+
process.exit(1);
179+
});

x-pack/plugins/apm/scripts/shared/create-or-update-index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import { Client } from '@elastic/elasticsearch';
7+
import { ESClient } from './get_es_client';
88

99
export async function createOrUpdateIndex({
1010
client,
1111
clear,
1212
indexName,
1313
template,
1414
}: {
15-
client: Client;
15+
client: ESClient;
1616
clear: boolean;
1717
indexName: string;
1818
template: any;

0 commit comments

Comments
 (0)