From c6705e8053153a85f4630fae4c2c12ac166d1c43 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Tue, 14 Jul 2020 08:16:20 -0500 Subject: [PATCH] [APM] Additional data telemetry changes (#71112) * Add a date range of `now-1d` to the cloud query * Add a timeout of 5m to all queries (we'll investigate using async queries to improve this in the future.) * Factor out the date range filter into a variable * Fix a bug with the `indices_stats` tasks when it doesn't return data * Update the merge mapping script to create a migration file --- .../__snapshots__/apm_telemetry.test.ts.snap | 1892 +++++++++-------- .../plugins/apm/common/apm_telemetry.test.ts | 57 +- x-pack/plugins/apm/common/apm_telemetry.ts | 24 +- x-pack/plugins/apm/dev_docs/telemetry.md | 12 +- .../apm/scripts/merge-telemetry-mapping.js | 21 - .../scripts/merge-telemetry-mapping/index.ts | 30 - .../collect_data_telemetry/tasks.test.ts | 176 +- .../collect_data_telemetry/tasks.ts | 81 +- .../apm/server/lib/apm_telemetry/index.ts | 12 +- .../apm/server/lib/apm_telemetry/types.ts | 1 + 10 files changed, 1232 insertions(+), 1074 deletions(-) delete mode 100644 x-pack/plugins/apm/scripts/merge-telemetry-mapping.js delete mode 100644 x-pack/plugins/apm/scripts/merge-telemetry-mapping/index.ts diff --git a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap index 4ee7692222d68..1d8cfa28aea75 100644 --- a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap @@ -1,929 +1,973 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the telemetry mapping 1`] = ` -Object { - "properties": Object { - "agents": Object { - "properties": Object { - "dotnet": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - "go": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - "java": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - "js-base": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - "nodejs": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - "python": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - "ruby": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - "rum-js": Object { - "properties": Object { - "agent": Object { - "properties": Object { - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "service": Object { - "properties": Object { - "framework": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "language": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "runtime": Object { - "properties": Object { - "composite": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "name": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "version": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - }, - }, - }, - }, - }, - }, - "cardinality": Object { - "properties": Object { - "transaction": Object { - "properties": Object { - "name": Object { - "properties": Object { - "all_agents": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - "rum": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - }, - }, - }, - }, - "user_agent": Object { - "properties": Object { - "original": Object { - "properties": Object { - "all_agents": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - "rum": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - }, - }, - }, - }, - }, - }, - "cloud": Object { - "properties": Object { - "availability_zone": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "provider": Object { - "ignore_above": 1024, - "type": "keyword", - }, - "region": Object { - "ignore_above": 1024, - "type": "keyword", - }, - }, - }, - "counts": Object { - "properties": Object { - "agent_configuration": Object { - "properties": Object { - "all": Object { - "type": "long", - }, - }, - }, - "error": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - "all": Object { - "type": "long", - }, - }, - }, - "max_error_groups_per_service": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - "max_transaction_groups_per_service": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - "metric": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - "all": Object { - "type": "long", - }, - }, - }, - "onboarding": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - "all": Object { - "type": "long", - }, - }, - }, - "services": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - "sourcemap": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - "all": Object { - "type": "long", - }, - }, - }, - "span": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - "all": Object { - "type": "long", - }, - }, - }, - "traces": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - }, - }, - "transaction": Object { - "properties": Object { - "1d": Object { - "type": "long", - }, - "all": Object { - "type": "long", - }, - }, - }, - }, - }, - "has_any_services": Object { - "type": "boolean", - }, - "indices": Object { - "properties": Object { - "all": Object { - "properties": Object { - "total": Object { - "properties": Object { - "docs": Object { - "properties": Object { - "count": Object { - "type": "long", - }, - }, - }, - "store": Object { - "properties": Object { - "size_in_bytes": Object { - "type": "long", - }, - }, - }, - }, - }, - }, - }, - "shards": Object { - "properties": Object { - "total": Object { - "type": "long", - }, - }, - }, - }, - }, - "integrations": Object { - "properties": Object { - "ml": Object { - "properties": Object { - "all_jobs_count": Object { - "type": "long", - }, - }, - }, - }, - }, - "retainment": Object { - "properties": Object { - "error": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - "metric": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - "onboarding": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - "span": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - "transaction": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "services_per_agent": Object { - "properties": Object { - "dotnet": Object { - "null_value": 0, - "type": "long", - }, - "go": Object { - "null_value": 0, - "type": "long", - }, - "java": Object { - "null_value": 0, - "type": "long", - }, - "js-base": Object { - "null_value": 0, - "type": "long", - }, - "nodejs": Object { - "null_value": 0, - "type": "long", - }, - "python": Object { - "null_value": 0, - "type": "long", - }, - "ruby": Object { - "null_value": 0, - "type": "long", - }, - "rum-js": Object { - "null_value": 0, - "type": "long", - }, - }, - }, - "tasks": Object { - "properties": Object { - "agent_configuration": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "agents": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "cardinality": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "groupings": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "indices_stats": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "integrations": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "processor_events": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "services": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - "versions": Object { - "properties": Object { - "took": Object { - "properties": Object { - "ms": Object { - "type": "long", - }, - }, - }, - }, - }, - }, - }, - "version": Object { - "properties": Object { - "apm_server": Object { - "properties": Object { - "major": Object { - "type": "long", - }, - "minor": Object { - "type": "long", - }, - "patch": Object { - "type": "long", - }, - }, - }, - }, - }, - }, +{ + "properties": { + "stack_stats": { + "properties": { + "kibana": { + "properties": { + "plugins": { + "properties": { + "apm": { + "properties": { + "agents": { + "properties": { + "dotnet": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "go": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "java": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "js-base": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "nodejs": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "python": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "ruby": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "rum-js": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "language": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "runtime": { + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + } + } + }, + "cloud": { + "properties": { + "availability_zone": { + "type": "keyword", + "ignore_above": 1024 + }, + "provider": { + "type": "keyword", + "ignore_above": 1024 + }, + "region": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "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": { + "client": { + "properties": { + "geo": { + "properites": { + "country_iso_code": { + "rum": { + "properties": { + "1d": { + "type": "long" + } + } + } + } + } + } + } + }, + "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": { + "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": { + "properties": { + "dotnet": { + "type": "long", + "null_value": 0 + }, + "go": { + "type": "long", + "null_value": 0 + }, + "java": { + "type": "long", + "null_value": 0 + }, + "js-base": { + "type": "long", + "null_value": 0 + }, + "nodejs": { + "type": "long", + "null_value": 0 + }, + "python": { + "type": "long", + "null_value": 0 + }, + "ruby": { + "type": "long", + "null_value": 0 + }, + "rum-js": { + "type": "long", + "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" + } + } + } + } + }, + "cloud": { + "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" + } + } + } + } + } + } + } + } + } + } + } + } + } + } } `; diff --git a/x-pack/plugins/apm/common/apm_telemetry.test.ts b/x-pack/plugins/apm/common/apm_telemetry.test.ts index 1612716142ce7..035c546a5b49a 100644 --- a/x-pack/plugins/apm/common/apm_telemetry.test.ts +++ b/x-pack/plugins/apm/common/apm_telemetry.test.ts @@ -4,48 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - getApmTelemetryMapping, - mergeApmTelemetryMapping, -} from './apm_telemetry'; +import { getApmTelemetryMapping } from './apm_telemetry'; + +// Add this snapshot serializer for this test. The default snapshot serializer +// prints "Object" next to objects in the JSON output, but we want to be able to +// Use the output from this JSON snapshot to share with the telemetry team. When +// new fields are added to the mapping, we'll have a diff in the snapshot. +expect.addSnapshotSerializer({ + print: (contents) => { + return JSON.stringify(contents, null, 2); + }, + test: () => true, +}); describe('APM telemetry helpers', () => { describe('getApmTelemetry', () => { + // This test creates a snapshot with the JSON of our full telemetry mapping + // that can be PUT in a query to the index on the telemetry cluster. Sharing + // the contents of the snapshot with the telemetry team can provide them with + // useful information about changes to our telmetry. it('generates a JSON object with the telemetry mapping', () => { - expect(getApmTelemetryMapping()).toMatchSnapshot(); - }); - }); - - describe('mergeApmTelemetryMapping', () => { - describe('with an invalid mapping', () => { - it('throws an error', () => { - expect(() => mergeApmTelemetryMapping({})).toThrowError(); - }); - }); - - describe('with a valid mapping', () => { - it('merges the mapping', () => { - // This is "valid" in the sense that it has all of the deep fields - // needed to merge. It's not a valid mapping opbject. - const validTelemetryMapping = { - mappings: { + expect({ + properties: { + stack_stats: { properties: { - stack_stats: { + kibana: { properties: { - kibana: { - properties: { plugins: { properties: { apm: {} } } }, + plugins: { + properties: { + apm: getApmTelemetryMapping(), + }, }, }, }, }, }, - }; - - expect( - mergeApmTelemetryMapping(validTelemetryMapping)?.mappings.properties - .stack_stats.properties.kibana.properties.plugins.properties.apm - ).toEqual(getApmTelemetryMapping()); - }); + }, + }).toMatchSnapshot(); }); }); }); diff --git a/x-pack/plugins/apm/common/apm_telemetry.ts b/x-pack/plugins/apm/common/apm_telemetry.ts index 5837648f3e505..5fb6414674d1c 100644 --- a/x-pack/plugins/apm/common/apm_telemetry.ts +++ b/x-pack/plugins/apm/common/apm_telemetry.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { produce } from 'immer'; import { AGENT_NAMES } from './agent_name'; /** @@ -115,6 +114,15 @@ export function getApmTelemetryMapping() { }, cardinality: { properties: { + client: { + properties: { + geo: { + properites: { + country_iso_code: { rum: oneDayProperties }, + }, + }, + }, + }, user_agent: { properties: { original: { @@ -199,6 +207,7 @@ export function getApmTelemetryMapping() { agent_configuration: tookProperties, agents: tookProperties, cardinality: tookProperties, + cloud: tookProperties, groupings: tookProperties, indices_stats: tookProperties, integrations: tookProperties, @@ -221,16 +230,3 @@ export function getApmTelemetryMapping() { }, }; } - -/** - * Merge a telemetry mapping object (from https://github.com/elastic/telemetry/blob/master/config/templates/xpack-phone-home.json) - * with the output from `getApmTelemetryMapping`. - */ -export function mergeApmTelemetryMapping( - xpackPhoneHomeMapping: Record -) { - return produce(xpackPhoneHomeMapping, (draft: Record) => { - draft.mappings.properties.stack_stats.properties.kibana.properties.plugins.properties.apm = getApmTelemetryMapping(); - return draft; - }); -} diff --git a/x-pack/plugins/apm/dev_docs/telemetry.md b/x-pack/plugins/apm/dev_docs/telemetry.md index fa8e057a59595..d61afbe07522f 100644 --- a/x-pack/plugins/apm/dev_docs/telemetry.md +++ b/x-pack/plugins/apm/dev_docs/telemetry.md @@ -55,20 +55,16 @@ The mapping for the telemetry data is here under `stack_stats.kibana.plugins.apm The mapping used there can be generated with the output of the [`getTelemetryMapping`](../common/apm_telemetry.ts) function. -To make a change to the mapping, edit this function, run the tests to update the snapshots, then use the `merge_telemetry_mapping` script to merge the data into the telemetry repository. +The `schema` property of the `makeUsageCollector` call in the [`createApmTelemetry` function](../server/lib/apm_telemetry/index.ts) contains the output of `getTelemetryMapping`. -If the [telemetry repository](https://github.com/elastic/telemetry) is cloned as a sibling to the kibana directory, you can run the following from x-pack/plugins/apm: - -```bash -node ./scripts/merge-telemetry-mapping.js ../../../../telemetry/config/templates/xpack-phone-home.json -``` - -this will replace the contents of the mapping in the repository checkout with the updated mapping. You can then [follow the telemetry team's instructions](https://github.com/elastic/telemetry#mappings) for opening a pull request with the mapping changes. +When adding a task, the key of the task and the `took` properties need to be added under the `tasks` properties in the mapping, as when tasks run they report the time they took. The queries for the stats are in the [collect data telemetry tasks](../server/lib/apm_telemetry/collect_data_telemetry/tasks.ts). The collection tasks also use the [`APMDataTelemetry` type](../server/lib/apm_telemetry/types.ts) which also needs to be updated with any changes to the fields. +Running `node scripts/telemetry_check --fix` from the root Kibana directory will update the schemas which schema should automatically notify the Telemetry team when a pull request is opened so they can update the mapping in the telemetry clusters. (At the time of this writing the APM schema is excluded. #70180 is open to remove these exclusions so at this time any pull requests with mapping changes will have to manually request the Telemetry team as a reviewer.) + ## Behavioral Telemetry Behavioral telemetry is recorded with the ui_metrics and application_usage methods from the Usage Collection plugin. diff --git a/x-pack/plugins/apm/scripts/merge-telemetry-mapping.js b/x-pack/plugins/apm/scripts/merge-telemetry-mapping.js deleted file mode 100644 index 741df981a9cb0..0000000000000 --- a/x-pack/plugins/apm/scripts/merge-telemetry-mapping.js +++ /dev/null @@ -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('./merge-telemetry-mapping/index.ts'); diff --git a/x-pack/plugins/apm/scripts/merge-telemetry-mapping/index.ts b/x-pack/plugins/apm/scripts/merge-telemetry-mapping/index.ts deleted file mode 100644 index c06d4cec150dc..0000000000000 --- a/x-pack/plugins/apm/scripts/merge-telemetry-mapping/index.ts +++ /dev/null @@ -1,30 +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 { readFileSync, truncateSync, writeFileSync } from 'fs'; -import { resolve } from 'path'; -import { argv } from 'yargs'; -import { mergeApmTelemetryMapping } from '../../common/apm_telemetry'; - -function errorExit(error?: Error) { - console.error(`usage: ${argv.$0} /path/to/xpack-phone-home.json`); // eslint-disable-line no-console - if (error) { - throw error; - } - process.exit(1); -} - -try { - const filename = resolve(argv._[0]); - const xpackPhoneHomeMapping = JSON.parse(readFileSync(filename, 'utf-8')); - - const newMapping = mergeApmTelemetryMapping(xpackPhoneHomeMapping); - - truncateSync(filename); - writeFileSync(filename, JSON.stringify(newMapping, null, 2)); -} catch (error) { - errorExit(error); -} diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts index e3161b49b315d..ea2b57c01acff 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts @@ -16,7 +16,7 @@ describe('data telemetry collection tasks', () => { } as ApmIndicesConfig; describe('cloud', () => { - const cloudTask = tasks.find((task) => task.name === 'cloud'); + const task = tasks.find((t) => t.name === 'cloud'); it('returns a map of cloud provider data', async () => { const search = jest.fn().mockResolvedValueOnce({ @@ -42,7 +42,7 @@ describe('data telemetry collection tasks', () => { }, }); - expect(await cloudTask?.executor({ indices, search } as any)).toEqual({ + expect(await task?.executor({ indices, search } as any)).toEqual({ cloud: { availability_zone: ['us-west-1', 'europe-west1-c'], provider: ['aws', 'gcp'], @@ -55,7 +55,7 @@ describe('data telemetry collection tasks', () => { it('returns an empty map', async () => { const search = jest.fn().mockResolvedValueOnce({}); - expect(await cloudTask?.executor({ indices, search } as any)).toEqual({ + expect(await task?.executor({ indices, search } as any)).toEqual({ cloud: { availability_zone: [], provider: [], @@ -66,8 +66,83 @@ describe('data telemetry collection tasks', () => { }); }); + describe('processor_events', () => { + const task = tasks.find((t) => t.name === 'processor_events'); + + it('returns a map of processor events', async () => { + const getTime = jest + .spyOn(Date.prototype, 'getTime') + .mockReturnValue(1594330792957); + + const search = jest.fn().mockImplementation((params: any) => { + const isTotalHitsQuery = params?.body?.track_total_hits; + + return Promise.resolve( + isTotalHitsQuery + ? { hits: { total: { value: 1 } } } + : { + hits: { + hits: [{ _source: { '@timestamp': 1 } }], + }, + } + ); + }); + + expect(await task?.executor({ indices, search } as any)).toEqual({ + counts: { + error: { + '1d': 1, + all: 1, + }, + metric: { + '1d': 1, + all: 1, + }, + onboarding: { + '1d': 1, + all: 1, + }, + sourcemap: { + '1d': 1, + all: 1, + }, + span: { + '1d': 1, + all: 1, + }, + transaction: { + '1d': 1, + all: 1, + }, + }, + retainment: { + error: { + ms: 0, + }, + metric: { + ms: 0, + }, + onboarding: { + ms: 0, + }, + sourcemap: { + ms: 0, + }, + span: { + ms: 0, + }, + transaction: { + ms: 0, + }, + }, + }); + + getTime.mockRestore(); + }); + }); + describe('integrations', () => { - const integrationsTask = tasks.find((task) => task.name === 'integrations'); + const task = tasks.find((t) => t.name === 'integrations'); it('returns the count of ML jobs', async () => { const transportRequest = jest @@ -75,7 +150,7 @@ describe('data telemetry collection tasks', () => { .mockResolvedValueOnce({ body: { count: 1 } }); expect( - await integrationsTask?.executor({ indices, transportRequest } as any) + await task?.executor({ indices, transportRequest } as any) ).toEqual({ integrations: { ml: { @@ -90,7 +165,7 @@ describe('data telemetry collection tasks', () => { const transportRequest = jest.fn().mockResolvedValueOnce({}); expect( - await integrationsTask?.executor({ indices, transportRequest } as any) + await task?.executor({ indices, transportRequest } as any) ).toEqual({ integrations: { ml: { @@ -101,4 +176,93 @@ describe('data telemetry collection tasks', () => { }); }); }); + + describe('indices_stats', () => { + const task = tasks.find((t) => t.name === 'indices_stats'); + + it('returns a map of index stats', async () => { + const indicesStats = jest.fn().mockResolvedValueOnce({ + _all: { total: { docs: { count: 1 }, store: { size_in_bytes: 1 } } }, + _shards: { total: 1 }, + }); + + expect(await task?.executor({ indices, indicesStats } as any)).toEqual({ + indices: { + shards: { + total: 1, + }, + all: { + total: { + docs: { + count: 1, + }, + store: { + size_in_bytes: 1, + }, + }, + }, + }, + }); + }); + + describe('with no results', () => { + it('returns zero values', async () => { + const indicesStats = jest.fn().mockResolvedValueOnce({}); + + expect(await task?.executor({ indices, indicesStats } as any)).toEqual({ + indices: { + shards: { + total: 0, + }, + all: { + total: { + docs: { + count: 0, + }, + store: { + size_in_bytes: 0, + }, + }, + }, + }, + }); + }); + }); + }); + + describe('cardinality', () => { + const task = tasks.find((t) => t.name === 'cardinality'); + + it('returns cardinalities', async () => { + const search = jest.fn().mockImplementation((params: any) => { + const isRumQuery = params.body.query.bool.filter.length === 2; + if (isRumQuery) { + return Promise.resolve({ + aggregations: { + 'client.geo.country_iso_code': { value: 5 }, + 'transaction.name': { value: 1 }, + 'user_agent.original': { value: 2 }, + }, + }); + } else { + return Promise.resolve({ + aggregations: { + 'transaction.name': { value: 3 }, + 'user_agent.original': { value: 4 }, + }, + }); + } + }); + + expect(await task?.executor({ search } as any)).toEqual({ + cardinality: { + client: { geo: { country_iso_code: { rum: { '1d': 5 } } } }, + transaction: { name: { all_agents: { '1d': 3 }, rum: { '1d': 1 } } }, + user_agent: { + original: { all_agents: { '1d': 4 }, rum: { '1d': 2 } }, + }, + }, + }); + }); + }); }); diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts index 4bbaaf3e86e78..2ecb5a935893f 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts @@ -9,6 +9,7 @@ import { AGENT_NAMES } from '../../../../common/agent_name'; import { AGENT_NAME, AGENT_VERSION, + CLIENT_GEO_COUNTRY_ISO_CODE, CLOUD_AVAILABILITY_ZONE, CLOUD_PROVIDER, CLOUD_REGION, @@ -34,6 +35,9 @@ import { APMTelemetry } from '../types'; const TIME_RANGES = ['1d', 'all'] as const; type TimeRange = typeof TIME_RANGES[number]; +const range1d = { range: { '@timestamp': { gte: 'now-1d' } } }; +const timeout = '5m'; + export const tasks: TelemetryTask[] = [ { name: 'cloud', @@ -62,6 +66,7 @@ export const tasks: TelemetryTask[] = [ ], body: { size: 0, + timeout, aggs: { [az]: { terms: { @@ -109,15 +114,14 @@ export const tasks: TelemetryTask[] = [ type ProcessorEvent = keyof typeof indicesByProcessorEvent; - const jobs: Array<{ + interface Job { processorEvent: ProcessorEvent; timeRange: TimeRange; - }> = flatten( - (Object.keys( - indicesByProcessorEvent - ) as ProcessorEvent[]).map((processorEvent) => - TIME_RANGES.map((timeRange) => ({ processorEvent, timeRange })) - ) + } + + const events = Object.keys(indicesByProcessorEvent) as ProcessorEvent[]; + const jobs: Job[] = events.flatMap((processorEvent) => + TIME_RANGES.map((timeRange) => ({ processorEvent, timeRange })) ); const allData = await jobs.reduce((prevJob, current) => { @@ -128,21 +132,12 @@ export const tasks: TelemetryTask[] = [ index: indicesByProcessorEvent[processorEvent], body: { size: 0, + timeout, query: { bool: { filter: [ { term: { [PROCESSOR_EVENT]: processorEvent } }, - ...(timeRange !== 'all' - ? [ - { - range: { - '@timestamp': { - gte: `now-${timeRange}`, - }, - }, - }, - ] - : []), + ...(timeRange === '1d' ? [range1d] : []), ], }, }, @@ -155,6 +150,7 @@ export const tasks: TelemetryTask[] = [ ? await search({ index: indicesByProcessorEvent[processorEvent], body: { + timeout, query: { bool: { filter: [ @@ -208,6 +204,7 @@ export const tasks: TelemetryTask[] = [ index: indices.apmAgentConfigurationIndex, body: { size: 0, + timeout, track_total_hits: true, }, }) @@ -237,6 +234,7 @@ export const tasks: TelemetryTask[] = [ ], body: { size: 0, + timeout, query: { bool: { filter: [ @@ -245,13 +243,7 @@ export const tasks: TelemetryTask[] = [ [AGENT_NAME]: agentName, }, }, - { - range: { - '@timestamp': { - gte: 'now-1d', - }, - }, - }, + range1d, ], }, }, @@ -297,6 +289,7 @@ export const tasks: TelemetryTask[] = [ }, }, size: 1, + timeout, sort: { '@timestamp': 'desc', }, @@ -330,12 +323,12 @@ export const tasks: TelemetryTask[] = [ { 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, + timeout, query: { bool: { filter: [{ term: { [PROCESSOR_EVENT]: 'error' } }, range1d], @@ -368,6 +361,7 @@ export const tasks: TelemetryTask[] = [ index: indices['apm_oss.transactionIndices'], body: { size: 0, + timeout, query: { bool: { filter: [ @@ -415,6 +409,7 @@ export const tasks: TelemetryTask[] = [ }, track_total_hits: true, size: 0, + timeout, }, }) ).hits.total.value; @@ -428,6 +423,7 @@ export const tasks: TelemetryTask[] = [ ], body: { size: 0, + timeout, query: { bool: { filter: [range1d], @@ -497,12 +493,10 @@ export const tasks: TelemetryTask[] = [ ], body: { size: 0, + timeout, query: { bool: { - filter: [ - { term: { [AGENT_NAME]: agentName } }, - { range: { '@timestamp': { gte: 'now-1d' } } }, - ], + filter: [{ term: { [AGENT_NAME]: agentName } }, range1d], }, }, sort: { @@ -699,15 +693,15 @@ export const tasks: TelemetryTask[] = [ return { indices: { shards: { - total: response._shards.total, + total: response._shards?.total ?? 0, }, all: { total: { docs: { - count: response._all.total.docs.count, + count: response._all?.total?.docs?.count ?? 0, }, store: { - size_in_bytes: response._all.total.store.size_in_bytes, + size_in_bytes: response._all?.total?.store?.size_in_bytes ?? 0, }, }, }, @@ -721,9 +715,10 @@ export const tasks: TelemetryTask[] = [ const allAgentsCardinalityResponse = await search({ body: { size: 0, + timeout, query: { bool: { - filter: [{ range: { '@timestamp': { gte: 'now-1d' } } }], + filter: [range1d], }, }, aggs: { @@ -744,15 +739,19 @@ export const tasks: TelemetryTask[] = [ const rumAgentCardinalityResponse = await search({ body: { size: 0, + timeout, query: { bool: { filter: [ - { range: { '@timestamp': { gte: 'now-1d' } } }, + range1d, { terms: { [AGENT_NAME]: ['rum-js', 'js-base'] } }, ], }, }, aggs: { + [CLIENT_GEO_COUNTRY_ISO_CODE]: { + cardinality: { field: CLIENT_GEO_COUNTRY_ISO_CODE }, + }, [TRANSACTION_NAME]: { cardinality: { field: TRANSACTION_NAME, @@ -769,6 +768,18 @@ export const tasks: TelemetryTask[] = [ return { cardinality: { + client: { + geo: { + country_iso_code: { + rum: { + '1d': + rumAgentCardinalityResponse.aggregations?.[ + CLIENT_GEO_COUNTRY_ISO_CODE + ].value, + }, + }, + }, + }, transaction: { name: { all_agents: { diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts index 632e653a2f6e9..2836cf100a432 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts @@ -3,25 +3,26 @@ * or more contributor license agreements. Licensed under 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 { take } from 'rxjs/operators'; +import { CoreSetup, Logger } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { APMConfig } from '../..'; import { - TaskManagerStartContract, TaskManagerSetupContract, + TaskManagerStartContract, } 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'; +import { getApmTelemetryMapping } from '../../../common/apm_telemetry'; +import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; +import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; import { collectDataTelemetry, 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'; @@ -97,6 +98,7 @@ export async function createApmTelemetry({ const collector = usageCollector.makeUsageCollector({ type: 'apm', + schema: getApmTelemetryMapping(), fetch: async () => { try { const data = ( diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts index a1d94333b1a08..4c376aac52f5b 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts @@ -44,6 +44,7 @@ export type APMDataTelemetry = DeepPartial<{ services: TimeframeMap; }; cardinality: { + client: { geo: { country_iso_code: { rum: TimeframeMap1d } } }; user_agent: { original: { all_agents: TimeframeMap1d;