Revert "[APM] Collect telemetry about data/API performance (#51612)"
This reverts commit 13baa51561
.
This commit is contained in:
parent
35b222a840
commit
6de7f2a62b
|
@ -36,8 +36,6 @@ const IGNORE_FILE_GLOBS = [
|
||||||
'**/*fixtures*/**/*',
|
'**/*fixtures*/**/*',
|
||||||
// cypress isn't used in production, ignore it
|
// cypress isn't used in production, ignore it
|
||||||
'x-pack/legacy/plugins/apm/e2e/*',
|
'x-pack/legacy/plugins/apm/e2e/*',
|
||||||
// apm scripts aren't used in production, ignore them
|
|
||||||
'x-pack/legacy/plugins/apm/scripts/*',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
run(async ({ log }) => {
|
run(async ({ log }) => {
|
||||||
|
|
|
@ -14,13 +14,7 @@ import mappings from './mappings.json';
|
||||||
|
|
||||||
export const apm: LegacyPluginInitializer = kibana => {
|
export const apm: LegacyPluginInitializer = kibana => {
|
||||||
return new kibana.Plugin({
|
return new kibana.Plugin({
|
||||||
require: [
|
require: ['kibana', 'elasticsearch', 'xpack_main', 'apm_oss'],
|
||||||
'kibana',
|
|
||||||
'elasticsearch',
|
|
||||||
'xpack_main',
|
|
||||||
'apm_oss',
|
|
||||||
'task_manager'
|
|
||||||
],
|
|
||||||
id: 'apm',
|
id: 'apm',
|
||||||
configPrefix: 'xpack.apm',
|
configPrefix: 'xpack.apm',
|
||||||
publicDir: resolve(__dirname, 'public'),
|
publicDir: resolve(__dirname, 'public'),
|
||||||
|
@ -77,10 +71,7 @@ export const apm: LegacyPluginInitializer = kibana => {
|
||||||
autocreateApmIndexPattern: Joi.boolean().default(true),
|
autocreateApmIndexPattern: Joi.boolean().default(true),
|
||||||
|
|
||||||
// service map
|
// service map
|
||||||
serviceMapEnabled: Joi.boolean().default(true),
|
serviceMapEnabled: Joi.boolean().default(true)
|
||||||
|
|
||||||
// telemetry
|
|
||||||
telemetryCollectionEnabled: Joi.boolean().default(true)
|
|
||||||
}).default();
|
}).default();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -116,12 +107,10 @@ export const apm: LegacyPluginInitializer = kibana => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const apmPlugin = server.newPlatform.setup.plugins
|
const apmPlugin = server.newPlatform.setup.plugins
|
||||||
.apm as APMPluginContract;
|
.apm as APMPluginContract;
|
||||||
|
apmPlugin.registerLegacyAPI({ server });
|
||||||
apmPlugin.registerLegacyAPI({
|
|
||||||
server
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,655 +1,12 @@
|
||||||
{
|
{
|
||||||
"apm-telemetry": {
|
"apm-services-telemetry": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"agents": {
|
|
||||||
"properties": {
|
|
||||||
"dotnet": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"go": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"java": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"js-base": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"type": "object"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nodejs": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"python": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ruby": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"properties": {
|
|
||||||
"composite": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"type": "keyword",
|
|
||||||
"ignore_above": 256
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rum-js": {
|
|
||||||
"properties": {
|
|
||||||
"agent": {
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
"properties": {
|
|
||||||
"framework": {
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"type": "object"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"counts": {
|
|
||||||
"properties": {
|
|
||||||
"agent_configuration": {
|
|
||||||
"properties": {
|
|
||||||
"all": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"all": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"max_error_groups_per_service": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"max_transaction_groups_per_service": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metric": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"all": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"onboarding": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"all": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"services": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sourcemap": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"all": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"span": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"all": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"traces": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"transaction": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"all": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cardinality": {
|
|
||||||
"properties": {
|
|
||||||
"user_agent": {
|
|
||||||
"properties": {
|
|
||||||
"original": {
|
|
||||||
"properties": {
|
|
||||||
"all_agents": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rum": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"transaction": {
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"properties": {
|
|
||||||
"all_agents": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rum": {
|
|
||||||
"properties": {
|
|
||||||
"1d": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has_any_services": {
|
"has_any_services": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"indices": {
|
|
||||||
"properties": {
|
|
||||||
"all": {
|
|
||||||
"properties": {
|
|
||||||
"total": {
|
|
||||||
"properties": {
|
|
||||||
"docs": {
|
|
||||||
"properties": {
|
|
||||||
"count": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"store": {
|
|
||||||
"properties": {
|
|
||||||
"size_in_bytes": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shards": {
|
|
||||||
"properties": {
|
|
||||||
"total": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"integrations": {
|
|
||||||
"properties": {
|
|
||||||
"ml": {
|
|
||||||
"properties": {
|
|
||||||
"all_jobs_count": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"retainment": {
|
|
||||||
"properties": {
|
|
||||||
"error": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"metric": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"onboarding": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"span": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"transaction": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"services_per_agent": {
|
"services_per_agent": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"dotnet": {
|
"python": {
|
||||||
"type": "long",
|
|
||||||
"null_value": 0
|
|
||||||
},
|
|
||||||
"go": {
|
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"null_value": 0
|
"null_value": 0
|
||||||
},
|
},
|
||||||
|
@ -657,15 +14,19 @@
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"null_value": 0
|
"null_value": 0
|
||||||
},
|
},
|
||||||
"js-base": {
|
|
||||||
"type": "long",
|
|
||||||
"null_value": 0
|
|
||||||
},
|
|
||||||
"nodejs": {
|
"nodejs": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"null_value": 0
|
"null_value": 0
|
||||||
},
|
},
|
||||||
"python": {
|
"js-base": {
|
||||||
|
"type": "long",
|
||||||
|
"null_value": 0
|
||||||
|
},
|
||||||
|
"rum-js": {
|
||||||
|
"type": "long",
|
||||||
|
"null_value": 0
|
||||||
|
},
|
||||||
|
"dotnet": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"null_value": 0
|
"null_value": 0
|
||||||
},
|
},
|
||||||
|
@ -673,131 +34,11 @@
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"null_value": 0
|
"null_value": 0
|
||||||
},
|
},
|
||||||
"rum-js": {
|
"go": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"null_value": 0
|
"null_value": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"tasks": {
|
|
||||||
"properties": {
|
|
||||||
"agent_configuration": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"agents": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cardinality": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"groupings": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indices_stats": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"integrations": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"processor_events": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"services": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"versions": {
|
|
||||||
"properties": {
|
|
||||||
"took": {
|
|
||||||
"properties": {
|
|
||||||
"ms": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"version": {
|
|
||||||
"properties": {
|
|
||||||
"apm_server": {
|
|
||||||
"properties": {
|
|
||||||
"major": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"minor": {
|
|
||||||
"type": "long"
|
|
||||||
},
|
|
||||||
"patch": {
|
|
||||||
"type": "long"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
1
x-pack/legacy/plugins/apm/scripts/.gitignore
vendored
1
x-pack/legacy/plugins/apm/scripts/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
yarn.lock
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"name": "apm-scripts",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "index.js",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@octokit/rest": "^16.35.0",
|
|
||||||
"console-stamp": "^0.2.9"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,7 +16,6 @@
|
||||||
******************************/
|
******************************/
|
||||||
|
|
||||||
// compile typescript on the fly
|
// compile typescript on the fly
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
||||||
require('@babel/register')({
|
require('@babel/register')({
|
||||||
extensions: ['.ts'],
|
extensions: ['.ts'],
|
||||||
plugins: ['@babel/plugin-proposal-optional-chaining'],
|
plugins: ['@babel/plugin-proposal-optional-chaining'],
|
||||||
|
|
|
@ -1,21 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// compile typescript on the fly
|
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
||||||
require('@babel/register')({
|
|
||||||
extensions: ['.ts'],
|
|
||||||
plugins: [
|
|
||||||
'@babel/plugin-proposal-optional-chaining',
|
|
||||||
'@babel/plugin-proposal-nullish-coalescing-operator'
|
|
||||||
],
|
|
||||||
presets: [
|
|
||||||
'@babel/typescript',
|
|
||||||
['@babel/preset-env', { targets: { node: 'current' } }]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
require('./upload-telemetry-data/index.ts');
|
|
|
@ -1,26 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
import { Octokit } from '@octokit/rest';
|
|
||||||
|
|
||||||
export async function downloadTelemetryTemplate(octokit: Octokit) {
|
|
||||||
const file = await octokit.repos.getContents({
|
|
||||||
owner: 'elastic',
|
|
||||||
repo: 'telemetry',
|
|
||||||
path: 'config/templates/xpack-phone-home.json',
|
|
||||||
// @ts-ignore
|
|
||||||
mediaType: {
|
|
||||||
format: 'application/vnd.github.VERSION.raw'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Array.isArray(file.data)) {
|
|
||||||
throw new Error('Expected single response, got array');
|
|
||||||
}
|
|
||||||
|
|
||||||
return JSON.parse(Buffer.from(file.data.content!, 'base64').toString());
|
|
||||||
}
|
|
|
@ -1,124 +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 { DeepPartial } from 'utility-types';
|
|
||||||
import {
|
|
||||||
merge,
|
|
||||||
omit,
|
|
||||||
defaultsDeep,
|
|
||||||
range,
|
|
||||||
mapValues,
|
|
||||||
isPlainObject,
|
|
||||||
flatten
|
|
||||||
} from 'lodash';
|
|
||||||
import uuid from 'uuid';
|
|
||||||
import {
|
|
||||||
CollectTelemetryParams,
|
|
||||||
collectDataTelemetry
|
|
||||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
|
||||||
} from '../../../../../plugins/apm/server/lib/apm_telemetry/collect_data_telemetry';
|
|
||||||
|
|
||||||
interface GenerateOptions {
|
|
||||||
days: number;
|
|
||||||
instances: number;
|
|
||||||
variation: {
|
|
||||||
min: number;
|
|
||||||
max: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const randomize = (
|
|
||||||
value: unknown,
|
|
||||||
instanceVariation: number,
|
|
||||||
dailyGrowth: number
|
|
||||||
) => {
|
|
||||||
if (typeof value === 'boolean') {
|
|
||||||
return Math.random() > 0.5;
|
|
||||||
}
|
|
||||||
if (typeof value === 'number') {
|
|
||||||
return Math.round(instanceVariation * dailyGrowth * value);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapValuesDeep = (
|
|
||||||
obj: Record<string, any>,
|
|
||||||
iterator: (value: unknown, key: string, obj: Record<string, any>) => unknown
|
|
||||||
): Record<string, any> =>
|
|
||||||
mapValues(obj, (val, key) =>
|
|
||||||
isPlainObject(val) ? mapValuesDeep(val, iterator) : iterator(val, key!, obj)
|
|
||||||
);
|
|
||||||
|
|
||||||
export async function generateSampleDocuments(
|
|
||||||
options: DeepPartial<GenerateOptions> & {
|
|
||||||
collectTelemetryParams: CollectTelemetryParams;
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const { collectTelemetryParams, ...preferredOptions } = options;
|
|
||||||
|
|
||||||
const opts: GenerateOptions = defaultsDeep(
|
|
||||||
{
|
|
||||||
days: 100,
|
|
||||||
instances: 50,
|
|
||||||
variation: {
|
|
||||||
min: 0.1,
|
|
||||||
max: 4
|
|
||||||
}
|
|
||||||
},
|
|
||||||
preferredOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
const sample = await collectDataTelemetry(collectTelemetryParams);
|
|
||||||
|
|
||||||
console.log('Collected telemetry'); // eslint-disable-line no-console
|
|
||||||
console.log('\n' + JSON.stringify(sample, null, 2)); // eslint-disable-line no-console
|
|
||||||
|
|
||||||
const dateOfScriptExecution = new Date();
|
|
||||||
|
|
||||||
return flatten(
|
|
||||||
range(0, opts.instances).map(instanceNo => {
|
|
||||||
const instanceId = uuid.v4();
|
|
||||||
const defaults = {
|
|
||||||
cluster_uuid: instanceId,
|
|
||||||
stack_stats: {
|
|
||||||
kibana: {
|
|
||||||
versions: {
|
|
||||||
version: '8.0.0'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const instanceVariation =
|
|
||||||
Math.random() * (opts.variation.max - opts.variation.min) +
|
|
||||||
opts.variation.min;
|
|
||||||
|
|
||||||
return range(0, opts.days).map(dayNo => {
|
|
||||||
const dailyGrowth = Math.pow(1.005, opts.days - 1 - dayNo);
|
|
||||||
|
|
||||||
const timestamp = Date.UTC(
|
|
||||||
dateOfScriptExecution.getFullYear(),
|
|
||||||
dateOfScriptExecution.getMonth(),
|
|
||||||
-dayNo
|
|
||||||
);
|
|
||||||
|
|
||||||
const generated = mapValuesDeep(omit(sample, 'versions'), value =>
|
|
||||||
randomize(value, instanceVariation, dailyGrowth)
|
|
||||||
);
|
|
||||||
|
|
||||||
return merge({}, defaults, {
|
|
||||||
timestamp,
|
|
||||||
stack_stats: {
|
|
||||||
kibana: {
|
|
||||||
plugins: {
|
|
||||||
apm: merge({}, sample, generated)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,208 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This script downloads the telemetry mapping, runs the APM telemetry tasks,
|
|
||||||
// generates a bunch of randomized data based on the downloaded sample,
|
|
||||||
// and uploads it to a cluster of your choosing in the same format as it is
|
|
||||||
// stored in the telemetry cluster. Its purpose is twofold:
|
|
||||||
// - Easier testing of the telemetry tasks
|
|
||||||
// - Validate whether we can run the queries we want to on the telemetry data
|
|
||||||
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
// @ts-ignore
|
|
||||||
import { Octokit } from '@octokit/rest';
|
|
||||||
import { merge, chunk, flatten, pick, identity } from 'lodash';
|
|
||||||
import axios from 'axios';
|
|
||||||
import yaml from 'js-yaml';
|
|
||||||
import { Client } from 'elasticsearch';
|
|
||||||
import { argv } from 'yargs';
|
|
||||||
import { promisify } from 'util';
|
|
||||||
import { Logger } from 'kibana/server';
|
|
||||||
// @ts-ignore
|
|
||||||
import consoleStamp from 'console-stamp';
|
|
||||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
|
||||||
import { CollectTelemetryParams } from '../../../../../plugins/apm/server/lib/apm_telemetry/collect_data_telemetry';
|
|
||||||
import { downloadTelemetryTemplate } from './download-telemetry-template';
|
|
||||||
import mapping from '../../mappings.json';
|
|
||||||
import { generateSampleDocuments } from './generate-sample-documents';
|
|
||||||
|
|
||||||
consoleStamp(console, '[HH:MM:ss.l]');
|
|
||||||
|
|
||||||
const githubToken = process.env.GITHUB_TOKEN;
|
|
||||||
|
|
||||||
if (!githubToken) {
|
|
||||||
throw new Error('GITHUB_TOKEN was not provided.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const kibanaConfigDir = path.join(__filename, '../../../../../../../config');
|
|
||||||
const kibanaDevConfig = path.join(kibanaConfigDir, 'kibana.dev.yml');
|
|
||||||
const kibanaConfig = path.join(kibanaConfigDir, 'kibana.yml');
|
|
||||||
|
|
||||||
const xpackTelemetryIndexName = 'xpack-phone-home';
|
|
||||||
|
|
||||||
const loadedKibanaConfig = (yaml.safeLoad(
|
|
||||||
fs.readFileSync(
|
|
||||||
fs.existsSync(kibanaDevConfig) ? kibanaDevConfig : kibanaConfig,
|
|
||||||
'utf8'
|
|
||||||
)
|
|
||||||
) || {}) as {};
|
|
||||||
|
|
||||||
const cliEsCredentials = pick(
|
|
||||||
{
|
|
||||||
'elasticsearch.username': process.env.ELASTICSEARCH_USERNAME,
|
|
||||||
'elasticsearch.password': process.env.ELASTICSEARCH_PASSWORD,
|
|
||||||
'elasticsearch.hosts': process.env.ELASTICSEARCH_HOST
|
|
||||||
},
|
|
||||||
identity
|
|
||||||
) as {
|
|
||||||
'elasticsearch.username': string;
|
|
||||||
'elasticsearch.password': string;
|
|
||||||
'elasticsearch.hosts': string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
'apm_oss.transactionIndices': 'apm-*',
|
|
||||||
'apm_oss.metricsIndices': 'apm-*',
|
|
||||||
'apm_oss.errorIndices': 'apm-*',
|
|
||||||
'apm_oss.spanIndices': 'apm-*',
|
|
||||||
'apm_oss.onboardingIndices': 'apm-*',
|
|
||||||
'apm_oss.sourcemapIndices': 'apm-*',
|
|
||||||
'elasticsearch.hosts': 'http://localhost:9200',
|
|
||||||
...loadedKibanaConfig,
|
|
||||||
...cliEsCredentials
|
|
||||||
};
|
|
||||||
|
|
||||||
async function uploadData() {
|
|
||||||
const octokit = new Octokit({
|
|
||||||
auth: githubToken
|
|
||||||
});
|
|
||||||
|
|
||||||
const telemetryTemplate = await downloadTelemetryTemplate(octokit);
|
|
||||||
|
|
||||||
const kibanaMapping = mapping['apm-telemetry'];
|
|
||||||
|
|
||||||
const httpAuth =
|
|
||||||
config['elasticsearch.username'] && config['elasticsearch.password']
|
|
||||||
? {
|
|
||||||
username: config['elasticsearch.username'],
|
|
||||||
password: config['elasticsearch.password']
|
|
||||||
}
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const client = new Client({
|
|
||||||
host: config['elasticsearch.hosts'],
|
|
||||||
...(httpAuth
|
|
||||||
? {
|
|
||||||
httpAuth: `${httpAuth.username}:${httpAuth.password}`
|
|
||||||
}
|
|
||||||
: {})
|
|
||||||
});
|
|
||||||
|
|
||||||
if (argv.clear) {
|
|
||||||
try {
|
|
||||||
await promisify(client.indices.delete.bind(client))({
|
|
||||||
index: xpackTelemetryIndexName
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
// 404 = index not found, totally okay
|
|
||||||
if (err.status !== 404) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const axiosInstance = axios.create({
|
|
||||||
baseURL: config['elasticsearch.hosts'],
|
|
||||||
...(httpAuth ? { auth: httpAuth } : {})
|
|
||||||
});
|
|
||||||
|
|
||||||
const newTemplate = merge(telemetryTemplate, {
|
|
||||||
settings: {
|
|
||||||
index: { mapping: { total_fields: { limit: 10000 } } }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// override apm mapping instead of merging
|
|
||||||
newTemplate.mappings.properties.stack_stats.properties.kibana.properties.plugins.properties.apm = kibanaMapping;
|
|
||||||
|
|
||||||
await axiosInstance.put(`/_template/xpack-phone-home`, newTemplate);
|
|
||||||
|
|
||||||
const sampleDocuments = await generateSampleDocuments({
|
|
||||||
collectTelemetryParams: {
|
|
||||||
logger: (console as unknown) as Logger,
|
|
||||||
indices: {
|
|
||||||
...config,
|
|
||||||
apmCustomLinkIndex: '.apm-custom-links',
|
|
||||||
apmAgentConfigurationIndex: '.apm-agent-configuration'
|
|
||||||
},
|
|
||||||
search: body => {
|
|
||||||
return promisify(client.search.bind(client))({
|
|
||||||
...body,
|
|
||||||
requestTimeout: 120000
|
|
||||||
}) as any;
|
|
||||||
},
|
|
||||||
indicesStats: body => {
|
|
||||||
return promisify(client.indices.stats.bind(client))({
|
|
||||||
...body,
|
|
||||||
requestTimeout: 120000
|
|
||||||
}) as any;
|
|
||||||
},
|
|
||||||
transportRequest: (params => {
|
|
||||||
return axiosInstance[params.method](params.path);
|
|
||||||
}) as CollectTelemetryParams['transportRequest']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const chunks = chunk(sampleDocuments, 250);
|
|
||||||
|
|
||||||
await chunks.reduce<Promise<any>>((prev, documents) => {
|
|
||||||
return prev.then(async () => {
|
|
||||||
const body = flatten(
|
|
||||||
documents.map(doc => [{ index: { _index: 'xpack-phone-home' } }, doc])
|
|
||||||
);
|
|
||||||
|
|
||||||
return promisify(client.bulk.bind(client))({
|
|
||||||
body,
|
|
||||||
refresh: true
|
|
||||||
}).then((response: any) => {
|
|
||||||
if (response.errors) {
|
|
||||||
const firstError = response.items.filter(
|
|
||||||
(item: any) => item.index.status >= 400
|
|
||||||
)[0].index.error;
|
|
||||||
throw new Error(`Failed to upload documents: ${firstError.reason} `);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, Promise.resolve());
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadData()
|
|
||||||
.catch(e => {
|
|
||||||
if ('response' in e) {
|
|
||||||
if (typeof e.response === 'string') {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(e.response);
|
|
||||||
} else {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(
|
|
||||||
JSON.stringify(
|
|
||||||
e.response,
|
|
||||||
['status', 'statusText', 'headers', 'data'],
|
|
||||||
2
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
process.exit(1);
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('Finished uploading generated telemetry data');
|
|
||||||
});
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
exports[`Error AGENT_NAME 1`] = `"java"`;
|
exports[`Error AGENT_NAME 1`] = `"java"`;
|
||||||
|
|
||||||
exports[`Error AGENT_VERSION 1`] = `"agent version"`;
|
|
||||||
|
|
||||||
exports[`Error CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`;
|
exports[`Error CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error CONTAINER_ID 1`] = `undefined`;
|
exports[`Error CONTAINER_ID 1`] = `undefined`;
|
||||||
|
@ -58,7 +56,7 @@ exports[`Error METRIC_SYSTEM_TOTAL_MEMORY 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error OBSERVER_LISTENING 1`] = `undefined`;
|
exports[`Error OBSERVER_LISTENING 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error OBSERVER_VERSION_MAJOR 1`] = `8`;
|
exports[`Error OBSERVER_VERSION_MAJOR 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error PARENT_ID 1`] = `"parentId"`;
|
exports[`Error PARENT_ID 1`] = `"parentId"`;
|
||||||
|
|
||||||
|
@ -70,20 +68,10 @@ exports[`Error SERVICE_ENVIRONMENT 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
|
exports[`Error SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error SERVICE_FRAMEWORK_VERSION 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Error SERVICE_LANGUAGE_NAME 1`] = `"nodejs"`;
|
|
||||||
|
|
||||||
exports[`Error SERVICE_LANGUAGE_VERSION 1`] = `"v1337"`;
|
|
||||||
|
|
||||||
exports[`Error SERVICE_NAME 1`] = `"service name"`;
|
exports[`Error SERVICE_NAME 1`] = `"service name"`;
|
||||||
|
|
||||||
exports[`Error SERVICE_NODE_NAME 1`] = `undefined`;
|
exports[`Error SERVICE_NODE_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error SERVICE_RUNTIME_NAME 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Error SERVICE_RUNTIME_VERSION 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Error SERVICE_VERSION 1`] = `undefined`;
|
exports[`Error SERVICE_VERSION 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error SPAN_ACTION 1`] = `undefined`;
|
exports[`Error SPAN_ACTION 1`] = `undefined`;
|
||||||
|
@ -124,14 +112,10 @@ exports[`Error URL_FULL 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error USER_AGENT_NAME 1`] = `undefined`;
|
exports[`Error USER_AGENT_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Error USER_AGENT_ORIGINAL 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Error USER_ID 1`] = `undefined`;
|
exports[`Error USER_ID 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span AGENT_NAME 1`] = `"java"`;
|
exports[`Span AGENT_NAME 1`] = `"java"`;
|
||||||
|
|
||||||
exports[`Span AGENT_VERSION 1`] = `"agent version"`;
|
|
||||||
|
|
||||||
exports[`Span CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`;
|
exports[`Span CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span CONTAINER_ID 1`] = `undefined`;
|
exports[`Span CONTAINER_ID 1`] = `undefined`;
|
||||||
|
@ -186,7 +170,7 @@ exports[`Span METRIC_SYSTEM_TOTAL_MEMORY 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span OBSERVER_LISTENING 1`] = `undefined`;
|
exports[`Span OBSERVER_LISTENING 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span OBSERVER_VERSION_MAJOR 1`] = `8`;
|
exports[`Span OBSERVER_VERSION_MAJOR 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span PARENT_ID 1`] = `"parentId"`;
|
exports[`Span PARENT_ID 1`] = `"parentId"`;
|
||||||
|
|
||||||
|
@ -198,20 +182,10 @@ exports[`Span SERVICE_ENVIRONMENT 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
|
exports[`Span SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span SERVICE_FRAMEWORK_VERSION 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Span SERVICE_LANGUAGE_NAME 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Span SERVICE_LANGUAGE_VERSION 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Span SERVICE_NAME 1`] = `"service name"`;
|
exports[`Span SERVICE_NAME 1`] = `"service name"`;
|
||||||
|
|
||||||
exports[`Span SERVICE_NODE_NAME 1`] = `undefined`;
|
exports[`Span SERVICE_NODE_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span SERVICE_RUNTIME_NAME 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Span SERVICE_RUNTIME_VERSION 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Span SERVICE_VERSION 1`] = `undefined`;
|
exports[`Span SERVICE_VERSION 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span SPAN_ACTION 1`] = `"my action"`;
|
exports[`Span SPAN_ACTION 1`] = `"my action"`;
|
||||||
|
@ -252,14 +226,10 @@ exports[`Span URL_FULL 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span USER_AGENT_NAME 1`] = `undefined`;
|
exports[`Span USER_AGENT_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Span USER_AGENT_ORIGINAL 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Span USER_ID 1`] = `undefined`;
|
exports[`Span USER_ID 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction AGENT_NAME 1`] = `"java"`;
|
exports[`Transaction AGENT_NAME 1`] = `"java"`;
|
||||||
|
|
||||||
exports[`Transaction AGENT_VERSION 1`] = `"agent version"`;
|
|
||||||
|
|
||||||
exports[`Transaction CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`;
|
exports[`Transaction CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction CONTAINER_ID 1`] = `"container1234567890abcdef"`;
|
exports[`Transaction CONTAINER_ID 1`] = `"container1234567890abcdef"`;
|
||||||
|
@ -314,7 +284,7 @@ exports[`Transaction METRIC_SYSTEM_TOTAL_MEMORY 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction OBSERVER_LISTENING 1`] = `undefined`;
|
exports[`Transaction OBSERVER_LISTENING 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction OBSERVER_VERSION_MAJOR 1`] = `8`;
|
exports[`Transaction OBSERVER_VERSION_MAJOR 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction PARENT_ID 1`] = `"parentId"`;
|
exports[`Transaction PARENT_ID 1`] = `"parentId"`;
|
||||||
|
|
||||||
|
@ -326,20 +296,10 @@ exports[`Transaction SERVICE_ENVIRONMENT 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
|
exports[`Transaction SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction SERVICE_FRAMEWORK_VERSION 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Transaction SERVICE_LANGUAGE_NAME 1`] = `"nodejs"`;
|
|
||||||
|
|
||||||
exports[`Transaction SERVICE_LANGUAGE_VERSION 1`] = `"v1337"`;
|
|
||||||
|
|
||||||
exports[`Transaction SERVICE_NAME 1`] = `"service name"`;
|
exports[`Transaction SERVICE_NAME 1`] = `"service name"`;
|
||||||
|
|
||||||
exports[`Transaction SERVICE_NODE_NAME 1`] = `undefined`;
|
exports[`Transaction SERVICE_NODE_NAME 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction SERVICE_RUNTIME_NAME 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Transaction SERVICE_RUNTIME_VERSION 1`] = `undefined`;
|
|
||||||
|
|
||||||
exports[`Transaction SERVICE_VERSION 1`] = `undefined`;
|
exports[`Transaction SERVICE_VERSION 1`] = `undefined`;
|
||||||
|
|
||||||
exports[`Transaction SPAN_ACTION 1`] = `undefined`;
|
exports[`Transaction SPAN_ACTION 1`] = `undefined`;
|
||||||
|
@ -380,6 +340,4 @@ exports[`Transaction URL_FULL 1`] = `"http://www.elastic.co"`;
|
||||||
|
|
||||||
exports[`Transaction USER_AGENT_NAME 1`] = `"Other"`;
|
exports[`Transaction USER_AGENT_NAME 1`] = `"Other"`;
|
||||||
|
|
||||||
exports[`Transaction USER_AGENT_ORIGINAL 1`] = `"test original"`;
|
|
||||||
|
|
||||||
exports[`Transaction USER_ID 1`] = `"1337"`;
|
exports[`Transaction USER_ID 1`] = `"1337"`;
|
||||||
|
|
|
@ -4,40 +4,36 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AgentName } from '../typings/es_schemas/ui/fields/agent';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Agent names can be any string. This list only defines the official agents
|
* Agent names can be any string. This list only defines the official agents
|
||||||
* that we might want to target specifically eg. linking to their documentation
|
* that we might want to target specifically eg. linking to their documentation
|
||||||
* & telemetry reporting. Support additional agent types by appending
|
* & telemetry reporting. Support additional agent types by appending
|
||||||
* definitions in mappings.json (for telemetry), the AgentName type, and the
|
* definitions in mappings.json (for telemetry), the AgentName type, and the
|
||||||
* AGENT_NAMES array.
|
* agentNames object.
|
||||||
*/
|
*/
|
||||||
|
import { AgentName } from '../typings/es_schemas/ui/fields/agent';
|
||||||
|
|
||||||
export const AGENT_NAMES: AgentName[] = [
|
const agentNames: { [agentName in AgentName]: agentName } = {
|
||||||
'java',
|
python: 'python',
|
||||||
'js-base',
|
java: 'java',
|
||||||
'rum-js',
|
nodejs: 'nodejs',
|
||||||
'dotnet',
|
'js-base': 'js-base',
|
||||||
'go',
|
'rum-js': 'rum-js',
|
||||||
'java',
|
dotnet: 'dotnet',
|
||||||
'nodejs',
|
ruby: 'ruby',
|
||||||
'python',
|
go: 'go'
|
||||||
'ruby'
|
};
|
||||||
];
|
|
||||||
|
|
||||||
export function isAgentName(agentName: string): agentName is AgentName {
|
export function isAgentName(agentName: string): boolean {
|
||||||
return AGENT_NAMES.includes(agentName as AgentName);
|
return Object.values(agentNames).includes(agentName as AgentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isRumAgentName(
|
export function isRumAgentName(agentName: string | undefined) {
|
||||||
agentName: string | undefined
|
return (
|
||||||
): agentName is 'js-base' | 'rum-js' {
|
agentName === agentNames['js-base'] || agentName === agentNames['rum-js']
|
||||||
return agentName === 'js-base' || agentName === 'rum-js';
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isJavaAgentName(
|
export function isJavaAgentName(agentName: string | undefined) {
|
||||||
agentName: string | undefined
|
return agentName === agentNames.java;
|
||||||
): agentName is 'java' {
|
|
||||||
return agentName === 'java';
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,11 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// the types have to match the names of the saved object mappings
|
// APM Services telemetry
|
||||||
// in /x-pack/legacy/plugins/apm/mappings.json
|
export const APM_SERVICES_TELEMETRY_SAVED_OBJECT_TYPE =
|
||||||
|
'apm-services-telemetry';
|
||||||
|
export const APM_SERVICES_TELEMETRY_SAVED_OBJECT_ID = 'apm-services-telemetry';
|
||||||
|
|
||||||
// APM indices
|
// APM indices
|
||||||
export const APM_INDICES_SAVED_OBJECT_TYPE = 'apm-indices';
|
export const APM_INDICES_SAVED_OBJECT_TYPE = 'apm-indices';
|
||||||
export const APM_INDICES_SAVED_OBJECT_ID = 'apm-indices';
|
export const APM_INDICES_SAVED_OBJECT_ID = 'apm-indices';
|
||||||
|
|
||||||
// APM telemetry
|
|
||||||
export const APM_TELEMETRY_SAVED_OBJECT_TYPE = 'apm-telemetry';
|
|
||||||
export const APM_TELEMETRY_SAVED_OBJECT_ID = 'apm-telemetry';
|
|
||||||
|
|
|
@ -15,10 +15,7 @@ describe('Transaction', () => {
|
||||||
const transaction: AllowUnknownProperties<Transaction> = {
|
const transaction: AllowUnknownProperties<Transaction> = {
|
||||||
'@timestamp': new Date().toString(),
|
'@timestamp': new Date().toString(),
|
||||||
'@metadata': 'whatever',
|
'@metadata': 'whatever',
|
||||||
observer: {
|
observer: 'whatever',
|
||||||
version: 'whatever',
|
|
||||||
version_major: 8
|
|
||||||
},
|
|
||||||
agent: {
|
agent: {
|
||||||
name: 'java',
|
name: 'java',
|
||||||
version: 'agent version'
|
version: 'agent version'
|
||||||
|
@ -66,10 +63,7 @@ describe('Span', () => {
|
||||||
const span: AllowUnknownProperties<Span> = {
|
const span: AllowUnknownProperties<Span> = {
|
||||||
'@timestamp': new Date().toString(),
|
'@timestamp': new Date().toString(),
|
||||||
'@metadata': 'whatever',
|
'@metadata': 'whatever',
|
||||||
observer: {
|
observer: 'whatever',
|
||||||
version: 'whatever',
|
|
||||||
version_major: 8
|
|
||||||
},
|
|
||||||
agent: {
|
agent: {
|
||||||
name: 'java',
|
name: 'java',
|
||||||
version: 'agent version'
|
version: 'agent version'
|
||||||
|
@ -113,10 +107,7 @@ describe('Span', () => {
|
||||||
describe('Error', () => {
|
describe('Error', () => {
|
||||||
const errorDoc: AllowUnknownProperties<APMError> = {
|
const errorDoc: AllowUnknownProperties<APMError> = {
|
||||||
'@metadata': 'whatever',
|
'@metadata': 'whatever',
|
||||||
observer: {
|
observer: 'whatever',
|
||||||
version: 'whatever',
|
|
||||||
version_major: 8
|
|
||||||
},
|
|
||||||
agent: {
|
agent: {
|
||||||
name: 'java',
|
name: 'java',
|
||||||
version: 'agent version'
|
version: 'agent version'
|
||||||
|
|
|
@ -4,24 +4,15 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const AGENT_NAME = 'agent.name';
|
||||||
export const SERVICE_NAME = 'service.name';
|
export const SERVICE_NAME = 'service.name';
|
||||||
export const SERVICE_ENVIRONMENT = 'service.environment';
|
export const SERVICE_ENVIRONMENT = 'service.environment';
|
||||||
export const SERVICE_FRAMEWORK_NAME = 'service.framework.name';
|
export const SERVICE_FRAMEWORK_NAME = 'service.framework.name';
|
||||||
export const SERVICE_FRAMEWORK_VERSION = 'service.framework.version';
|
|
||||||
export const SERVICE_LANGUAGE_NAME = 'service.language.name';
|
|
||||||
export const SERVICE_LANGUAGE_VERSION = 'service.language.version';
|
|
||||||
export const SERVICE_RUNTIME_NAME = 'service.runtime.name';
|
|
||||||
export const SERVICE_RUNTIME_VERSION = 'service.runtime.version';
|
|
||||||
export const SERVICE_NODE_NAME = 'service.node.name';
|
export const SERVICE_NODE_NAME = 'service.node.name';
|
||||||
export const SERVICE_VERSION = 'service.version';
|
export const SERVICE_VERSION = 'service.version';
|
||||||
|
|
||||||
export const AGENT_NAME = 'agent.name';
|
|
||||||
export const AGENT_VERSION = 'agent.version';
|
|
||||||
|
|
||||||
export const URL_FULL = 'url.full';
|
export const URL_FULL = 'url.full';
|
||||||
export const HTTP_REQUEST_METHOD = 'http.request.method';
|
export const HTTP_REQUEST_METHOD = 'http.request.method';
|
||||||
export const USER_ID = 'user.id';
|
export const USER_ID = 'user.id';
|
||||||
export const USER_AGENT_ORIGINAL = 'user_agent.original';
|
|
||||||
export const USER_AGENT_NAME = 'user_agent.name';
|
export const USER_AGENT_NAME = 'user_agent.name';
|
||||||
|
|
||||||
export const DESTINATION_ADDRESS = 'destination.address';
|
export const DESTINATION_ADDRESS = 'destination.address';
|
||||||
|
|
|
@ -3,11 +3,8 @@
|
||||||
"server": true,
|
"server": true,
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"kibanaVersion": "kibana",
|
"kibanaVersion": "kibana",
|
||||||
"configPath": [
|
"configPath": ["xpack", "apm"],
|
||||||
"xpack",
|
|
||||||
"apm"
|
|
||||||
],
|
|
||||||
"ui": false,
|
"ui": false,
|
||||||
"requiredPlugins": ["apm_oss", "data", "home", "licensing"],
|
"requiredPlugins": ["apm_oss", "data", "home", "licensing"],
|
||||||
"optionalPlugins": ["cloud", "usageCollection", "taskManager"]
|
"optionalPlugins": ["cloud", "usageCollection"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,7 @@ export const config = {
|
||||||
enabled: schema.boolean({ defaultValue: true }),
|
enabled: schema.boolean({ defaultValue: true }),
|
||||||
transactionGroupBucketSize: schema.number({ defaultValue: 100 }),
|
transactionGroupBucketSize: schema.number({ defaultValue: 100 }),
|
||||||
maxTraceItems: schema.number({ defaultValue: 1000 })
|
maxTraceItems: schema.number({ defaultValue: 1000 })
|
||||||
}),
|
})
|
||||||
telemetryCollectionEnabled: schema.boolean({ defaultValue: true })
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,8 +62,7 @@ export function mergeConfigs(
|
||||||
'xpack.apm.ui.maxTraceItems': apmConfig.ui.maxTraceItems,
|
'xpack.apm.ui.maxTraceItems': apmConfig.ui.maxTraceItems,
|
||||||
'xpack.apm.ui.transactionGroupBucketSize':
|
'xpack.apm.ui.transactionGroupBucketSize':
|
||||||
apmConfig.ui.transactionGroupBucketSize,
|
apmConfig.ui.transactionGroupBucketSize,
|
||||||
'xpack.apm.autocreateApmIndexPattern': apmConfig.autocreateApmIndexPattern,
|
'xpack.apm.autocreateApmIndexPattern': apmConfig.autocreateApmIndexPattern
|
||||||
'xpack.apm.telemetryCollectionEnabled': apmConfig.telemetryCollectionEnabled
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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 { SavedObjectAttributes } from '../../../../../../../src/core/server';
|
||||||
|
import { createApmTelementry, storeApmServicesTelemetry } from '../index';
|
||||||
|
import {
|
||||||
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_TYPE,
|
||||||
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_ID
|
||||||
|
} from '../../../../common/apm_saved_object_constants';
|
||||||
|
|
||||||
|
describe('apm_telemetry', () => {
|
||||||
|
describe('createApmTelementry', () => {
|
||||||
|
it('should create a ApmTelemetry object with boolean flag and frequency map of the given list of AgentNames', () => {
|
||||||
|
const apmTelemetry = createApmTelementry([
|
||||||
|
'go',
|
||||||
|
'nodejs',
|
||||||
|
'go',
|
||||||
|
'js-base'
|
||||||
|
]);
|
||||||
|
expect(apmTelemetry.has_any_services).toBe(true);
|
||||||
|
expect(apmTelemetry.services_per_agent).toMatchObject({
|
||||||
|
go: 2,
|
||||||
|
nodejs: 1,
|
||||||
|
'js-base': 1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should ignore undefined or unknown AgentName values', () => {
|
||||||
|
const apmTelemetry = createApmTelementry([
|
||||||
|
'go',
|
||||||
|
'nodejs',
|
||||||
|
'go',
|
||||||
|
'js-base',
|
||||||
|
'example-platform' as any,
|
||||||
|
undefined as any
|
||||||
|
]);
|
||||||
|
expect(apmTelemetry.services_per_agent).toMatchObject({
|
||||||
|
go: 2,
|
||||||
|
nodejs: 1,
|
||||||
|
'js-base': 1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('storeApmServicesTelemetry', () => {
|
||||||
|
let apmTelemetry: SavedObjectAttributes;
|
||||||
|
let savedObjectsClient: any;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
apmTelemetry = {
|
||||||
|
has_any_services: true,
|
||||||
|
services_per_agent: {
|
||||||
|
go: 2,
|
||||||
|
nodejs: 1,
|
||||||
|
'js-base': 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
savedObjectsClient = { create: jest.fn() };
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call savedObjectsClient create with the given ApmTelemetry object', () => {
|
||||||
|
storeApmServicesTelemetry(savedObjectsClient, apmTelemetry);
|
||||||
|
expect(savedObjectsClient.create.mock.calls[0][1]).toBe(apmTelemetry);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call savedObjectsClient create with the apm-telemetry document type and ID', () => {
|
||||||
|
storeApmServicesTelemetry(savedObjectsClient, apmTelemetry);
|
||||||
|
expect(savedObjectsClient.create.mock.calls[0][0]).toBe(
|
||||||
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_TYPE
|
||||||
|
);
|
||||||
|
expect(savedObjectsClient.create.mock.calls[0][2].id).toBe(
|
||||||
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_ID
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call savedObjectsClient create with overwrite: true', () => {
|
||||||
|
storeApmServicesTelemetry(savedObjectsClient, apmTelemetry);
|
||||||
|
expect(savedObjectsClient.create.mock.calls[0][2].overwrite).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,77 +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 { merge } from 'lodash';
|
|
||||||
import { Logger, CallAPIOptions } from 'kibana/server';
|
|
||||||
import { IndicesStatsParams, Client } from 'elasticsearch';
|
|
||||||
import {
|
|
||||||
ESSearchRequest,
|
|
||||||
ESSearchResponse
|
|
||||||
} from '../../../../typings/elasticsearch';
|
|
||||||
import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices';
|
|
||||||
import { tasks } from './tasks';
|
|
||||||
import { APMDataTelemetry } from '../types';
|
|
||||||
|
|
||||||
type TelemetryTaskExecutor = (params: {
|
|
||||||
indices: ApmIndicesConfig;
|
|
||||||
search<TSearchRequest extends ESSearchRequest>(
|
|
||||||
params: TSearchRequest
|
|
||||||
): Promise<ESSearchResponse<unknown, TSearchRequest>>;
|
|
||||||
indicesStats(
|
|
||||||
params: IndicesStatsParams,
|
|
||||||
options?: CallAPIOptions
|
|
||||||
): ReturnType<Client['indices']['stats']>;
|
|
||||||
transportRequest: (params: {
|
|
||||||
path: string;
|
|
||||||
method: 'get';
|
|
||||||
}) => Promise<unknown>;
|
|
||||||
}) => Promise<APMDataTelemetry>;
|
|
||||||
|
|
||||||
export interface TelemetryTask {
|
|
||||||
name: string;
|
|
||||||
executor: TelemetryTaskExecutor;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CollectTelemetryParams = Parameters<TelemetryTaskExecutor>[0] & {
|
|
||||||
logger: Logger;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function collectDataTelemetry({
|
|
||||||
search,
|
|
||||||
indices,
|
|
||||||
logger,
|
|
||||||
indicesStats,
|
|
||||||
transportRequest
|
|
||||||
}: CollectTelemetryParams) {
|
|
||||||
return tasks.reduce((prev, task) => {
|
|
||||||
return prev.then(async data => {
|
|
||||||
logger.debug(`Executing APM telemetry task ${task.name}`);
|
|
||||||
try {
|
|
||||||
const time = process.hrtime();
|
|
||||||
const next = await task.executor({
|
|
||||||
search,
|
|
||||||
indices,
|
|
||||||
indicesStats,
|
|
||||||
transportRequest
|
|
||||||
});
|
|
||||||
const took = process.hrtime(time);
|
|
||||||
|
|
||||||
return merge({}, data, next, {
|
|
||||||
tasks: {
|
|
||||||
[task.name]: {
|
|
||||||
took: {
|
|
||||||
ms: Math.round(took[0] * 1000 + took[1] / 1e6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
logger.warn(`Failed executing APM telemetry task ${task.name}`);
|
|
||||||
logger.warn(err);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, Promise.resolve({} as APMDataTelemetry));
|
|
||||||
}
|
|
|
@ -1,725 +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 { flatten, merge, sortBy, sum } from 'lodash';
|
|
||||||
import { AgentName } from '../../../../typings/es_schemas/ui/fields/agent';
|
|
||||||
import { AGENT_NAMES } from '../../../../common/agent_name';
|
|
||||||
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
|
|
||||||
import {
|
|
||||||
PROCESSOR_EVENT,
|
|
||||||
SERVICE_NAME,
|
|
||||||
AGENT_NAME,
|
|
||||||
AGENT_VERSION,
|
|
||||||
ERROR_GROUP_ID,
|
|
||||||
TRANSACTION_NAME,
|
|
||||||
PARENT_ID,
|
|
||||||
SERVICE_FRAMEWORK_NAME,
|
|
||||||
SERVICE_FRAMEWORK_VERSION,
|
|
||||||
SERVICE_LANGUAGE_NAME,
|
|
||||||
SERVICE_LANGUAGE_VERSION,
|
|
||||||
SERVICE_RUNTIME_NAME,
|
|
||||||
SERVICE_RUNTIME_VERSION,
|
|
||||||
USER_AGENT_ORIGINAL
|
|
||||||
} from '../../../../common/elasticsearch_fieldnames';
|
|
||||||
import { Span } from '../../../../typings/es_schemas/ui/span';
|
|
||||||
import { APMError } from '../../../../typings/es_schemas/ui/apm_error';
|
|
||||||
import { TelemetryTask } from '.';
|
|
||||||
import { APMTelemetry } from '../types';
|
|
||||||
|
|
||||||
const TIME_RANGES = ['1d', 'all'] as const;
|
|
||||||
type TimeRange = typeof TIME_RANGES[number];
|
|
||||||
|
|
||||||
export const tasks: TelemetryTask[] = [
|
|
||||||
{
|
|
||||||
name: 'processor_events',
|
|
||||||
executor: async ({ indices, search }) => {
|
|
||||||
const indicesByProcessorEvent = {
|
|
||||||
error: indices['apm_oss.errorIndices'],
|
|
||||||
metric: indices['apm_oss.metricsIndices'],
|
|
||||||
span: indices['apm_oss.spanIndices'],
|
|
||||||
transaction: indices['apm_oss.transactionIndices'],
|
|
||||||
onboarding: indices['apm_oss.onboardingIndices'],
|
|
||||||
sourcemap: indices['apm_oss.sourcemapIndices']
|
|
||||||
};
|
|
||||||
|
|
||||||
type ProcessorEvent = keyof typeof indicesByProcessorEvent;
|
|
||||||
|
|
||||||
const jobs: Array<{
|
|
||||||
processorEvent: ProcessorEvent;
|
|
||||||
timeRange: TimeRange;
|
|
||||||
}> = flatten(
|
|
||||||
(Object.keys(
|
|
||||||
indicesByProcessorEvent
|
|
||||||
) as ProcessorEvent[]).map(processorEvent =>
|
|
||||||
TIME_RANGES.map(timeRange => ({ processorEvent, timeRange }))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const allData = await jobs.reduce((prevJob, current) => {
|
|
||||||
return prevJob.then(async data => {
|
|
||||||
const { processorEvent, timeRange } = current;
|
|
||||||
|
|
||||||
const response = await search({
|
|
||||||
index: indicesByProcessorEvent[processorEvent],
|
|
||||||
body: {
|
|
||||||
size: 1,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [
|
|
||||||
{ term: { [PROCESSOR_EVENT]: processorEvent } },
|
|
||||||
...(timeRange !== 'all'
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
range: {
|
|
||||||
'@timestamp': {
|
|
||||||
gte: `now-${timeRange}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
: [])
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
'@timestamp': 'asc'
|
|
||||||
},
|
|
||||||
_source: ['@timestamp'],
|
|
||||||
track_total_hits: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const event = response.hits.hits[0]?._source as {
|
|
||||||
'@timestamp': number;
|
|
||||||
};
|
|
||||||
|
|
||||||
return merge({}, data, {
|
|
||||||
counts: {
|
|
||||||
[processorEvent]: {
|
|
||||||
[timeRange]: response.hits.total.value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
...(timeRange === 'all' && event
|
|
||||||
? {
|
|
||||||
retainment: {
|
|
||||||
[processorEvent]: {
|
|
||||||
ms:
|
|
||||||
new Date().getTime() -
|
|
||||||
new Date(event['@timestamp']).getTime()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: {})
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, Promise.resolve({} as Record<string, { counts: Record<ProcessorEvent, Record<TimeRange, number>> }>));
|
|
||||||
|
|
||||||
return allData;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'agent_configuration',
|
|
||||||
executor: async ({ indices, search }) => {
|
|
||||||
const agentConfigurationCount = (
|
|
||||||
await search({
|
|
||||||
index: indices.apmAgentConfigurationIndex,
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
track_total_hits: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
).hits.total.value;
|
|
||||||
|
|
||||||
return {
|
|
||||||
counts: {
|
|
||||||
agent_configuration: {
|
|
||||||
all: agentConfigurationCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'services',
|
|
||||||
executor: async ({ indices, search }) => {
|
|
||||||
const servicesPerAgent = await AGENT_NAMES.reduce(
|
|
||||||
(prevJob, agentName) => {
|
|
||||||
return prevJob.then(async data => {
|
|
||||||
const response = await search({
|
|
||||||
index: [
|
|
||||||
indices['apm_oss.errorIndices'],
|
|
||||||
indices['apm_oss.spanIndices'],
|
|
||||||
indices['apm_oss.metricsIndices'],
|
|
||||||
indices['apm_oss.transactionIndices']
|
|
||||||
],
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [
|
|
||||||
{
|
|
||||||
term: {
|
|
||||||
[AGENT_NAME]: agentName
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
range: {
|
|
||||||
'@timestamp': {
|
|
||||||
gte: 'now-1d'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
services: {
|
|
||||||
cardinality: {
|
|
||||||
field: SERVICE_NAME
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
[agentName]: response.aggregations?.services.value || 0
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
Promise.resolve({} as Record<AgentName, number>)
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
has_any_services: sum(Object.values(servicesPerAgent)) > 0,
|
|
||||||
services_per_agent: servicesPerAgent
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'versions',
|
|
||||||
executor: async ({ search, indices }) => {
|
|
||||||
const response = await search({
|
|
||||||
index: [
|
|
||||||
indices['apm_oss.transactionIndices'],
|
|
||||||
indices['apm_oss.spanIndices'],
|
|
||||||
indices['apm_oss.errorIndices']
|
|
||||||
],
|
|
||||||
terminateAfter: 1,
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
exists: {
|
|
||||||
field: 'observer.version'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
size: 1,
|
|
||||||
sort: {
|
|
||||||
'@timestamp': 'desc'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const hit = response.hits.hits[0]?._source as Pick<
|
|
||||||
Transaction | Span | APMError,
|
|
||||||
'observer'
|
|
||||||
>;
|
|
||||||
|
|
||||||
if (!hit || !hit.observer?.version) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const [major, minor, patch] = hit.observer.version
|
|
||||||
.split('.')
|
|
||||||
.map(part => Number(part));
|
|
||||||
|
|
||||||
return {
|
|
||||||
versions: {
|
|
||||||
apm_server: {
|
|
||||||
major,
|
|
||||||
minor,
|
|
||||||
patch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'groupings',
|
|
||||||
executor: async ({ search, indices }) => {
|
|
||||||
const range1d = { range: { '@timestamp': { gte: 'now-1d' } } };
|
|
||||||
const errorGroupsCount = (
|
|
||||||
await search({
|
|
||||||
index: indices['apm_oss.errorIndices'],
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ term: { [PROCESSOR_EVENT]: 'error' } }, range1d]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
top_service: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_NAME,
|
|
||||||
order: {
|
|
||||||
error_groups: 'desc'
|
|
||||||
},
|
|
||||||
size: 1
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
error_groups: {
|
|
||||||
cardinality: {
|
|
||||||
field: ERROR_GROUP_ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
).aggregations?.top_service.buckets[0]?.error_groups.value;
|
|
||||||
|
|
||||||
const transactionGroupsCount = (
|
|
||||||
await search({
|
|
||||||
index: indices['apm_oss.transactionIndices'],
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [
|
|
||||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
|
||||||
range1d
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
top_service: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_NAME,
|
|
||||||
order: {
|
|
||||||
transaction_groups: 'desc'
|
|
||||||
},
|
|
||||||
size: 1
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
transaction_groups: {
|
|
||||||
cardinality: {
|
|
||||||
field: TRANSACTION_NAME
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
).aggregations?.top_service.buckets[0]?.transaction_groups.value;
|
|
||||||
|
|
||||||
const tracesPerDayCount = (
|
|
||||||
await search({
|
|
||||||
index: indices['apm_oss.transactionIndices'],
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [
|
|
||||||
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
|
|
||||||
range1d
|
|
||||||
],
|
|
||||||
must_not: {
|
|
||||||
exists: { field: PARENT_ID }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
track_total_hits: true,
|
|
||||||
size: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
).hits.total.value;
|
|
||||||
|
|
||||||
const servicesCount = (
|
|
||||||
await search({
|
|
||||||
index: [
|
|
||||||
indices['apm_oss.transactionIndices'],
|
|
||||||
indices['apm_oss.errorIndices'],
|
|
||||||
indices['apm_oss.metricsIndices']
|
|
||||||
],
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [range1d]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
service_name: {
|
|
||||||
cardinality: {
|
|
||||||
field: SERVICE_NAME
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
).aggregations?.service_name.value;
|
|
||||||
|
|
||||||
return {
|
|
||||||
counts: {
|
|
||||||
max_error_groups_per_service: {
|
|
||||||
'1d': errorGroupsCount || 0
|
|
||||||
},
|
|
||||||
max_transaction_groups_per_service: {
|
|
||||||
'1d': transactionGroupsCount || 0
|
|
||||||
},
|
|
||||||
traces: {
|
|
||||||
'1d': tracesPerDayCount || 0
|
|
||||||
},
|
|
||||||
services: {
|
|
||||||
'1d': servicesCount || 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'integrations',
|
|
||||||
executor: async ({ transportRequest }) => {
|
|
||||||
const apmJobs = ['*-high_mean_response_time'];
|
|
||||||
|
|
||||||
const response = (await transportRequest({
|
|
||||||
method: 'get',
|
|
||||||
path: `/_ml/anomaly_detectors/${apmJobs.join(',')}`
|
|
||||||
})) as { data?: { count: number } };
|
|
||||||
|
|
||||||
return {
|
|
||||||
integrations: {
|
|
||||||
ml: {
|
|
||||||
all_jobs_count: response.data?.count ?? 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'agents',
|
|
||||||
executor: async ({ search, indices }) => {
|
|
||||||
const size = 3;
|
|
||||||
|
|
||||||
const agentData = await AGENT_NAMES.reduce(async (prevJob, agentName) => {
|
|
||||||
const data = await prevJob;
|
|
||||||
|
|
||||||
const response = await search({
|
|
||||||
index: [
|
|
||||||
indices['apm_oss.errorIndices'],
|
|
||||||
indices['apm_oss.metricsIndices'],
|
|
||||||
indices['apm_oss.transactionIndices']
|
|
||||||
],
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [
|
|
||||||
{ term: { [AGENT_NAME]: agentName } },
|
|
||||||
{ range: { '@timestamp': { gte: 'now-1d' } } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
'@timestamp': 'desc'
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
[AGENT_VERSION]: {
|
|
||||||
terms: {
|
|
||||||
field: AGENT_VERSION,
|
|
||||||
size
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERVICE_FRAMEWORK_NAME]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_FRAMEWORK_NAME,
|
|
||||||
size
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
[SERVICE_FRAMEWORK_VERSION]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_FRAMEWORK_VERSION,
|
|
||||||
size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERVICE_FRAMEWORK_VERSION]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_FRAMEWORK_VERSION,
|
|
||||||
size
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERVICE_LANGUAGE_NAME]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_LANGUAGE_NAME,
|
|
||||||
size
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
[SERVICE_LANGUAGE_VERSION]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_LANGUAGE_VERSION,
|
|
||||||
size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERVICE_LANGUAGE_VERSION]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_LANGUAGE_VERSION,
|
|
||||||
size
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERVICE_RUNTIME_NAME]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_RUNTIME_NAME,
|
|
||||||
size
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
[SERVICE_RUNTIME_VERSION]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_RUNTIME_VERSION,
|
|
||||||
size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERVICE_RUNTIME_VERSION]: {
|
|
||||||
terms: {
|
|
||||||
field: SERVICE_RUNTIME_VERSION,
|
|
||||||
size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const { aggregations } = response;
|
|
||||||
|
|
||||||
if (!aggregations) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const toComposite = (
|
|
||||||
outerKey: string | number,
|
|
||||||
innerKey: string | number
|
|
||||||
) => `${outerKey}/${innerKey}`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
[agentName]: {
|
|
||||||
agent: {
|
|
||||||
version: aggregations[AGENT_VERSION].buckets.map(
|
|
||||||
bucket => bucket.key as string
|
|
||||||
)
|
|
||||||
},
|
|
||||||
service: {
|
|
||||||
framework: {
|
|
||||||
name: aggregations[SERVICE_FRAMEWORK_NAME].buckets
|
|
||||||
.map(bucket => bucket.key as string)
|
|
||||||
.slice(0, size),
|
|
||||||
version: aggregations[SERVICE_FRAMEWORK_VERSION].buckets
|
|
||||||
.map(bucket => bucket.key as string)
|
|
||||||
.slice(0, size),
|
|
||||||
composite: sortBy(
|
|
||||||
flatten(
|
|
||||||
aggregations[SERVICE_FRAMEWORK_NAME].buckets.map(bucket =>
|
|
||||||
bucket[SERVICE_FRAMEWORK_VERSION].buckets.map(
|
|
||||||
versionBucket => ({
|
|
||||||
doc_count: versionBucket.doc_count,
|
|
||||||
name: toComposite(bucket.key, versionBucket.key)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'doc_count'
|
|
||||||
)
|
|
||||||
.reverse()
|
|
||||||
.slice(0, size)
|
|
||||||
.map(composite => composite.name)
|
|
||||||
},
|
|
||||||
language: {
|
|
||||||
name: aggregations[SERVICE_LANGUAGE_NAME].buckets
|
|
||||||
.map(bucket => bucket.key as string)
|
|
||||||
.slice(0, size),
|
|
||||||
version: aggregations[SERVICE_LANGUAGE_VERSION].buckets
|
|
||||||
.map(bucket => bucket.key as string)
|
|
||||||
.slice(0, size),
|
|
||||||
composite: sortBy(
|
|
||||||
flatten(
|
|
||||||
aggregations[SERVICE_LANGUAGE_NAME].buckets.map(bucket =>
|
|
||||||
bucket[SERVICE_LANGUAGE_VERSION].buckets.map(
|
|
||||||
versionBucket => ({
|
|
||||||
doc_count: versionBucket.doc_count,
|
|
||||||
name: toComposite(bucket.key, versionBucket.key)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'doc_count'
|
|
||||||
)
|
|
||||||
.reverse()
|
|
||||||
.slice(0, size)
|
|
||||||
.map(composite => composite.name)
|
|
||||||
},
|
|
||||||
runtime: {
|
|
||||||
name: aggregations[SERVICE_RUNTIME_NAME].buckets
|
|
||||||
.map(bucket => bucket.key as string)
|
|
||||||
.slice(0, size),
|
|
||||||
version: aggregations[SERVICE_RUNTIME_VERSION].buckets
|
|
||||||
.map(bucket => bucket.key as string)
|
|
||||||
.slice(0, size),
|
|
||||||
composite: sortBy(
|
|
||||||
flatten(
|
|
||||||
aggregations[SERVICE_RUNTIME_NAME].buckets.map(bucket =>
|
|
||||||
bucket[SERVICE_RUNTIME_VERSION].buckets.map(
|
|
||||||
versionBucket => ({
|
|
||||||
doc_count: versionBucket.doc_count,
|
|
||||||
name: toComposite(bucket.key, versionBucket.key)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'doc_count'
|
|
||||||
)
|
|
||||||
.reverse()
|
|
||||||
.slice(0, size)
|
|
||||||
.map(composite => composite.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, Promise.resolve({} as APMTelemetry['agents']));
|
|
||||||
|
|
||||||
return {
|
|
||||||
agents: agentData
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'indices_stats',
|
|
||||||
executor: async ({ indicesStats, indices }) => {
|
|
||||||
const response = await indicesStats({
|
|
||||||
index: [
|
|
||||||
indices.apmAgentConfigurationIndex,
|
|
||||||
indices['apm_oss.errorIndices'],
|
|
||||||
indices['apm_oss.metricsIndices'],
|
|
||||||
indices['apm_oss.onboardingIndices'],
|
|
||||||
indices['apm_oss.sourcemapIndices'],
|
|
||||||
indices['apm_oss.spanIndices'],
|
|
||||||
indices['apm_oss.transactionIndices']
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
indices: {
|
|
||||||
shards: {
|
|
||||||
total: response._shards.total
|
|
||||||
},
|
|
||||||
all: {
|
|
||||||
total: {
|
|
||||||
docs: {
|
|
||||||
count: response._all.total.docs.count
|
|
||||||
},
|
|
||||||
store: {
|
|
||||||
size_in_bytes: response._all.total.store.size_in_bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'cardinality',
|
|
||||||
executor: async ({ search }) => {
|
|
||||||
const allAgentsCardinalityResponse = await search({
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ range: { '@timestamp': { gte: 'now-1d' } } }]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
[TRANSACTION_NAME]: {
|
|
||||||
cardinality: {
|
|
||||||
field: TRANSACTION_NAME
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[USER_AGENT_ORIGINAL]: {
|
|
||||||
cardinality: {
|
|
||||||
field: USER_AGENT_ORIGINAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const rumAgentCardinalityResponse = await search({
|
|
||||||
body: {
|
|
||||||
size: 0,
|
|
||||||
query: {
|
|
||||||
bool: {
|
|
||||||
filter: [
|
|
||||||
{ range: { '@timestamp': { gte: 'now-1d' } } },
|
|
||||||
{ terms: { [AGENT_NAME]: ['rum-js', 'js-base'] } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
aggs: {
|
|
||||||
[TRANSACTION_NAME]: {
|
|
||||||
cardinality: {
|
|
||||||
field: TRANSACTION_NAME
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[USER_AGENT_ORIGINAL]: {
|
|
||||||
cardinality: {
|
|
||||||
field: USER_AGENT_ORIGINAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
cardinality: {
|
|
||||||
transaction: {
|
|
||||||
name: {
|
|
||||||
all_agents: {
|
|
||||||
'1d':
|
|
||||||
allAgentsCardinalityResponse.aggregations?.[TRANSACTION_NAME]
|
|
||||||
.value
|
|
||||||
},
|
|
||||||
rum: {
|
|
||||||
'1d':
|
|
||||||
rumAgentCardinalityResponse.aggregations?.[TRANSACTION_NAME]
|
|
||||||
.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
user_agent: {
|
|
||||||
original: {
|
|
||||||
all_agents: {
|
|
||||||
'1d':
|
|
||||||
allAgentsCardinalityResponse.aggregations?.[
|
|
||||||
USER_AGENT_ORIGINAL
|
|
||||||
].value
|
|
||||||
},
|
|
||||||
rum: {
|
|
||||||
'1d':
|
|
||||||
rumAgentCardinalityResponse.aggregations?.[
|
|
||||||
USER_AGENT_ORIGINAL
|
|
||||||
].value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
|
@ -3,127 +3,60 @@
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
import { CoreSetup, Logger } from 'src/core/server';
|
|
||||||
import { Observable } from 'rxjs';
|
import { countBy } from 'lodash';
|
||||||
import { take } from 'rxjs/operators';
|
import { SavedObjectAttributes } from '../../../../../../src/core/server';
|
||||||
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
|
import { isAgentName } from '../../../common/agent_name';
|
||||||
import {
|
import {
|
||||||
TaskManagerStartContract,
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_TYPE,
|
||||||
TaskManagerSetupContract
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_ID
|
||||||
} from '../../../../task_manager/server';
|
|
||||||
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
|
|
||||||
import {
|
|
||||||
APM_TELEMETRY_SAVED_OBJECT_ID,
|
|
||||||
APM_TELEMETRY_SAVED_OBJECT_TYPE
|
|
||||||
} from '../../../common/apm_saved_object_constants';
|
} from '../../../common/apm_saved_object_constants';
|
||||||
import {
|
import { UsageCollectionSetup } from '../../../../../../src/plugins/usage_collection/server';
|
||||||
collectDataTelemetry,
|
import { InternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client';
|
||||||
CollectTelemetryParams
|
|
||||||
} from './collect_data_telemetry';
|
|
||||||
import { APMConfig } from '../..';
|
|
||||||
import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client';
|
|
||||||
|
|
||||||
const APM_TELEMETRY_TASK_NAME = 'apm-telemetry-task';
|
export function createApmTelementry(
|
||||||
|
agentNames: string[] = []
|
||||||
export async function createApmTelemetry({
|
): SavedObjectAttributes {
|
||||||
core,
|
const validAgentNames = agentNames.filter(isAgentName);
|
||||||
config$,
|
return {
|
||||||
usageCollector,
|
has_any_services: validAgentNames.length > 0,
|
||||||
taskManager,
|
services_per_agent: countBy(validAgentNames)
|
||||||
logger
|
|
||||||
}: {
|
|
||||||
core: CoreSetup;
|
|
||||||
config$: Observable<APMConfig>;
|
|
||||||
usageCollector: UsageCollectionSetup;
|
|
||||||
taskManager: TaskManagerSetupContract;
|
|
||||||
logger: Logger;
|
|
||||||
}) {
|
|
||||||
const savedObjectsClient = await getInternalSavedObjectsClient(core);
|
|
||||||
|
|
||||||
const collectAndStore = async () => {
|
|
||||||
const config = await config$.pipe(take(1)).toPromise();
|
|
||||||
const esClient = core.elasticsearch.dataClient;
|
|
||||||
|
|
||||||
const indices = await getApmIndices({
|
|
||||||
config,
|
|
||||||
savedObjectsClient
|
|
||||||
});
|
|
||||||
|
|
||||||
const search = esClient.callAsInternalUser.bind(
|
|
||||||
esClient,
|
|
||||||
'search'
|
|
||||||
) as CollectTelemetryParams['search'];
|
|
||||||
|
|
||||||
const indicesStats = esClient.callAsInternalUser.bind(
|
|
||||||
esClient,
|
|
||||||
'indices.stats'
|
|
||||||
) as CollectTelemetryParams['indicesStats'];
|
|
||||||
|
|
||||||
const transportRequest = esClient.callAsInternalUser.bind(
|
|
||||||
esClient,
|
|
||||||
'transport.request'
|
|
||||||
) as CollectTelemetryParams['transportRequest'];
|
|
||||||
|
|
||||||
const dataTelemetry = await collectDataTelemetry({
|
|
||||||
search,
|
|
||||||
indices,
|
|
||||||
logger,
|
|
||||||
indicesStats,
|
|
||||||
transportRequest
|
|
||||||
});
|
|
||||||
|
|
||||||
await savedObjectsClient.create(
|
|
||||||
APM_TELEMETRY_SAVED_OBJECT_TYPE,
|
|
||||||
dataTelemetry,
|
|
||||||
{ id: APM_TELEMETRY_SAVED_OBJECT_TYPE, overwrite: true }
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
taskManager.registerTaskDefinitions({
|
export async function storeApmServicesTelemetry(
|
||||||
[APM_TELEMETRY_TASK_NAME]: {
|
savedObjectsClient: InternalSavedObjectsClient,
|
||||||
title: 'Collect APM telemetry',
|
apmTelemetry: SavedObjectAttributes
|
||||||
type: APM_TELEMETRY_TASK_NAME,
|
) {
|
||||||
createTaskRunner: () => {
|
return savedObjectsClient.create(
|
||||||
return {
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_TYPE,
|
||||||
run: async () => {
|
apmTelemetry,
|
||||||
await collectAndStore();
|
{
|
||||||
}
|
id: APM_SERVICES_TELEMETRY_SAVED_OBJECT_ID,
|
||||||
};
|
overwrite: true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const collector = usageCollector.makeUsageCollector({
|
export function makeApmUsageCollector(
|
||||||
|
usageCollector: UsageCollectionSetup,
|
||||||
|
savedObjectsRepository: InternalSavedObjectsClient
|
||||||
|
) {
|
||||||
|
const apmUsageCollector = usageCollector.makeUsageCollector({
|
||||||
type: 'apm',
|
type: 'apm',
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
const data = (
|
try {
|
||||||
await savedObjectsClient.get(
|
const apmTelemetrySavedObject = await savedObjectsRepository.get(
|
||||||
APM_TELEMETRY_SAVED_OBJECT_TYPE,
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_TYPE,
|
||||||
APM_TELEMETRY_SAVED_OBJECT_ID
|
APM_SERVICES_TELEMETRY_SAVED_OBJECT_ID
|
||||||
)
|
);
|
||||||
).attributes;
|
return apmTelemetrySavedObject.attributes;
|
||||||
|
} catch (err) {
|
||||||
return data;
|
return createApmTelementry();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
isReady: () => true
|
isReady: () => true
|
||||||
});
|
});
|
||||||
|
|
||||||
usageCollector.registerCollector(collector);
|
usageCollector.registerCollector(apmUsageCollector);
|
||||||
|
|
||||||
core.getStartServices().then(([coreStart, pluginsStart]) => {
|
|
||||||
const { taskManager: taskManagerStart } = pluginsStart as {
|
|
||||||
taskManager: TaskManagerStartContract;
|
|
||||||
};
|
|
||||||
|
|
||||||
taskManagerStart.ensureScheduled({
|
|
||||||
id: APM_TELEMETRY_TASK_NAME,
|
|
||||||
taskType: APM_TELEMETRY_TASK_NAME,
|
|
||||||
schedule: {
|
|
||||||
interval: '720m'
|
|
||||||
},
|
|
||||||
scope: ['apm'],
|
|
||||||
params: {},
|
|
||||||
state: {}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,118 +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 { DeepPartial } from 'utility-types';
|
|
||||||
import { AgentName } from '../../../typings/es_schemas/ui/fields/agent';
|
|
||||||
|
|
||||||
export interface TimeframeMap {
|
|
||||||
'1d': number;
|
|
||||||
all: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TimeframeMap1d = Pick<TimeframeMap, '1d'>;
|
|
||||||
export type TimeframeMapAll = Pick<TimeframeMap, 'all'>;
|
|
||||||
|
|
||||||
export type APMDataTelemetry = DeepPartial<{
|
|
||||||
has_any_services: boolean;
|
|
||||||
services_per_agent: Record<AgentName, number>;
|
|
||||||
versions: {
|
|
||||||
apm_server: {
|
|
||||||
minor: number;
|
|
||||||
major: number;
|
|
||||||
patch: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
counts: {
|
|
||||||
transaction: TimeframeMap;
|
|
||||||
span: TimeframeMap;
|
|
||||||
error: TimeframeMap;
|
|
||||||
metric: TimeframeMap;
|
|
||||||
sourcemap: TimeframeMap;
|
|
||||||
onboarding: TimeframeMap;
|
|
||||||
agent_configuration: TimeframeMapAll;
|
|
||||||
max_transaction_groups_per_service: TimeframeMap;
|
|
||||||
max_error_groups_per_service: TimeframeMap;
|
|
||||||
traces: TimeframeMap;
|
|
||||||
services: TimeframeMap;
|
|
||||||
};
|
|
||||||
cardinality: {
|
|
||||||
user_agent: {
|
|
||||||
original: {
|
|
||||||
all_agents: TimeframeMap1d;
|
|
||||||
rum: TimeframeMap1d;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
transaction: {
|
|
||||||
name: {
|
|
||||||
all_agents: TimeframeMap1d;
|
|
||||||
rum: TimeframeMap1d;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
retainment: Record<
|
|
||||||
'span' | 'transaction' | 'error' | 'metric' | 'sourcemap' | 'onboarding',
|
|
||||||
{ ms: number }
|
|
||||||
>;
|
|
||||||
integrations: {
|
|
||||||
ml: {
|
|
||||||
all_jobs_count: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
agents: Record<
|
|
||||||
AgentName,
|
|
||||||
{
|
|
||||||
agent: {
|
|
||||||
version: string[];
|
|
||||||
};
|
|
||||||
service: {
|
|
||||||
framework: {
|
|
||||||
name: string[];
|
|
||||||
version: string[];
|
|
||||||
composite: string[];
|
|
||||||
};
|
|
||||||
language: {
|
|
||||||
name: string[];
|
|
||||||
version: string[];
|
|
||||||
composite: string[];
|
|
||||||
};
|
|
||||||
runtime: {
|
|
||||||
name: string[];
|
|
||||||
version: string[];
|
|
||||||
composite: string[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
indices: {
|
|
||||||
shards: {
|
|
||||||
total: number;
|
|
||||||
};
|
|
||||||
all: {
|
|
||||||
total: {
|
|
||||||
docs: {
|
|
||||||
count: number;
|
|
||||||
};
|
|
||||||
store: {
|
|
||||||
size_in_bytes: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
tasks: Record<
|
|
||||||
| 'processor_events'
|
|
||||||
| 'agent_configuration'
|
|
||||||
| 'services'
|
|
||||||
| 'versions'
|
|
||||||
| 'groupings'
|
|
||||||
| 'integrations'
|
|
||||||
| 'agents'
|
|
||||||
| 'indices_stats'
|
|
||||||
| 'cardinality',
|
|
||||||
{ took: { ms: number } }
|
|
||||||
>;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export type APMTelemetry = APMDataTelemetry;
|
|
|
@ -39,19 +39,6 @@ function getMockRequest() {
|
||||||
_debug: false
|
_debug: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
__LEGACY: {
|
|
||||||
server: {
|
|
||||||
plugins: {
|
|
||||||
elasticsearch: {
|
|
||||||
getCluster: jest.fn().mockReturnValue({ callWithInternalUser: {} })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
savedObjects: {
|
|
||||||
SavedObjectsClient: jest.fn(),
|
|
||||||
getSavedObjectsRepository: jest.fn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
core: {
|
core: {
|
||||||
elasticsearch: {
|
elasticsearch: {
|
||||||
dataClient: {
|
dataClient: {
|
||||||
|
|
|
@ -8,9 +8,9 @@ import { Observable, combineLatest, AsyncSubject } from 'rxjs';
|
||||||
import { map, take } from 'rxjs/operators';
|
import { map, take } from 'rxjs/operators';
|
||||||
import { Server } from 'hapi';
|
import { Server } from 'hapi';
|
||||||
import { once } from 'lodash';
|
import { once } from 'lodash';
|
||||||
import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server';
|
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
|
||||||
import { TaskManagerSetupContract } from '../../task_manager/server';
|
|
||||||
import { APMOSSPluginSetup } from '../../../../src/plugins/apm_oss/server';
|
import { APMOSSPluginSetup } from '../../../../src/plugins/apm_oss/server';
|
||||||
|
import { makeApmUsageCollector } from './lib/apm_telemetry';
|
||||||
import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index';
|
import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index';
|
||||||
import { createApmCustomLinkIndex } from './lib/settings/custom_link/create_custom_link_index';
|
import { createApmCustomLinkIndex } from './lib/settings/custom_link/create_custom_link_index';
|
||||||
import { createApmApi } from './routes/create_apm_api';
|
import { createApmApi } from './routes/create_apm_api';
|
||||||
|
@ -21,7 +21,6 @@ import { tutorialProvider } from './tutorial';
|
||||||
import { CloudSetup } from '../../cloud/server';
|
import { CloudSetup } from '../../cloud/server';
|
||||||
import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client';
|
import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client';
|
||||||
import { LicensingPluginSetup } from '../../licensing/public';
|
import { LicensingPluginSetup } from '../../licensing/public';
|
||||||
import { createApmTelemetry } from './lib/apm_telemetry';
|
|
||||||
|
|
||||||
export interface LegacySetup {
|
export interface LegacySetup {
|
||||||
server: Server;
|
server: Server;
|
||||||
|
@ -48,10 +47,9 @@ export class APMPlugin implements Plugin<APMPluginContract> {
|
||||||
licensing: LicensingPluginSetup;
|
licensing: LicensingPluginSetup;
|
||||||
cloud?: CloudSetup;
|
cloud?: CloudSetup;
|
||||||
usageCollection?: UsageCollectionSetup;
|
usageCollection?: UsageCollectionSetup;
|
||||||
taskManager?: TaskManagerSetupContract;
|
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const logger = this.initContext.logger.get();
|
const logger = this.initContext.logger.get('apm');
|
||||||
const config$ = this.initContext.config.create<APMXPackConfig>();
|
const config$ = this.initContext.config.create<APMXPackConfig>();
|
||||||
const mergedConfig$ = combineLatest(plugins.apm_oss.config$, config$).pipe(
|
const mergedConfig$ = combineLatest(plugins.apm_oss.config$, config$).pipe(
|
||||||
map(([apmOssConfig, apmConfig]) => mergeConfigs(apmOssConfig, apmConfig))
|
map(([apmOssConfig, apmConfig]) => mergeConfigs(apmOssConfig, apmConfig))
|
||||||
|
@ -63,20 +61,6 @@ export class APMPlugin implements Plugin<APMPluginContract> {
|
||||||
|
|
||||||
const currentConfig = await mergedConfig$.pipe(take(1)).toPromise();
|
const currentConfig = await mergedConfig$.pipe(take(1)).toPromise();
|
||||||
|
|
||||||
if (
|
|
||||||
plugins.taskManager &&
|
|
||||||
plugins.usageCollection &&
|
|
||||||
currentConfig['xpack.apm.telemetryCollectionEnabled']
|
|
||||||
) {
|
|
||||||
createApmTelemetry({
|
|
||||||
core,
|
|
||||||
config$: mergedConfig$,
|
|
||||||
usageCollector: plugins.usageCollection,
|
|
||||||
taskManager: plugins.taskManager,
|
|
||||||
logger
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// create agent configuration index without blocking setup lifecycle
|
// create agent configuration index without blocking setup lifecycle
|
||||||
createApmAgentConfigurationIndex({
|
createApmAgentConfigurationIndex({
|
||||||
esClient: core.elasticsearch.dataClient,
|
esClient: core.elasticsearch.dataClient,
|
||||||
|
@ -105,6 +89,18 @@ export class APMPlugin implements Plugin<APMPluginContract> {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const usageCollection = plugins.usageCollection;
|
||||||
|
if (usageCollection) {
|
||||||
|
getInternalSavedObjectsClient(core)
|
||||||
|
.then(savedObjectsClient => {
|
||||||
|
makeApmUsageCollector(usageCollection, savedObjectsClient);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
logger.error('Unable to initialize use collection');
|
||||||
|
logger.error(error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
config$: mergedConfig$,
|
config$: mergedConfig$,
|
||||||
registerLegacyAPI: once((__LEGACY: LegacySetup) => {
|
registerLegacyAPI: once((__LEGACY: LegacySetup) => {
|
||||||
|
@ -119,7 +115,6 @@ export class APMPlugin implements Plugin<APMPluginContract> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async start() {}
|
public start() {}
|
||||||
|
|
||||||
public stop() {}
|
public stop() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@ const getCoreMock = () => {
|
||||||
put,
|
put,
|
||||||
createRouter,
|
createRouter,
|
||||||
context: {
|
context: {
|
||||||
measure: () => undefined,
|
|
||||||
config$: new BehaviorSubject({} as APMConfig),
|
config$: new BehaviorSubject({} as APMConfig),
|
||||||
logger: ({
|
logger: ({
|
||||||
error: jest.fn()
|
error: jest.fn()
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as t from 'io-ts';
|
import * as t from 'io-ts';
|
||||||
|
import { AgentName } from '../../typings/es_schemas/ui/fields/agent';
|
||||||
|
import {
|
||||||
|
createApmTelementry,
|
||||||
|
storeApmServicesTelemetry
|
||||||
|
} from '../lib/apm_telemetry';
|
||||||
import { setupRequest } from '../lib/helpers/setup_request';
|
import { setupRequest } from '../lib/helpers/setup_request';
|
||||||
import { getServiceAgentName } from '../lib/services/get_service_agent_name';
|
import { getServiceAgentName } from '../lib/services/get_service_agent_name';
|
||||||
import { getServices } from '../lib/services/get_services';
|
import { getServices } from '../lib/services/get_services';
|
||||||
|
@ -13,6 +18,7 @@ import { getServiceNodeMetadata } from '../lib/services/get_service_node_metadat
|
||||||
import { createRoute } from './create_route';
|
import { createRoute } from './create_route';
|
||||||
import { uiFiltersRt, rangeRt } from './default_api_types';
|
import { uiFiltersRt, rangeRt } from './default_api_types';
|
||||||
import { getServiceAnnotations } from '../lib/services/annotations';
|
import { getServiceAnnotations } from '../lib/services/annotations';
|
||||||
|
import { getInternalSavedObjectsClient } from '../lib/helpers/get_internal_saved_objects_client';
|
||||||
|
|
||||||
export const servicesRoute = createRoute(core => ({
|
export const servicesRoute = createRoute(core => ({
|
||||||
path: '/api/apm/services',
|
path: '/api/apm/services',
|
||||||
|
@ -23,6 +29,16 @@ export const servicesRoute = createRoute(core => ({
|
||||||
const setup = await setupRequest(context, request);
|
const setup = await setupRequest(context, request);
|
||||||
const services = await getServices(setup);
|
const services = await getServices(setup);
|
||||||
|
|
||||||
|
// Store telemetry data derived from services
|
||||||
|
const agentNames = services.items.map(
|
||||||
|
({ agentName }) => agentName as AgentName
|
||||||
|
);
|
||||||
|
const apmTelemetry = createApmTelementry(agentNames);
|
||||||
|
const savedObjectsClient = await getInternalSavedObjectsClient(core);
|
||||||
|
storeApmServicesTelemetry(savedObjectsClient, apmTelemetry).catch(error => {
|
||||||
|
context.logger.error(error.message);
|
||||||
|
});
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -126,16 +126,6 @@ export interface AggregationOptionsByType {
|
||||||
combine_script: Script;
|
combine_script: Script;
|
||||||
reduce_script: Script;
|
reduce_script: Script;
|
||||||
};
|
};
|
||||||
date_range: {
|
|
||||||
field: string;
|
|
||||||
format?: string;
|
|
||||||
ranges: Array<
|
|
||||||
| { from: string | number }
|
|
||||||
| { to: string | number }
|
|
||||||
| { from: string | number; to: string | number }
|
|
||||||
>;
|
|
||||||
keyed?: boolean;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AggregationType = keyof AggregationOptionsByType;
|
type AggregationType = keyof AggregationOptionsByType;
|
||||||
|
@ -146,15 +136,6 @@ type AggregationOptionsMap = Unionize<
|
||||||
}
|
}
|
||||||
> & { aggs?: AggregationInputMap };
|
> & { aggs?: AggregationInputMap };
|
||||||
|
|
||||||
interface DateRangeBucket {
|
|
||||||
key: string;
|
|
||||||
to?: number;
|
|
||||||
from?: number;
|
|
||||||
to_as_string?: string;
|
|
||||||
from_as_string?: string;
|
|
||||||
doc_count: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AggregationInputMap {
|
export interface AggregationInputMap {
|
||||||
[key: string]: AggregationOptionsMap;
|
[key: string]: AggregationOptionsMap;
|
||||||
}
|
}
|
||||||
|
@ -295,11 +276,6 @@ interface AggregationResponsePart<
|
||||||
scripted_metric: {
|
scripted_metric: {
|
||||||
value: unknown;
|
value: unknown;
|
||||||
};
|
};
|
||||||
date_range: {
|
|
||||||
buckets: TAggregationOptionsMap extends { date_range: { keyed: true } }
|
|
||||||
? Record<string, DateRangeBucket>
|
|
||||||
: { buckets: DateRangeBucket[] };
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type for debugging purposes. If you see an error in AggregationResponseMap
|
// Type for debugging purposes. If you see an error in AggregationResponseMap
|
||||||
|
@ -309,7 +285,7 @@ interface AggregationResponsePart<
|
||||||
|
|
||||||
// type MissingAggregationResponseTypes = Exclude<
|
// type MissingAggregationResponseTypes = Exclude<
|
||||||
// AggregationType,
|
// AggregationType,
|
||||||
// keyof AggregationResponsePart<{}, unknown>
|
// keyof AggregationResponsePart<{}>
|
||||||
// >;
|
// >;
|
||||||
|
|
||||||
export type AggregationResponseMap<
|
export type AggregationResponseMap<
|
||||||
|
|
|
@ -15,7 +15,6 @@ import { Service } from './fields/service';
|
||||||
import { IStackframe } from './fields/stackframe';
|
import { IStackframe } from './fields/stackframe';
|
||||||
import { Url } from './fields/url';
|
import { Url } from './fields/url';
|
||||||
import { User } from './fields/user';
|
import { User } from './fields/user';
|
||||||
import { Observer } from './fields/observer';
|
|
||||||
|
|
||||||
interface Processor {
|
interface Processor {
|
||||||
name: 'error';
|
name: 'error';
|
||||||
|
@ -62,5 +61,4 @@ export interface ErrorRaw extends APMBaseDoc {
|
||||||
service: Service;
|
service: Service;
|
||||||
url?: Url;
|
url?: Url;
|
||||||
user?: User;
|
user?: User;
|
||||||
observer?: Observer;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface Observer {
|
|
||||||
version: string;
|
|
||||||
version_major: number;
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
import { APMBaseDoc } from './apm_base_doc';
|
import { APMBaseDoc } from './apm_base_doc';
|
||||||
import { IStackframe } from './fields/stackframe';
|
import { IStackframe } from './fields/stackframe';
|
||||||
import { Observer } from './fields/observer';
|
|
||||||
|
|
||||||
interface Processor {
|
interface Processor {
|
||||||
name: 'transaction';
|
name: 'transaction';
|
||||||
|
@ -51,5 +50,4 @@ export interface SpanRaw extends APMBaseDoc {
|
||||||
transaction?: {
|
transaction?: {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
observer?: Observer;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import { Service } from './fields/service';
|
||||||
import { Url } from './fields/url';
|
import { Url } from './fields/url';
|
||||||
import { User } from './fields/user';
|
import { User } from './fields/user';
|
||||||
import { UserAgent } from './fields/user_agent';
|
import { UserAgent } from './fields/user_agent';
|
||||||
import { Observer } from './fields/observer';
|
|
||||||
|
|
||||||
interface Processor {
|
interface Processor {
|
||||||
name: 'transaction';
|
name: 'transaction';
|
||||||
|
@ -62,5 +61,4 @@ export interface TransactionRaw extends APMBaseDoc {
|
||||||
url?: Url;
|
url?: Url;
|
||||||
user?: User;
|
user?: User;
|
||||||
user_agent?: UserAgent;
|
user_agent?: UserAgent;
|
||||||
observer?: Observer;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue