diff --git a/packages/kbn-apm-utils/es_fields.ts b/packages/kbn-apm-utils/es_fields.ts new file mode 100644 index 0000000000000..00e78c5196f7d --- /dev/null +++ b/packages/kbn-apm-utils/es_fields.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './src/es_fields/apm'; diff --git a/packages/kbn-apm-utils/es_schemas_raw.ts b/packages/kbn-apm-utils/es_schemas_raw.ts new file mode 100644 index 0000000000000..ef0d4cbeb5897 --- /dev/null +++ b/packages/kbn-apm-utils/es_schemas_raw.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +export * from './src/es_schemas/raw'; +export * from './src/es_schemas/raw/fields'; diff --git a/packages/kbn-apm-utils/es_schemas_ui.ts b/packages/kbn-apm-utils/es_schemas_ui.ts new file mode 100644 index 0000000000000..e974312a737ef --- /dev/null +++ b/packages/kbn-apm-utils/es_schemas_ui.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './src/es_schemas/ui'; +export * from './src/es_schemas/ui/fields'; diff --git a/packages/kbn-apm-utils/index.ts b/packages/kbn-apm-utils/index.ts index 09a6989091f60..6280489df3de2 100644 --- a/packages/kbn-apm-utils/index.ts +++ b/packages/kbn-apm-utils/index.ts @@ -6,111 +6,4 @@ * Side Public License, v 1. */ -import agent from 'elastic-apm-node'; -import asyncHooks from 'async_hooks'; - -export interface SpanOptions { - name: string; - type?: string; - subtype?: string; - labels?: Record; - intercept?: boolean; -} - -type Span = Exclude; - -export function parseSpanOptions(optionsOrName: SpanOptions | string) { - const options = typeof optionsOrName === 'string' ? { name: optionsOrName } : optionsOrName; - - return options; -} - -const runInNewContext = any>(cb: T): ReturnType => { - const resource = new asyncHooks.AsyncResource('fake_async'); - - return resource.runInAsyncScope(cb); -}; - -export async function withSpan( - optionsOrName: SpanOptions | string, - cb: (span?: Span) => Promise -): Promise { - const options = parseSpanOptions(optionsOrName); - - const { name, type, subtype, labels, intercept } = options; - - if (!agent.isStarted()) { - return cb(); - } - - let createdSpan: Span | undefined; - - // When a span starts, it's marked as the active span in its context. - // When it ends, it's not untracked, which means that if a span - // starts directly after this one ends, the newly started span is a - // child of this span, even though it should be a sibling. - // To mitigate this, we queue a microtask by awaiting a promise. - if (!intercept) { - await Promise.resolve(); - - createdSpan = agent.startSpan(name) ?? undefined; - - if (!createdSpan) { - return cb(); - } - } - - // If a span is created in the same context as the span that we just - // started, it will be a sibling, not a child. E.g., the Elasticsearch span - // that is created when calling search() happens in the same context. To - // mitigate this we create a new context. - - return runInNewContext(() => { - const promise = cb(createdSpan); - - let span: Span | undefined = createdSpan; - - if (intercept) { - span = agent.currentSpan ?? undefined; - } - - if (!span) { - return promise; - } - - const targetedSpan = span; - - if (name) { - targetedSpan.name = name; - } - - // @ts-ignore - if (type) { - targetedSpan.type = type; - } - if (subtype) { - targetedSpan.subtype = subtype; - } - - if (labels) { - targetedSpan.addLabels(labels); - } - - return promise - .then((res) => { - if (!targetedSpan.outcome || targetedSpan.outcome === 'unknown') { - targetedSpan.outcome = 'success'; - } - return res; - }) - .catch((err) => { - if (!targetedSpan.outcome || targetedSpan.outcome === 'unknown') { - targetedSpan.outcome = 'failure'; - } - throw err; - }) - .finally(() => { - targetedSpan.end(); - }); - }); -} +export { withSpan, parseSpanOptions, type SpanOptions } from './src/with_span'; diff --git a/packages/kbn-apm-utils/src/es_fields/apm.ts b/packages/kbn-apm-utils/src/es_fields/apm.ts new file mode 100644 index 0000000000000..d17a1ed78db90 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_fields/apm.ts @@ -0,0 +1,197 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const TIMESTAMP = 'timestamp.us'; +export const AGENT = 'agent'; +export const AGENT_NAME = 'agent.name'; +export const AGENT_VERSION = 'agent.version'; +export const AGENT_ACTIVATION_METHOD = 'agent.activation_method'; + +export const DESTINATION_ADDRESS = 'destination.address'; + +export const CLOUD = 'cloud'; +export const CLOUD_AVAILABILITY_ZONE = 'cloud.availability_zone'; +export const CLOUD_PROVIDER = 'cloud.provider'; +export const CLOUD_REGION = 'cloud.region'; +export const CLOUD_MACHINE_TYPE = 'cloud.machine.type'; +export const CLOUD_ACCOUNT_ID = 'cloud.account.id'; +export const CLOUD_INSTANCE_ID = 'cloud.instance.id'; +export const CLOUD_INSTANCE_NAME = 'cloud.instance.name'; +export const CLOUD_SERVICE_NAME = 'cloud.service.name'; + +export const EVENT_SUCCESS_COUNT = 'event.success_count'; + +export const SERVICE = 'service'; +export const SERVICE_NAME = 'service.name'; +export const SERVICE_ENVIRONMENT = 'service.environment'; +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_VERSION = 'service.version'; +export const SERVICE_TARGET_TYPE = 'service.target.type'; +export const SERVICE_OVERFLOW_COUNT = 'service_transaction.aggregation.overflow_count'; + +export const URL_FULL = 'url.full'; +export const HTTP_REQUEST_METHOD = 'http.request.method'; +export const HTTP_RESPONSE_STATUS_CODE = 'http.response.status_code'; +export const USER_ID = 'user.id'; +export const USER_AGENT_ORIGINAL = 'user_agent.original'; +export const USER_AGENT_NAME = 'user_agent.name'; + +export const OBSERVER_HOSTNAME = 'observer.hostname'; +export const OBSERVER_LISTENING = 'observer.listening'; +export const PROCESSOR_EVENT = 'processor.event'; + +export const TRANSACTION_DURATION = 'transaction.duration.us'; +export const TRANSACTION_DURATION_HISTOGRAM = 'transaction.duration.histogram'; +export const TRANSACTION_DURATION_SUMMARY = 'transaction.duration.summary'; +export const TRANSACTION_TYPE = 'transaction.type'; +export const TRANSACTION_RESULT = 'transaction.result'; +export const TRANSACTION_NAME = 'transaction.name'; +export const TRANSACTION_ID = 'transaction.id'; +export const TRANSACTION_SAMPLED = 'transaction.sampled'; +export const TRANSACTION_PAGE_URL = 'transaction.page.url'; +export const TRANSACTION_FAILURE_COUNT = 'transaction.failure_count'; +export const TRANSACTION_SUCCESS_COUNT = 'transaction.success_count'; +export const TRANSACTION_OVERFLOW_COUNT = 'transaction.aggregation.overflow_count'; +// for transaction metrics +export const TRANSACTION_ROOT = 'transaction.root'; +export const TRANSACTION_PROFILER_STACK_TRACE_IDS = 'transaction.profiler_stack_trace_ids'; + +export const EVENT_OUTCOME = 'event.outcome'; + +export const TRACE_ID = 'trace.id'; + +export const SPAN_DURATION = 'span.duration.us'; +export const SPAN_TYPE = 'span.type'; +export const SPAN_SUBTYPE = 'span.subtype'; +export const SPAN_SELF_TIME_SUM = 'span.self_time.sum.us'; +export const SPAN_ACTION = 'span.action'; +export const SPAN_NAME = 'span.name'; +export const SPAN_ID = 'span.id'; +export const SPAN_DESTINATION_SERVICE_RESOURCE = 'span.destination.service.resource'; +export const SPAN_DESTINATION_SERVICE_RESPONSE_TIME_COUNT = + 'span.destination.service.response_time.count'; + +export const SPAN_DESTINATION_SERVICE_RESPONSE_TIME_SUM = + 'span.destination.service.response_time.sum.us'; + +export const SPAN_LINKS = 'span.links'; +export const SPAN_LINKS_TRACE_ID = 'span.links.trace.id'; +export const SPAN_LINKS_SPAN_ID = 'span.links.span.id'; + +export const SPAN_COMPOSITE_COUNT = 'span.composite.count'; +export const SPAN_COMPOSITE_SUM = 'span.composite.sum.us'; +export const SPAN_COMPOSITE_COMPRESSION_STRATEGY = 'span.composite.compression_strategy'; + +export const SPAN_SYNC = 'span.sync'; + +// Parent ID for a transaction or span +export const PARENT_ID = 'parent.id'; + +export const ERROR_ID = 'error.id'; +export const ERROR_GROUP_ID = 'error.grouping_key'; +export const ERROR_GROUP_NAME = 'error.grouping_name'; +export const ERROR_CULPRIT = 'error.culprit'; +export const ERROR_LOG_LEVEL = 'error.log.level'; +export const ERROR_LOG_MESSAGE = 'error.log.message'; +export const ERROR_EXCEPTION = 'error.exception'; +export const ERROR_EXC_MESSAGE = 'error.exception.message'; // only to be used in es queries, since error.exception is now an array +export const ERROR_EXC_HANDLED = 'error.exception.handled'; // only to be used in es queries, since error.exception is now an array +export const ERROR_EXC_TYPE = 'error.exception.type'; +export const ERROR_PAGE_URL = 'error.page.url'; +export const ERROR_TYPE = 'error.type'; + +// METRICS +export const METRIC_SYSTEM_FREE_MEMORY = 'system.memory.actual.free'; +export const METRIC_SYSTEM_TOTAL_MEMORY = 'system.memory.total'; +export const METRIC_SYSTEM_CPU_PERCENT = 'system.cpu.total.norm.pct'; +export const METRIC_PROCESS_CPU_PERCENT = 'system.process.cpu.total.norm.pct'; +export const METRIC_CGROUP_MEMORY_LIMIT_BYTES = 'system.process.cgroup.memory.mem.limit.bytes'; +export const METRIC_CGROUP_MEMORY_USAGE_BYTES = 'system.process.cgroup.memory.mem.usage.bytes'; + +export const METRIC_JAVA_HEAP_MEMORY_MAX = 'jvm.memory.heap.max'; +export const METRIC_JAVA_HEAP_MEMORY_COMMITTED = 'jvm.memory.heap.committed'; +export const METRIC_JAVA_HEAP_MEMORY_USED = 'jvm.memory.heap.used'; +export const METRIC_JAVA_NON_HEAP_MEMORY_MAX = 'jvm.memory.non_heap.max'; +export const METRIC_JAVA_NON_HEAP_MEMORY_COMMITTED = 'jvm.memory.non_heap.committed'; +export const METRIC_JAVA_NON_HEAP_MEMORY_USED = 'jvm.memory.non_heap.used'; +export const METRIC_JAVA_THREAD_COUNT = 'jvm.thread.count'; +export const METRIC_JAVA_GC_COUNT = 'jvm.gc.count'; +export const METRIC_JAVA_GC_TIME = 'jvm.gc.time'; + +export const METRICSET_NAME = 'metricset.name'; +export const METRICSET_INTERVAL = 'metricset.interval'; + +export const LABEL_NAME = 'labels.name'; +export const LABEL_GC = 'labels.gc'; +export const LABEL_TYPE = 'labels.type'; +export const LABEL_TELEMETRY_AUTO_VERSION = 'labels.telemetry_auto_version'; +export const LABEL_LIFECYCLE_STATE = 'labels.lifecycle_state'; + +export const HOST = 'host'; +export const HOST_HOSTNAME = 'host.hostname'; // Do not use. Please use `HOST_NAME` instead. +export const HOST_NAME = 'host.name'; +export const HOST_OS_PLATFORM = 'host.os.platform'; +export const HOST_ARCHITECTURE = 'host.architecture'; +export const HOST_OS_VERSION = 'host.os.version'; + +export const CONTAINER_ID = 'container.id'; +export const CONTAINER = 'container'; +export const CONTAINER_IMAGE = 'container.image.name'; + +export const KUBERNETES = 'kubernetes'; +export const KUBERNETES_POD_NAME = 'kubernetes.pod.name'; +export const KUBERNETES_POD_UID = 'kubernetes.pod.uid'; + +export const FAAS_ID = 'faas.id'; +export const FAAS_NAME = 'faas.name'; +export const FAAS_COLDSTART = 'faas.coldstart'; +export const FAAS_TRIGGER_TYPE = 'faas.trigger.type'; +export const FAAS_DURATION = 'faas.duration'; +export const FAAS_COLDSTART_DURATION = 'faas.coldstart_duration'; +export const FAAS_BILLED_DURATION = 'faas.billed_duration'; + +// OpenTelemetry Metrics +export const METRIC_OTEL_SYSTEM_CPU_UTILIZATION = 'system.cpu.utilization'; +export const METRIC_OTEL_SYSTEM_MEMORY_UTILIZATION = 'system.memory.utilization'; + +export const METRIC_OTEL_JVM_PROCESS_CPU_PERCENT = 'process.runtime.jvm.cpu.utilization'; +export const METRIC_OTEL_JVM_PROCESS_MEMORY_USAGE = 'process.runtime.jvm.memory.usage'; +export const METRIC_OTEL_JVM_PROCESS_MEMORY_COMMITTED = 'process.runtime.jvm.memory.committed'; +export const METRIC_OTEL_JVM_PROCESS_MEMORY_LIMIT = 'process.runtime.jvm.memory.limit'; +export const METRIC_OTEL_JVM_PROCESS_THREADS_COUNT = 'process.runtime.jvm.threads.count'; +export const METRIC_OTEL_JVM_SYSTEM_CPU_PERCENT = 'process.runtime.jvm.system.cpu.utilization'; +export const METRIC_OTEL_JVM_GC_DURATION = 'process.runtime.jvm.gc.duration'; +export const VALUE_OTEL_JVM_PROCESS_MEMORY_HEAP = 'heap'; +export const VALUE_OTEL_JVM_PROCESS_MEMORY_NON_HEAP = 'non_heap'; + +// Metadata +export const TIER = '_tier'; +export const INDEX = '_index'; +export const DATA_STEAM_TYPE = 'data_stream.type'; + +// Mobile +export const NETWORK_CONNECTION_TYPE = 'network.connection.type'; +export const DEVICE_MODEL_IDENTIFIER = 'device.model.identifier'; +export const SESSION_ID = 'session.id'; +export const APP_LAUNCH_TIME = 'application.launch.time'; +export const EVENT_NAME = 'event.name'; + +// Location +export const CLIENT_GEO_COUNTRY_ISO_CODE = 'client.geo.country_iso_code'; +export const CLIENT_GEO_REGION_ISO_CODE = 'client.geo.region_iso_code'; +export const CLIENT_GEO_COUNTRY_NAME = 'client.geo.country_name'; +export const CLIENT_GEO_CITY_NAME = 'client.geo.city_name'; +export const CLIENT_GEO_REGION_NAME = 'client.geo.region_name'; + +export const CHILD_ID = 'child.id'; diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/apm_base_doc.ts b/packages/kbn-apm-utils/src/es_schemas/raw/apm_base_doc.ts new file mode 100644 index 0000000000000..a750c39c775d2 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/apm_base_doc.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Observer } from './fields/observer'; + +// all documents types extend APMBaseDoc and inherit all properties +export interface APMBaseDoc { + '@timestamp': string; + agent: { + name: string; + version: string; + }; + parent?: { id: string }; // parent ID is not available on root transactions + trace?: { id: string }; + labels?: { + [key: string]: string | number | boolean; + }; + observer?: Observer; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/error_raw.ts b/packages/kbn-apm-utils/src/es_schemas/raw/error_raw.ts new file mode 100644 index 0000000000000..f0157a6a08376 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/error_raw.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { APMBaseDoc } from './apm_base_doc'; +import { + Container, + Host, + Http, + Kubernetes, + Page, + Process, + Service, + Stackframe, + TimestampUs, + Url, + User, +} from './fields'; + +export interface Processor { + name: 'error'; + event: 'error'; +} + +export interface Exception { + attributes?: { + response?: string; + }; + code?: string; + message?: string; // either message or type are given + type?: string; + module?: string; + handled?: boolean; + stacktrace?: Stackframe[]; +} + +export interface Log { + message: string; + stacktrace?: Stackframe[]; +} + +export interface ErrorRaw extends APMBaseDoc { + processor: Processor; + timestamp: TimestampUs; + transaction?: { + id: string; + sampled?: boolean; + type: string; + }; + error: { + id: string; + culprit?: string; + grouping_key: string; + // either exception or log are given + exception?: Exception[]; + page?: Page; // special property for RUM: shared by error and transaction + log?: Log; + stack_trace?: string; + custom?: Record; + }; + + // Shared by errors and transactions + container?: Container; + host?: Host; + http?: Http; + kubernetes?: Kubernetes; + process?: Process; + service: Service; + url?: Url; + user?: User; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/event_raw.ts b/packages/kbn-apm-utils/src/es_schemas/raw/event_raw.ts new file mode 100644 index 0000000000000..f8d3124914239 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/event_raw.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { APMBaseDoc } from './apm_base_doc'; +import { TimestampUs } from './fields/timestamp_us'; + +export interface EventRaw extends APMBaseDoc { + timestamp: TimestampUs; + transaction?: { + id: string; + sampled?: boolean; + type: string; + }; + log: { + message?: string; + }; + event: { + action: string; + category: string; + }; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/cloud.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/cloud.ts new file mode 100644 index 0000000000000..eaad379f5069b --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/cloud.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Cloud { + availability_zone?: string; + instance?: { + name: string; + id: string; + }; + machine?: { + type: string; + }; + project?: { + id: string; + name: string; + }; + provider?: string; + region?: string; + account?: { + id: string; + name: string; + }; + image?: { + id: string; + }; + service?: { + name: string; + }; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/container.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/container.ts new file mode 100644 index 0000000000000..ae6526ad9ff92 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/container.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Container { + id?: string | null; + image?: string | null; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/event_outcome.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/event_outcome.ts new file mode 100644 index 0000000000000..53c19ab293d9b --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/event_outcome.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type EventOutcome = 'success' | 'failure' | 'unknown'; diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/faas.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/faas.ts new file mode 100644 index 0000000000000..9054839b82902 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/faas.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Faas { + id: string; + coldstart?: boolean; + execution?: string; + trigger?: { + type?: string; + request_id?: string; + }; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/host.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/host.ts new file mode 100644 index 0000000000000..7a12a8eba824f --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/host.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Host { + architecture?: string; + hostname?: string; + name?: string; + ip?: string; + os?: { + platform?: string; + }; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/http.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/http.ts new file mode 100644 index 0000000000000..3e16e5dceb80c --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/http.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Http { + request?: { method: string; [key: string]: unknown }; + response?: { status_code: number; [key: string]: unknown }; + version?: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/index.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/index.ts new file mode 100644 index 0000000000000..aa8355934fbb4 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './cloud'; +export * from './container'; +export * from './event_outcome'; +export * from './faas'; +export * from './host'; +export * from './http'; +export * from './kubernetes'; +export * from './observer'; +export * from './page'; +export * from './process'; +export * from './service'; +export * from './span_links'; +export * from './stackframe'; +export * from './timestamp_us'; +export * from './url'; +export * from './user_agent'; +export * from './user'; diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/kubernetes.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/kubernetes.ts new file mode 100644 index 0000000000000..09667f08d441c --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/kubernetes.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Kubernetes { + pod?: { uid?: string | null; [key: string]: unknown }; + namespace?: string; + replicaset?: { + name?: string; + }; + deployment?: { + name?: string; + }; + container?: { + id?: string; + name?: string; + }; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/observer.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/observer.ts new file mode 100644 index 0000000000000..b035c0210bb35 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/observer.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Observer { + ephemeral_id?: string; + hostname?: string; + id?: string; + name?: string; + type?: string; + version: string; + version_major: number; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/page.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/page.ts new file mode 100644 index 0000000000000..1c2548cb777cd --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/page.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +// only for RUM agent: shared by error and transaction +export interface Page { + url: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/process.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/process.ts new file mode 100644 index 0000000000000..25db0098f8d3d --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/process.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Process { + args?: string[]; + pid: number; + ppid?: number; + title?: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/service.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/service.ts new file mode 100644 index 0000000000000..ff01bfc8517e8 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/service.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Service { + name: string; + environment?: string; + framework?: { + name: string; + version?: string; + }; + node?: { + name?: string; + }; + runtime?: { + name: string; + version: string; + }; + language?: { + name: string; + version?: string; + }; + version?: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/span_links.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/span_links.ts new file mode 100644 index 0000000000000..13ffc4d7075f1 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/span_links.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface SpanLink { + trace: { id: string }; + span: { id: string }; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/stackframe.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/stackframe.ts new file mode 100644 index 0000000000000..b2b1cf8000103 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/stackframe.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +interface Line { + column?: number; + number: number; +} + +interface Sourcemap { + error?: string; + updated?: boolean; +} + +interface StackframeBase { + abs_path?: string; + classname?: string; + context?: { + post?: string[]; + pre?: string[]; + }; + exclude_from_grouping?: boolean; + filename?: string; + function?: string; + module?: string; + library_frame?: boolean; + line?: Line; + sourcemap?: Sourcemap; + vars?: { + [key: string]: unknown; + }; +} + +export type StackframeWithLineContext = StackframeBase & { + line: Line & { + context: string; + }; +}; + +export type Stackframe = StackframeBase | StackframeWithLineContext; diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/timestamp_us.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/timestamp_us.ts new file mode 100644 index 0000000000000..17c06c8e38156 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/timestamp_us.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface TimestampUs { + us: number; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/url.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/url.ts new file mode 100644 index 0000000000000..4fa149e6b65d6 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/url.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Url { + domain?: string; + full: string; + original?: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/user.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/user.ts new file mode 100644 index 0000000000000..ced460ececd17 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/user.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface User { + id: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/fields/user_agent.ts b/packages/kbn-apm-utils/src/es_schemas/raw/fields/user_agent.ts new file mode 100644 index 0000000000000..0658d408dbe54 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/fields/user_agent.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface UserAgent { + device?: { + name: string; + }; + name?: string; + original: string; + os?: { + name: string; + version?: string; + full?: string; + }; + version?: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/index.ts b/packages/kbn-apm-utils/src/es_schemas/raw/index.ts new file mode 100644 index 0000000000000..addd3279f2586 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './apm_base_doc'; +export * from './error_raw'; +export * from './event_raw'; +export * from './metric_raw'; +export * from './span_raw'; +export * from './transaction_raw'; diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/metric_raw.ts b/packages/kbn-apm-utils/src/es_schemas/raw/metric_raw.ts new file mode 100644 index 0000000000000..29a8dc921f3d9 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/metric_raw.ts @@ -0,0 +1,124 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { APMBaseDoc } from './apm_base_doc'; +import { Cloud } from './fields/cloud'; +import { Container } from './fields/container'; +import { Host } from './fields/host'; +import { Kubernetes } from './fields/kubernetes'; +import { Service } from './fields/service'; + +type BaseMetric = APMBaseDoc & { + processor: { + name: 'metric'; + event: 'metric'; + }; + cloud?: Cloud; + container?: Container; + kubernetes?: Kubernetes; + service?: Service; + host?: Host; +}; + +type BaseBreakdownMetric = BaseMetric & { + transaction: { + name: string; + type: string; + }; + span: { + self_time: { + count: number; + sum: { + us: number; + }; + }; + }; +}; + +type TransactionBreakdownMetric = BaseBreakdownMetric & { + transaction: { + duration: { + count: number; + sum: { + us: number; + }; + }; + breakdown: { + count: number; + }; + }; +}; + +type SpanBreakdownMetric = BaseBreakdownMetric & { + span: { + type: string; + subtype?: string; + }; +}; + +type SystemMetric = BaseMetric & { + system: unknown; + service: { + node?: { + name: string; + }; + }; +}; + +type CGroupMetric = SystemMetric; +type JVMMetric = SystemMetric & { + jvm: unknown; +}; + +type TransactionDurationMetric = BaseMetric & { + transaction: { + name: string; + type: string; + result?: string; + duration: { + histogram: { + values: number[]; + counts: number[]; + }; + }; + }; + service: { + name: string; + node?: { + name: string; + }; + environment?: string; + version?: string; + }; +}; + +export type SpanDestinationMetric = BaseMetric & { + span: { + destination: { + service: { + resource: string; + response_time: { + count: number; + sum: { + us: number; + }; + }; + }; + }; + }; +}; + +export type MetricRaw = + | BaseMetric + | TransactionBreakdownMetric + | SpanBreakdownMetric + | TransactionDurationMetric + | SpanDestinationMetric + | SystemMetric + | CGroupMetric + | JVMMetric; diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/span_raw.ts b/packages/kbn-apm-utils/src/es_schemas/raw/span_raw.ts new file mode 100644 index 0000000000000..0d45d3bb00cc4 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/span_raw.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { APMBaseDoc } from './apm_base_doc'; +import { EventOutcome } from './fields/event_outcome'; +import { Http } from './fields/http'; +import { SpanLink } from './fields/span_links'; +import { Stackframe } from './fields/stackframe'; +import { TimestampUs } from './fields/timestamp_us'; +import { Url } from './fields/url'; + +interface Processor { + name: 'transaction'; + event: 'span'; +} + +export interface SpanRaw extends APMBaseDoc { + processor: Processor; + trace: { id: string }; // trace is required + event?: { outcome?: EventOutcome }; + service: { + name: string; + environment?: string; + }; + span: { + destination?: { + service: { + resource: string; + }; + }; + action?: string; + duration: { us: number }; + id: string; + name: string; + stacktrace?: Stackframe[]; + subtype?: string; + sync?: boolean; + type: string; + http?: { + url?: { + original?: string; + }; + response: { + status_code: number; + }; + method?: string; + }; + db?: { + statement?: string; + type?: string; + }; + message?: { + queue?: { name: string }; + age?: { ms: number }; + body?: string; + headers?: Record; + }; + composite?: { + count: number; + sum: { us: number }; + compression_strategy: string; + }; + links?: SpanLink[]; + }; + timestamp: TimestampUs; + transaction?: { + id: string; + }; + child?: { id: string[] }; + code?: { + stacktrace?: string; + }; + http?: Http; + url?: Url; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/raw/transaction_raw.ts b/packages/kbn-apm-utils/src/es_schemas/raw/transaction_raw.ts new file mode 100644 index 0000000000000..6505e2808f795 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/raw/transaction_raw.ts @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { APMBaseDoc } from './apm_base_doc'; +import { Cloud } from './fields/cloud'; +import { Container } from './fields/container'; +import { EventOutcome } from './fields/event_outcome'; +import { Host } from './fields/host'; +import { Http } from './fields/http'; +import { Kubernetes } from './fields/kubernetes'; +import { Page } from './fields/page'; +import { Process } from './fields/process'; +import { Service } from './fields/service'; +import { TimestampUs } from './fields/timestamp_us'; +import { Url } from './fields/url'; +import { User } from './fields/user'; +import { UserAgent } from './fields/user_agent'; +import { Faas } from './fields/faas'; +import { SpanLink } from './fields/span_links'; + +interface Processor { + name: 'transaction'; + event: 'transaction'; +} + +export interface TransactionRaw extends APMBaseDoc { + processor: Processor; + timestamp: TimestampUs; + trace: { id: string }; // trace is required + event?: { outcome?: EventOutcome }; + transaction: { + duration: { us: number }; + id: string; + marks?: { + // "agent": not defined by APM Server - only sent by RUM agent + agent?: { + [name: string]: number; + }; + }; + name?: string; + page?: Page; // special property for RUM: shared by error and transaction + result?: string; + sampled: boolean; + span_count?: { + started?: number; + dropped?: number; + }; + type: string; + custom?: Record; + message?: { + queue?: { name: string }; + age?: { ms: number }; + body?: string; + headers?: Record; + }; + }; + + // Shared by errors and transactions + container?: Container; + ecs?: { version?: string }; + host?: Host; + http?: Http; + kubernetes?: Kubernetes; + process?: Process; + service: Service; + url?: Url; + user?: User; + user_agent?: UserAgent; + cloud?: Cloud; + faas?: Faas; + span?: { + links?: SpanLink[]; + }; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/apm_error.ts b/packages/kbn-apm-utils/src/es_schemas/ui/apm_error.ts new file mode 100644 index 0000000000000..fad4190a229ef --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/apm_error.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ErrorRaw } from '../raw/error_raw'; +import { Agent } from './fields/agent'; + +export interface APMError extends ErrorRaw { + agent: Agent; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/event.ts b/packages/kbn-apm-utils/src/es_schemas/ui/event.ts new file mode 100644 index 0000000000000..8d0fd78f5f0f9 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/event.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EventRaw } from '../raw/event_raw'; +import { Agent } from './fields/agent'; + +export interface Event extends EventRaw { + agent: Agent; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/fields/agent.ts b/packages/kbn-apm-utils/src/es_schemas/ui/fields/agent.ts new file mode 100644 index 0000000000000..85cb7340fdda6 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/fields/agent.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { AgentName } from '@kbn/elastic-agent-utils'; + +export type { ElasticAgentName, OpenTelemetryAgentName, AgentName } from '@kbn/elastic-agent-utils'; + +export interface Agent { + ephemeral_id?: string; + name: AgentName; + version: string; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/fields/index.ts b/packages/kbn-apm-utils/src/es_schemas/ui/fields/index.ts new file mode 100644 index 0000000000000..1e64e14e07f8a --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/fields/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +export * from './agent'; diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/index.ts b/packages/kbn-apm-utils/src/es_schemas/ui/index.ts new file mode 100644 index 0000000000000..26f716289aaff --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './apm_error'; +export * from './event'; +export * from './metric'; +export * from './span'; +export * from './transaction'; diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/metric.ts b/packages/kbn-apm-utils/src/es_schemas/ui/metric.ts new file mode 100644 index 0000000000000..bd9391e269554 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/metric.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { MetricRaw } from '../raw/metric_raw'; + +export type Metric = MetricRaw; diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/span.ts b/packages/kbn-apm-utils/src/es_schemas/ui/span.ts new file mode 100644 index 0000000000000..5e09b84b87df2 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/span.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SpanRaw } from '../raw/span_raw'; +import { Agent } from './fields/agent'; + +export interface Span extends SpanRaw { + agent: Agent; +} diff --git a/packages/kbn-apm-utils/src/es_schemas/ui/transaction.ts b/packages/kbn-apm-utils/src/es_schemas/ui/transaction.ts new file mode 100644 index 0000000000000..ea5ccf5fd6434 --- /dev/null +++ b/packages/kbn-apm-utils/src/es_schemas/ui/transaction.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { TransactionRaw } from '../raw/transaction_raw'; +import { Agent } from './fields/agent'; + +// Make `transaction.name` required instead of optional. +// `transaction.name` can be missing in Elasticsearch but the UI will only aggregate on transactions with a name, +// and thus it doesn't make sense to treat it as optional +type InnerTransaction = TransactionRaw['transaction']; +interface InnerTransactionWithName extends InnerTransaction { + name: string; +} + +export interface Transaction extends TransactionRaw { + agent: Agent; + transaction: InnerTransactionWithName; +} diff --git a/packages/kbn-apm-utils/src/with_span.ts b/packages/kbn-apm-utils/src/with_span.ts new file mode 100644 index 0000000000000..09a6989091f60 --- /dev/null +++ b/packages/kbn-apm-utils/src/with_span.ts @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import agent from 'elastic-apm-node'; +import asyncHooks from 'async_hooks'; + +export interface SpanOptions { + name: string; + type?: string; + subtype?: string; + labels?: Record; + intercept?: boolean; +} + +type Span = Exclude; + +export function parseSpanOptions(optionsOrName: SpanOptions | string) { + const options = typeof optionsOrName === 'string' ? { name: optionsOrName } : optionsOrName; + + return options; +} + +const runInNewContext = any>(cb: T): ReturnType => { + const resource = new asyncHooks.AsyncResource('fake_async'); + + return resource.runInAsyncScope(cb); +}; + +export async function withSpan( + optionsOrName: SpanOptions | string, + cb: (span?: Span) => Promise +): Promise { + const options = parseSpanOptions(optionsOrName); + + const { name, type, subtype, labels, intercept } = options; + + if (!agent.isStarted()) { + return cb(); + } + + let createdSpan: Span | undefined; + + // When a span starts, it's marked as the active span in its context. + // When it ends, it's not untracked, which means that if a span + // starts directly after this one ends, the newly started span is a + // child of this span, even though it should be a sibling. + // To mitigate this, we queue a microtask by awaiting a promise. + if (!intercept) { + await Promise.resolve(); + + createdSpan = agent.startSpan(name) ?? undefined; + + if (!createdSpan) { + return cb(); + } + } + + // If a span is created in the same context as the span that we just + // started, it will be a sibling, not a child. E.g., the Elasticsearch span + // that is created when calling search() happens in the same context. To + // mitigate this we create a new context. + + return runInNewContext(() => { + const promise = cb(createdSpan); + + let span: Span | undefined = createdSpan; + + if (intercept) { + span = agent.currentSpan ?? undefined; + } + + if (!span) { + return promise; + } + + const targetedSpan = span; + + if (name) { + targetedSpan.name = name; + } + + // @ts-ignore + if (type) { + targetedSpan.type = type; + } + if (subtype) { + targetedSpan.subtype = subtype; + } + + if (labels) { + targetedSpan.addLabels(labels); + } + + return promise + .then((res) => { + if (!targetedSpan.outcome || targetedSpan.outcome === 'unknown') { + targetedSpan.outcome = 'success'; + } + return res; + }) + .catch((err) => { + if (!targetedSpan.outcome || targetedSpan.outcome === 'unknown') { + targetedSpan.outcome = 'failure'; + } + throw err; + }) + .finally(() => { + targetedSpan.end(); + }); + }); +} diff --git a/packages/kbn-apm-utils/tsconfig.json b/packages/kbn-apm-utils/tsconfig.json index 2649fb45f0a42..33927475b819d 100644 --- a/packages/kbn-apm-utils/tsconfig.json +++ b/packages/kbn-apm-utils/tsconfig.json @@ -2,14 +2,8 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", - "types": [ - "node" - ] + "types": ["node"] }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "target/**/*", - ] + "include": ["**/*.ts"], + "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/observability_solution/apm/common/data_source.ts b/x-pack/plugins/observability_solution/apm/common/data_source.ts index 217862e03e415..8a54757c17985 100644 --- a/x-pack/plugins/observability_solution/apm/common/data_source.ts +++ b/x-pack/plugins/observability_solution/apm/common/data_source.ts @@ -5,25 +5,4 @@ * 2.0. */ -import { ApmDocumentType } from './document_type'; -import { RollupInterval } from './rollup'; - -type AnyApmDocumentType = - | ApmDocumentType.ServiceTransactionMetric - | ApmDocumentType.TransactionMetric - | ApmDocumentType.TransactionEvent - | ApmDocumentType.ServiceDestinationMetric - | ApmDocumentType.ServiceSummaryMetric - | ApmDocumentType.ErrorEvent - | ApmDocumentType.SpanEvent; - -export interface ApmDataSource { - rollupInterval: RollupInterval; - documentType: TDocumentType; -} - -export type ApmDataSourceWithSummary = - ApmDataSource & { - hasDurationSummaryField: boolean; - hasDocs: boolean; - }; +export type { ApmDataSource, ApmDataSourceWithSummary } from '@kbn/apm-data-access-plugin/common'; diff --git a/x-pack/plugins/observability_solution/apm/common/document_type.ts b/x-pack/plugins/observability_solution/apm/common/document_type.ts index e8a29e8d08c43..6e9341a6d45ec 100644 --- a/x-pack/plugins/observability_solution/apm/common/document_type.ts +++ b/x-pack/plugins/observability_solution/apm/common/document_type.ts @@ -5,21 +5,8 @@ * 2.0. */ -export enum ApmDocumentType { - TransactionMetric = 'transactionMetric', - ServiceTransactionMetric = 'serviceTransactionMetric', - TransactionEvent = 'transactionEvent', - ServiceDestinationMetric = 'serviceDestinationMetric', - ServiceSummaryMetric = 'serviceSummaryMetric', - ErrorEvent = 'error', - SpanEvent = 'span', -} - -export type ApmServiceTransactionDocumentType = - | ApmDocumentType.ServiceTransactionMetric - | ApmDocumentType.TransactionMetric - | ApmDocumentType.TransactionEvent; - -export type ApmTransactionDocumentType = - | ApmDocumentType.TransactionMetric - | ApmDocumentType.TransactionEvent; +export { + ApmDocumentType, + type ApmServiceTransactionDocumentType, + type ApmTransactionDocumentType, +} from '@kbn/apm-data-access-plugin/common'; diff --git a/x-pack/plugins/observability_solution/apm/common/es_fields/apm.ts b/x-pack/plugins/observability_solution/apm/common/es_fields/apm.ts index 539484fed182e..b7df5bb942cdd 100644 --- a/x-pack/plugins/observability_solution/apm/common/es_fields/apm.ts +++ b/x-pack/plugins/observability_solution/apm/common/es_fields/apm.ts @@ -4,192 +4,5 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -export const TIMESTAMP = 'timestamp.us'; -export const AGENT = 'agent'; -export const AGENT_NAME = 'agent.name'; -export const AGENT_VERSION = 'agent.version'; -export const AGENT_ACTIVATION_METHOD = 'agent.activation_method'; -export const DESTINATION_ADDRESS = 'destination.address'; - -export const CLOUD = 'cloud'; -export const CLOUD_AVAILABILITY_ZONE = 'cloud.availability_zone'; -export const CLOUD_PROVIDER = 'cloud.provider'; -export const CLOUD_REGION = 'cloud.region'; -export const CLOUD_MACHINE_TYPE = 'cloud.machine.type'; -export const CLOUD_ACCOUNT_ID = 'cloud.account.id'; -export const CLOUD_INSTANCE_ID = 'cloud.instance.id'; -export const CLOUD_INSTANCE_NAME = 'cloud.instance.name'; -export const CLOUD_SERVICE_NAME = 'cloud.service.name'; - -export const EVENT_SUCCESS_COUNT = 'event.success_count'; - -export const SERVICE = 'service'; -export const SERVICE_NAME = 'service.name'; -export const SERVICE_ENVIRONMENT = 'service.environment'; -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_VERSION = 'service.version'; -export const SERVICE_TARGET_TYPE = 'service.target.type'; -export const SERVICE_OVERFLOW_COUNT = 'service_transaction.aggregation.overflow_count'; - -export const URL_FULL = 'url.full'; -export const HTTP_REQUEST_METHOD = 'http.request.method'; -export const HTTP_RESPONSE_STATUS_CODE = 'http.response.status_code'; -export const USER_ID = 'user.id'; -export const USER_AGENT_ORIGINAL = 'user_agent.original'; -export const USER_AGENT_NAME = 'user_agent.name'; - -export const OBSERVER_HOSTNAME = 'observer.hostname'; -export const OBSERVER_LISTENING = 'observer.listening'; -export const PROCESSOR_EVENT = 'processor.event'; - -export const TRANSACTION_DURATION = 'transaction.duration.us'; -export const TRANSACTION_DURATION_HISTOGRAM = 'transaction.duration.histogram'; -export const TRANSACTION_DURATION_SUMMARY = 'transaction.duration.summary'; -export const TRANSACTION_TYPE = 'transaction.type'; -export const TRANSACTION_RESULT = 'transaction.result'; -export const TRANSACTION_NAME = 'transaction.name'; -export const TRANSACTION_ID = 'transaction.id'; -export const TRANSACTION_SAMPLED = 'transaction.sampled'; -export const TRANSACTION_PAGE_URL = 'transaction.page.url'; -export const TRANSACTION_FAILURE_COUNT = 'transaction.failure_count'; -export const TRANSACTION_SUCCESS_COUNT = 'transaction.success_count'; -export const TRANSACTION_OVERFLOW_COUNT = 'transaction.aggregation.overflow_count'; -// for transaction metrics -export const TRANSACTION_ROOT = 'transaction.root'; -export const TRANSACTION_PROFILER_STACK_TRACE_IDS = 'transaction.profiler_stack_trace_ids'; - -export const EVENT_OUTCOME = 'event.outcome'; - -export const TRACE_ID = 'trace.id'; - -export const SPAN_DURATION = 'span.duration.us'; -export const SPAN_TYPE = 'span.type'; -export const SPAN_SUBTYPE = 'span.subtype'; -export const SPAN_SELF_TIME_SUM = 'span.self_time.sum.us'; -export const SPAN_ACTION = 'span.action'; -export const SPAN_NAME = 'span.name'; -export const SPAN_ID = 'span.id'; -export const SPAN_DESTINATION_SERVICE_RESOURCE = 'span.destination.service.resource'; -export const SPAN_DESTINATION_SERVICE_RESPONSE_TIME_COUNT = - 'span.destination.service.response_time.count'; - -export const SPAN_DESTINATION_SERVICE_RESPONSE_TIME_SUM = - 'span.destination.service.response_time.sum.us'; - -export const SPAN_LINKS = 'span.links'; -export const SPAN_LINKS_TRACE_ID = 'span.links.trace.id'; -export const SPAN_LINKS_SPAN_ID = 'span.links.span.id'; - -export const SPAN_COMPOSITE_COUNT = 'span.composite.count'; -export const SPAN_COMPOSITE_SUM = 'span.composite.sum.us'; -export const SPAN_COMPOSITE_COMPRESSION_STRATEGY = 'span.composite.compression_strategy'; - -export const SPAN_SYNC = 'span.sync'; - -// Parent ID for a transaction or span -export const PARENT_ID = 'parent.id'; - -export const ERROR_ID = 'error.id'; -export const ERROR_GROUP_ID = 'error.grouping_key'; -export const ERROR_GROUP_NAME = 'error.grouping_name'; -export const ERROR_CULPRIT = 'error.culprit'; -export const ERROR_LOG_LEVEL = 'error.log.level'; -export const ERROR_LOG_MESSAGE = 'error.log.message'; -export const ERROR_EXCEPTION = 'error.exception'; -export const ERROR_EXC_MESSAGE = 'error.exception.message'; // only to be used in es queries, since error.exception is now an array -export const ERROR_EXC_HANDLED = 'error.exception.handled'; // only to be used in es queries, since error.exception is now an array -export const ERROR_EXC_TYPE = 'error.exception.type'; -export const ERROR_PAGE_URL = 'error.page.url'; -export const ERROR_TYPE = 'error.type'; - -// METRICS -export const METRIC_SYSTEM_FREE_MEMORY = 'system.memory.actual.free'; -export const METRIC_SYSTEM_TOTAL_MEMORY = 'system.memory.total'; -export const METRIC_SYSTEM_CPU_PERCENT = 'system.cpu.total.norm.pct'; -export const METRIC_PROCESS_CPU_PERCENT = 'system.process.cpu.total.norm.pct'; -export const METRIC_CGROUP_MEMORY_LIMIT_BYTES = 'system.process.cgroup.memory.mem.limit.bytes'; -export const METRIC_CGROUP_MEMORY_USAGE_BYTES = 'system.process.cgroup.memory.mem.usage.bytes'; - -export const METRIC_JAVA_HEAP_MEMORY_MAX = 'jvm.memory.heap.max'; -export const METRIC_JAVA_HEAP_MEMORY_COMMITTED = 'jvm.memory.heap.committed'; -export const METRIC_JAVA_HEAP_MEMORY_USED = 'jvm.memory.heap.used'; -export const METRIC_JAVA_NON_HEAP_MEMORY_MAX = 'jvm.memory.non_heap.max'; -export const METRIC_JAVA_NON_HEAP_MEMORY_COMMITTED = 'jvm.memory.non_heap.committed'; -export const METRIC_JAVA_NON_HEAP_MEMORY_USED = 'jvm.memory.non_heap.used'; -export const METRIC_JAVA_THREAD_COUNT = 'jvm.thread.count'; -export const METRIC_JAVA_GC_COUNT = 'jvm.gc.count'; -export const METRIC_JAVA_GC_TIME = 'jvm.gc.time'; - -export const METRICSET_NAME = 'metricset.name'; -export const METRICSET_INTERVAL = 'metricset.interval'; - -export const LABEL_NAME = 'labels.name'; -export const LABEL_GC = 'labels.gc'; -export const LABEL_TYPE = 'labels.type'; -export const LABEL_TELEMETRY_AUTO_VERSION = 'labels.telemetry_auto_version'; -export const LABEL_LIFECYCLE_STATE = 'labels.lifecycle_state'; - -export const HOST = 'host'; -export const HOST_HOSTNAME = 'host.hostname'; // Do not use. Please use `HOST_NAME` instead. -export const HOST_NAME = 'host.name'; -export const HOST_OS_PLATFORM = 'host.os.platform'; -export const HOST_ARCHITECTURE = 'host.architecture'; -export const HOST_OS_VERSION = 'host.os.version'; - -export const CONTAINER_ID = 'container.id'; -export const CONTAINER = 'container'; -export const CONTAINER_IMAGE = 'container.image.name'; - -export const KUBERNETES = 'kubernetes'; -export const KUBERNETES_POD_NAME = 'kubernetes.pod.name'; -export const KUBERNETES_POD_UID = 'kubernetes.pod.uid'; - -export const FAAS_ID = 'faas.id'; -export const FAAS_NAME = 'faas.name'; -export const FAAS_COLDSTART = 'faas.coldstart'; -export const FAAS_TRIGGER_TYPE = 'faas.trigger.type'; -export const FAAS_DURATION = 'faas.duration'; -export const FAAS_COLDSTART_DURATION = 'faas.coldstart_duration'; -export const FAAS_BILLED_DURATION = 'faas.billed_duration'; - -// OpenTelemetry Metrics -export const METRIC_OTEL_SYSTEM_CPU_UTILIZATION = 'system.cpu.utilization'; -export const METRIC_OTEL_SYSTEM_MEMORY_UTILIZATION = 'system.memory.utilization'; - -export const METRIC_OTEL_JVM_PROCESS_CPU_PERCENT = 'process.runtime.jvm.cpu.utilization'; -export const METRIC_OTEL_JVM_PROCESS_MEMORY_USAGE = 'process.runtime.jvm.memory.usage'; -export const METRIC_OTEL_JVM_PROCESS_MEMORY_COMMITTED = 'process.runtime.jvm.memory.committed'; -export const METRIC_OTEL_JVM_PROCESS_MEMORY_LIMIT = 'process.runtime.jvm.memory.limit'; -export const METRIC_OTEL_JVM_PROCESS_THREADS_COUNT = 'process.runtime.jvm.threads.count'; -export const METRIC_OTEL_JVM_SYSTEM_CPU_PERCENT = 'process.runtime.jvm.system.cpu.utilization'; -export const METRIC_OTEL_JVM_GC_DURATION = 'process.runtime.jvm.gc.duration'; -export const VALUE_OTEL_JVM_PROCESS_MEMORY_HEAP = 'heap'; -export const VALUE_OTEL_JVM_PROCESS_MEMORY_NON_HEAP = 'non_heap'; - -// Metadata -export const TIER = '_tier'; -export const INDEX = '_index'; -export const DATA_STEAM_TYPE = 'data_stream.type'; - -// Mobile -export const NETWORK_CONNECTION_TYPE = 'network.connection.type'; -export const DEVICE_MODEL_IDENTIFIER = 'device.model.identifier'; -export const SESSION_ID = 'session.id'; -export const APP_LAUNCH_TIME = 'application.launch.time'; -export const EVENT_NAME = 'event.name'; - -// Location -export const CLIENT_GEO_COUNTRY_ISO_CODE = 'client.geo.country_iso_code'; -export const CLIENT_GEO_REGION_ISO_CODE = 'client.geo.region_iso_code'; -export const CLIENT_GEO_COUNTRY_NAME = 'client.geo.country_name'; -export const CLIENT_GEO_CITY_NAME = 'client.geo.city_name'; -export const CLIENT_GEO_REGION_NAME = 'client.geo.region_name'; - -export const CHILD_ID = 'child.id'; +export * from '@kbn/apm-utils/es_fields'; diff --git a/x-pack/plugins/observability_solution/apm/common/rollup.ts b/x-pack/plugins/observability_solution/apm/common/rollup.ts index 500337e3fc06b..d3bab49a01377 100644 --- a/x-pack/plugins/observability_solution/apm/common/rollup.ts +++ b/x-pack/plugins/observability_solution/apm/common/rollup.ts @@ -5,9 +5,4 @@ * 2.0. */ -export enum RollupInterval { - OneMinute = '1m', - TenMinutes = '10m', - SixtyMinutes = '60m', - None = 'none', -} +export { RollupInterval } from '@kbn/apm-data-access-plugin/common'; diff --git a/x-pack/plugins/observability_solution/apm/common/time_range_metadata.ts b/x-pack/plugins/observability_solution/apm/common/time_range_metadata.ts index f13ab5a89d6d1..7aa9d80a8906f 100644 --- a/x-pack/plugins/observability_solution/apm/common/time_range_metadata.ts +++ b/x-pack/plugins/observability_solution/apm/common/time_range_metadata.ts @@ -5,9 +5,4 @@ * 2.0. */ -import { ApmDataSource } from './data_source'; - -export interface TimeRangeMetadata { - isUsingServiceDestinationMetrics: boolean; - sources: Array; -} +export type { TimeRangeMetadata } from '@kbn/apm-data-access-plugin/common'; diff --git a/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/index.ts b/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/index.ts index a2946137cf911..837b0295fa22b 100644 --- a/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/index.ts +++ b/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/index.ts @@ -5,25 +5,4 @@ * 2.0. */ -import moment from 'moment'; -import { calculateAuto } from './calculate_auto'; - -export function getBucketSize({ - start, - end, - numBuckets = 50, - minBucketSize, -}: { - start: number; - end: number; - numBuckets?: number; - minBucketSize?: number; -}) { - const duration = moment.duration(end - start, 'ms'); - const bucketSize = Math.max( - calculateAuto.near(numBuckets, duration)?.asSeconds() ?? 0, - minBucketSize || 1 - ); - - return { bucketSize, intervalString: `${bucketSize}s` }; -} +export { getBucketSize } from '@kbn/apm-data-access-plugin/common'; diff --git a/x-pack/plugins/observability_solution/apm/public/hooks/use_preferred_data_source_and_bucket_size.ts b/x-pack/plugins/observability_solution/apm/public/hooks/use_preferred_data_source_and_bucket_size.ts index b8dfa5682a340..cf27bce80de40 100644 --- a/x-pack/plugins/observability_solution/apm/public/hooks/use_preferred_data_source_and_bucket_size.ts +++ b/x-pack/plugins/observability_solution/apm/public/hooks/use_preferred_data_source_and_bucket_size.ts @@ -6,10 +6,10 @@ */ import { useMemo } from 'react'; +import { getPreferredBucketSizeAndDataSource } from '@kbn/apm-data-access-plugin/common'; import { ApmDataSourceWithSummary } from '../../common/data_source'; import { ApmDocumentType } from '../../common/document_type'; import { getBucketSize } from '../../common/utils/get_bucket_size'; -import { getPreferredBucketSizeAndDataSource } from '../../common/utils/get_preferred_bucket_size_and_data_source'; import { useTimeRangeMetadata } from '../context/time_range_metadata/use_time_range_metadata_context'; /** diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index 1d6592814526c..0c838bc0129f7 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -4,329 +4,4 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import type { - EqlSearchRequest, - FieldCapsRequest, - FieldCapsResponse, - MsearchMultisearchBody, - MsearchMultisearchHeader, - TermsEnumRequest, - TermsEnumResponse, -} from '@elastic/elasticsearch/lib/api/types'; -import { ElasticsearchClient, KibanaRequest } from '@kbn/core/server'; -import type { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types'; -import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { unwrapEsResponse } from '@kbn/observability-plugin/server'; -import { compact, omit } from 'lodash'; -import { ValuesType } from 'utility-types'; -import type { APMIndices } from '@kbn/apm-data-access-plugin/server'; -import { ApmDataSource } from '../../../../../common/data_source'; -import { APMError } from '../../../../../typings/es_schemas/ui/apm_error'; -import { Metric } from '../../../../../typings/es_schemas/ui/metric'; -import { Span } from '../../../../../typings/es_schemas/ui/span'; -import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; -import { Event } from '../../../../../typings/es_schemas/ui/event'; -import { withApmSpan } from '../../../../utils/with_apm_span'; -import { callAsyncWithDebug, getDebugBody, getDebugTitle } from '../call_async_with_debug'; -import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort'; -import { ProcessorEventOfDocumentType } from '../document_type'; -import { getRequestBase, processorEventsToIndex } from './get_request_base'; - -export type APMEventESSearchRequest = Omit & { - apm: { - includeLegacyData?: boolean; - } & ({ events: ProcessorEvent[] } | { sources: ApmDataSource[] }); - body: { - size: number; - track_total_hits: boolean | number; - }; -}; - -export type APMLogEventESSearchRequest = Omit & { - body: { - size: number; - track_total_hits: boolean | number; - }; -}; - -type APMEventWrapper = Omit & { - apm: { events: ProcessorEvent[] }; -}; - -type APMEventTermsEnumRequest = APMEventWrapper; -type APMEventEqlSearchRequest = APMEventWrapper; -type APMEventFieldCapsRequest = APMEventWrapper; - -type TypeOfProcessorEvent = { - [ProcessorEvent.error]: APMError; - [ProcessorEvent.transaction]: Transaction; - [ProcessorEvent.span]: Span; - [ProcessorEvent.metric]: Metric; -}[T]; - -type TypedLogEventSearchResponse = - InferSearchResponseOf; - -type TypedSearchResponse = InferSearchResponseOf< - TypeOfProcessorEvent< - TParams['apm'] extends { events: ProcessorEvent[] } - ? ValuesType - : TParams['apm'] extends { sources: ApmDataSource[] } - ? ProcessorEventOfDocumentType['documentType']> - : never - >, - TParams ->; - -interface TypedMSearchResponse { - responses: Array>; -} - -export interface APMEventClientConfig { - esClient: ElasticsearchClient; - debug: boolean; - request: KibanaRequest; - indices: APMIndices; - options: { - includeFrozen: boolean; - }; -} - -export class APMEventClient { - private readonly esClient: ElasticsearchClient; - private readonly debug: boolean; - private readonly request: KibanaRequest; - public readonly indices: APMIndices; - private readonly includeFrozen: boolean; - - constructor(config: APMEventClientConfig) { - this.esClient = config.esClient; - this.debug = config.debug; - this.request = config.request; - this.indices = config.indices; - this.includeFrozen = config.options.includeFrozen; - } - - private callAsyncWithDebug({ - requestType, - params, - cb, - operationName, - }: { - requestType: string; - params: Record; - cb: (requestOpts: { signal: AbortSignal; meta: true }) => Promise; - operationName: string; - }): Promise { - return callAsyncWithDebug({ - getDebugMessage: () => ({ - body: getDebugBody({ - params, - requestType, - operationName, - }), - title: getDebugTitle(this.request), - }), - isCalledWithInternalUser: false, - debug: this.debug, - request: this.request, - operationName, - requestParams: params, - cb: () => { - const controller = new AbortController(); - - const promise = withApmSpan(operationName, () => { - return cancelEsRequestOnAbort( - cb({ signal: controller.signal, meta: true }), - this.request, - controller - ); - }); - - return unwrapEsResponse(promise); - }, - }); - } - - async search( - operationName: string, - params: TParams - ): Promise> { - const { index, filters } = getRequestBase({ - apm: params.apm, - indices: this.indices, - }); - - const searchParams = { - ...omit(params, 'apm', 'body'), - index, - body: { - ...params.body, - query: { - bool: { - filter: filters, - must: compact([params.body.query]), - }, - }, - }, - ...(this.includeFrozen ? { ignore_throttled: false } : {}), - ignore_unavailable: true, - preference: 'any', - expand_wildcards: ['open' as const, 'hidden' as const], - }; - - return this.callAsyncWithDebug({ - cb: (opts) => - this.esClient.search(searchParams, opts) as unknown as Promise<{ - body: TypedSearchResponse; - }>, - operationName, - params: searchParams, - requestType: 'search', - }); - } - - async logEventSearch( - operationName: string, - params: TParams - ): Promise> { - // Reusing indices configured for errors since both events and errors are stored as logs. - const index = processorEventsToIndex([ProcessorEvent.error], this.indices); - - const searchParams = { - ...omit(params, 'body'), - index, - body: { - ...params.body, - query: { - bool: { - must: compact([params.body.query]), - }, - }, - }, - ...(this.includeFrozen ? { ignore_throttled: false } : {}), - ignore_unavailable: true, - preference: 'any', - expand_wildcards: ['open' as const, 'hidden' as const], - }; - - return this.callAsyncWithDebug({ - cb: (opts) => - this.esClient.search(searchParams, opts) as unknown as Promise<{ - body: TypedLogEventSearchResponse; - }>, - operationName, - params: searchParams, - requestType: 'search', - }); - } - - async msearch( - operationName: string, - ...allParams: TParams[] - ): Promise> { - const searches = allParams - .map((params) => { - const { index, filters } = getRequestBase({ - apm: params.apm, - indices: this.indices, - }); - - const searchParams: [MsearchMultisearchHeader, MsearchMultisearchBody] = [ - { - index, - preference: 'any', - ...(this.includeFrozen ? { ignore_throttled: false } : {}), - ignore_unavailable: true, - expand_wildcards: ['open' as const, 'hidden' as const], - }, - { - ...omit(params, 'apm', 'body'), - ...params.body, - query: { - bool: { - filter: compact([params.body.query, ...filters]), - }, - }, - }, - ]; - - return searchParams; - }) - .flat(); - - return this.callAsyncWithDebug({ - cb: (opts) => - this.esClient.msearch( - { - searches, - }, - opts - ) as unknown as Promise<{ - body: TypedMSearchResponse; - }>, - operationName, - params: searches, - requestType: 'msearch', - }); - } - - async eqlSearch(operationName: string, params: APMEventEqlSearchRequest) { - const index = processorEventsToIndex(params.apm.events, this.indices); - - const requestParams = { - ...omit(params, 'apm'), - index, - }; - - return this.callAsyncWithDebug({ - operationName, - requestType: 'eql_search', - params: requestParams, - cb: (opts) => this.esClient.eql.search(requestParams, opts), - }); - } - - async fieldCaps( - operationName: string, - params: APMEventFieldCapsRequest - ): Promise { - const index = processorEventsToIndex(params.apm.events, this.indices); - - const requestParams = { - ...omit(params, 'apm'), - index, - }; - - return this.callAsyncWithDebug({ - operationName, - requestType: '_field_caps', - params: requestParams, - cb: (opts) => this.esClient.fieldCaps(requestParams, opts), - }); - } - - async termsEnum( - operationName: string, - params: APMEventTermsEnumRequest - ): Promise { - const index = processorEventsToIndex(params.apm.events, this.indices); - - const requestParams = { - ...omit(params, 'apm'), - index: index.join(','), - }; - - return this.callAsyncWithDebug({ - operationName, - requestType: '_terms_enum', - params: requestParams, - cb: (opts) => this.esClient.termsEnum(requestParams, opts), - }); - } - - getIndicesFromProcessorEvent(processorEvent: ProcessorEvent) { - return processorEventsToIndex([processorEvent], this.indices); - } -} +export { APMEventClient } from '@kbn/apm-data-access-plugin/server'; diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts index a0f5a6dfbf319..0e0f270040618 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts @@ -9,9 +9,13 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { unwrapEsResponse } from '@kbn/observability-plugin/server'; import type { ESSearchResponse, ESSearchRequest } from '@kbn/es-types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { + callAsyncWithDebug, + getDebugBody, + getDebugTitle, + cancelEsRequestOnAbort, +} from '@kbn/apm-data-access-plugin/server/helpers'; import { APMRouteHandlerResources } from '../../../../routes/apm_routes/register_apm_server_routes'; -import { callAsyncWithDebug, getDebugBody, getDebugTitle } from '../call_async_with_debug'; -import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort'; export type APMIndexDocumentParams = estypes.IndexRequest; diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_data_access_client.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_data_access_client.ts new file mode 100644 index 0000000000000..7575371255be4 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_data_access_client.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ApmDataAccessClient, APMEventClient } from '@kbn/apm-data-access-plugin/server'; +import { MinimalAPMRouteHandlerResources } from '../../routes/apm_routes/register_apm_server_routes'; + +export async function getApmDataAccessClient({ + apmEventClient, + plugins, + context, +}: { + apmEventClient: APMEventClient; +} & Pick): Promise { + const coreContext = await context.core; + const apmDataAccessPlugin = await plugins.apmDataAccess; + + return apmDataAccessPlugin.setup.getClient({ + apmEventClient, + deps: { + uiSettings: coreContext.uiSettings.client, + }, + }); +} diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_event_client.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_event_client.ts index b756876eb3212..8f21bf8f1c691 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_event_client.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_apm_event_client.ts @@ -9,6 +9,7 @@ import { UI_SETTINGS } from '@kbn/data-plugin/common'; import { APMEventClient } from './create_es_client/create_apm_event_client'; import { withApmSpan } from '../../utils/with_apm_span'; import { MinimalAPMRouteHandlerResources } from '../../routes/apm_routes/register_apm_server_routes'; +import { inspectableEsQueriesMap } from '../../routes/apm_routes/register_apm_server_routes'; export async function getApmEventClient({ context, @@ -35,6 +36,7 @@ export async function getApmEventClient({ indices, options: { includeFrozen, + inspectableEsQueriesMap, }, }); }); diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/spans/get_is_using_service_destination_metrics.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/spans/get_is_using_service_destination_metrics.ts index 7e53735bafabb..4d5474fabd0dd 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/spans/get_is_using_service_destination_metrics.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/spans/get_is_using_service_destination_metrics.ts @@ -6,11 +6,10 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { kqlQuery, rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { getDocumentTypeFilterForServiceDestinationStatistics } from '@kbn/apm-data-access-plugin/server/helpers'; import { - METRICSET_NAME, - METRICSET_INTERVAL, SPAN_DESTINATION_SERVICE_RESPONSE_TIME_COUNT, SPAN_DESTINATION_SERVICE_RESPONSE_TIME_SUM, SPAN_DURATION, @@ -24,25 +23,6 @@ export function getProcessorEventForServiceDestinationStatistics( return searchServiceDestinationMetrics ? ProcessorEvent.metric : ProcessorEvent.span; } -export function getDocumentTypeFilterForServiceDestinationStatistics( - searchServiceDestinationMetrics: boolean -) { - return searchServiceDestinationMetrics - ? [ - { - bool: { - filter: termQuery(METRICSET_NAME, 'service_destination'), - must_not: { - terms: { - [METRICSET_INTERVAL]: ['10m', '60m'], - }, - }, - }, - }, - ] - : []; -} - export function getLatencyFieldForServiceDestinationStatistics( searchServiceDestinationMetrics: boolean ) { @@ -117,3 +97,5 @@ export async function getIsUsingServiceDestinationMetrics({ anyServiceDestinationMetricsCount > 0 && serviceDestinationMetricsWithoutSpanNameCount === 0 ); } + +export { getDocumentTypeFilterForServiceDestinationStatistics }; diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/transactions/index.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/transactions/index.ts index f1aa16f4e4f37..06b70b6bb55bb 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/transactions/index.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/transactions/index.ts @@ -14,14 +14,14 @@ import { TRANSACTION_DURATION_HISTOGRAM, TRANSACTION_ROOT, PARENT_ID, - METRICSET_INTERVAL, - METRICSET_NAME, TRANSACTION_DURATION_SUMMARY, } from '../../../../common/es_fields/apm'; import { APMConfig } from '../../..'; import { APMEventClient } from '../create_es_client/create_apm_event_client'; import { ApmDocumentType } from '../../../../common/document_type'; +export { getBackwardCompatibleDocumentTypeFilter } from '@kbn/apm-data-access-plugin/server/helpers'; + export async function getHasTransactionsEvents({ start, end, @@ -125,23 +125,6 @@ export function getDurationFieldForTransactions( return TRANSACTION_DURATION; } -// The function returns Document type filter for 1m Transaction Metrics -export function getBackwardCompatibleDocumentTypeFilter(searchAggregatedTransactions: boolean) { - return searchAggregatedTransactions - ? [ - { - bool: { - filter: [{ exists: { field: TRANSACTION_DURATION_HISTOGRAM } }], - must_not: [ - { terms: { [METRICSET_INTERVAL]: ['10m', '60m'] } }, - { term: { [METRICSET_NAME]: 'service_transaction' } }, - ], - }, - }, - ] - : []; -} - export function getProcessorEventForTransactions( searchAggregatedTransactions: boolean ): ProcessorEvent.metric | ProcessorEvent.transaction { diff --git a/x-pack/plugins/observability_solution/apm/server/routes/time_range_metadata/route.ts b/x-pack/plugins/observability_solution/apm/server/routes/time_range_metadata/route.ts index eaff14fd7c647..cffad84b2c136 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/time_range_metadata/route.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/time_range_metadata/route.ts @@ -8,10 +8,10 @@ import { toBooleanRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; import { TimeRangeMetadata } from '../../../common/time_range_metadata'; import { getApmEventClient } from '../../lib/helpers/get_apm_event_client'; -import { getDocumentSources } from '../../lib/helpers/get_document_sources'; import { getIsUsingServiceDestinationMetrics } from '../../lib/helpers/spans/get_is_using_service_destination_metrics'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { kueryRt, rangeRt } from '../default_api_types'; +import { getApmDataAccessClient } from '../../lib/helpers/get_apm_data_access_client'; export const timeRangeMetadataRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/time_range_metadata', @@ -31,6 +31,7 @@ export const timeRangeMetadataRoute = createApmServerRoute({ }, handler: async (resources): Promise => { const apmEventClient = await getApmEventClient(resources); + const apmDataAccessClient = await getApmDataAccessClient({ apmEventClient, ...resources }); const { query: { @@ -51,8 +52,7 @@ export const timeRangeMetadataRoute = createApmServerRoute({ end, kuery, }), - getDocumentSources({ - apmEventClient, + apmDataAccessClient.getDocumentSources({ start, end, kuery, diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/apm_base_doc.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/apm_base_doc.ts index e39d90ff58b99..5c4b659d8031a 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/apm_base_doc.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/apm_base_doc.ts @@ -5,19 +5,4 @@ * 2.0. */ -import { Observer } from './fields/observer'; - -// all documents types extend APMBaseDoc and inherit all properties -export interface APMBaseDoc { - '@timestamp': string; - agent: { - name: string; - version: string; - }; - parent?: { id: string }; // parent ID is not available on root transactions - trace?: { id: string }; - labels?: { - [key: string]: string | number | boolean; - }; - observer?: Observer; -} +export { APMBaseDoc } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/error_raw.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/error_raw.ts index 34e24033db230..538c7dad4c6df 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/error_raw.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/error_raw.ts @@ -5,68 +5,4 @@ * 2.0. */ -import { APMBaseDoc } from './apm_base_doc'; -import { Container } from './fields/container'; -import { Host } from './fields/host'; -import { Http } from './fields/http'; -import { Kubernetes } from './fields/kubernetes'; -import { Page } from './fields/page'; -import { Process } from './fields/process'; -import { Service } from './fields/service'; -import { Stackframe } from './fields/stackframe'; -import { TimestampUs } from './fields/timestamp_us'; -import { Url } from './fields/url'; -import { User } from './fields/user'; - -export interface Processor { - name: 'error'; - event: 'error'; -} - -export interface Exception { - attributes?: { - response?: string; - }; - code?: string; - message?: string; // either message or type are given - type?: string; - module?: string; - handled?: boolean; - stacktrace?: Stackframe[]; -} - -export interface Log { - message: string; - stacktrace?: Stackframe[]; -} - -export interface ErrorRaw extends APMBaseDoc { - processor: Processor; - timestamp: TimestampUs; - transaction?: { - id: string; - sampled?: boolean; - type: string; - }; - error: { - id: string; - culprit?: string; - grouping_key: string; - // either exception or log are given - exception?: Exception[]; - page?: Page; // special property for RUM: shared by error and transaction - log?: Log; - stack_trace?: string; - custom?: Record; - }; - - // Shared by errors and transactions - container?: Container; - host?: Host; - http?: Http; - kubernetes?: Kubernetes; - process?: Process; - service: Service; - url?: Url; - user?: User; -} +export { ErrorRaw } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/event_raw.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/event_raw.ts index 31a1952cdc03d..1ca70d6d2a139 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/event_raw.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/event_raw.ts @@ -5,21 +5,4 @@ * 2.0. */ -import { APMBaseDoc } from './apm_base_doc'; -import { TimestampUs } from './fields/timestamp_us'; - -export interface EventRaw extends APMBaseDoc { - timestamp: TimestampUs; - transaction?: { - id: string; - sampled?: boolean; - type: string; - }; - log: { - message?: string; - }; - event: { - action: string; - category: string; - }; -} +export { EventRaw } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/cloud.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/cloud.ts index bc0c3ea8002ad..4f600274ddd14 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/cloud.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/cloud.ts @@ -5,29 +5,4 @@ * 2.0. */ -export interface Cloud { - availability_zone?: string; - instance?: { - name: string; - id: string; - }; - machine?: { - type: string; - }; - project?: { - id: string; - name: string; - }; - provider?: string; - region?: string; - account?: { - id: string; - name: string; - }; - image?: { - id: string; - }; - service?: { - name: string; - }; -} +export { Cloud } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/container.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/container.ts index c17517b7c5f2d..b266d7aaae23b 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/container.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/container.ts @@ -5,7 +5,4 @@ * 2.0. */ -export interface Container { - id?: string | null; - image?: string | null; -} +export { Container } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/event_outcome.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/event_outcome.ts index d0ca41fcba4ed..b55d027a2a16d 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/event_outcome.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/event_outcome.ts @@ -5,4 +5,4 @@ * 2.0. */ -export type EventOutcome = 'success' | 'failure' | 'unknown'; +export { EventOutcome } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/faas.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/faas.ts index 1229b8134ac13..8fa4c465fc072 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/faas.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/faas.ts @@ -5,12 +5,4 @@ * 2.0. */ -export interface Faas { - id: string; - coldstart?: boolean; - execution?: string; - trigger?: { - type?: string; - request_id?: string; - }; -} +export { Faas } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/host.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/host.ts index 6d1941ff0184c..82ba3fa45614a 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/host.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/host.ts @@ -5,12 +5,4 @@ * 2.0. */ -export interface Host { - architecture?: string; - hostname?: string; - name?: string; - ip?: string; - os?: { - platform?: string; - }; -} +export { Host } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/http.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/http.ts index 547f117b41326..603946c87d880 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/http.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/http.ts @@ -5,8 +5,4 @@ * 2.0. */ -export interface Http { - request?: { method: string; [key: string]: unknown }; - response?: { status_code: number; [key: string]: unknown }; - version?: string; -} +export { Http } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/kubernetes.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/kubernetes.ts index 5cf0b497dad18..9d1094910fd97 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/kubernetes.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/kubernetes.ts @@ -5,17 +5,4 @@ * 2.0. */ -export interface Kubernetes { - pod?: { uid?: string | null; [key: string]: unknown }; - namespace?: string; - replicaset?: { - name?: string; - }; - deployment?: { - name?: string; - }; - container?: { - id?: string; - name?: string; - }; -} +export { Kubernetes } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/observer.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/observer.ts index 81a0bf1e0bfd2..34f32dcb8b1fa 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/observer.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/observer.ts @@ -5,12 +5,4 @@ * 2.0. */ -export interface Observer { - ephemeral_id?: string; - hostname?: string; - id?: string; - name?: string; - type?: string; - version: string; - version_major: number; -} +export { Observer } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/page.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/page.ts index f934435594786..abfd9908be7b8 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/page.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/page.ts @@ -6,6 +6,4 @@ */ // only for RUM agent: shared by error and transaction -export interface Page { - url: string; -} +export { Page } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/process.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/process.ts index 10973e3b66a5f..d8fe8e49f1edf 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/process.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/process.ts @@ -5,9 +5,4 @@ * 2.0. */ -export interface Process { - args?: string[]; - pid: number; - ppid?: number; - title?: string; -} +export { Process } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/service.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/service.ts index 7158c886e8109..29f0f62707b26 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/service.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/service.ts @@ -5,23 +5,4 @@ * 2.0. */ -export interface Service { - name: string; - environment?: string; - framework?: { - name: string; - version?: string; - }; - node?: { - name?: string; - }; - runtime?: { - name: string; - version: string; - }; - language?: { - name: string; - version?: string; - }; - version?: string; -} +export { Service } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/span_links.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/span_links.ts index 5e0028ad58176..315f6c46a1a84 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/span_links.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/span_links.ts @@ -5,7 +5,4 @@ * 2.0. */ -export interface SpanLink { - trace: { id: string }; - span: { id: string }; -} +export { SpanLink } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/stackframe.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/stackframe.ts index 90d7f20047573..1f02e7d9c04e7 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/stackframe.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/stackframe.ts @@ -5,39 +5,4 @@ * 2.0. */ -interface Line { - column?: number; - number: number; -} - -interface Sourcemap { - error?: string; - updated?: boolean; -} - -interface StackframeBase { - abs_path?: string; - classname?: string; - context?: { - post?: string[]; - pre?: string[]; - }; - exclude_from_grouping?: boolean; - filename?: string; - function?: string; - module?: string; - library_frame?: boolean; - line?: Line; - sourcemap?: Sourcemap; - vars?: { - [key: string]: unknown; - }; -} - -export type StackframeWithLineContext = StackframeBase & { - line: Line & { - context: string; - }; -}; - -export type Stackframe = StackframeBase | StackframeWithLineContext; +export { StackframeWithLineContext, Stackframe } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/timestamp_us.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/timestamp_us.ts index f6f944b6fe95f..86b6eb6dc1e31 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/timestamp_us.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/timestamp_us.ts @@ -5,6 +5,4 @@ * 2.0. */ -export interface TimestampUs { - us: number; -} +export { TimestampUs } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/url.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/url.ts index 001d6370e5f06..1000e8a54560c 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/url.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/url.ts @@ -5,8 +5,4 @@ * 2.0. */ -export interface Url { - domain?: string; - full: string; - original?: string; -} +export { Url } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user.ts index dcb5fa03dcd5a..0be18d2b8214e 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user.ts @@ -5,6 +5,4 @@ * 2.0. */ -export interface User { - id: string; -} +export { User } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user_agent.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user_agent.ts index 884f627353d9b..0df035c1dde38 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user_agent.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/fields/user_agent.ts @@ -5,16 +5,4 @@ * 2.0. */ -export interface UserAgent { - device?: { - name: string; - }; - name?: string; - original: string; - os?: { - name: string; - version?: string; - full?: string; - }; - version?: string; -} +export { UserAgent } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/metric_raw.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/metric_raw.ts index d7d015fd21da5..d70822c947334 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/metric_raw.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/metric_raw.ts @@ -5,119 +5,4 @@ * 2.0. */ -import { APMBaseDoc } from './apm_base_doc'; -import { Cloud } from './fields/cloud'; -import { Container } from './fields/container'; -import { Host } from './fields/host'; -import { Kubernetes } from './fields/kubernetes'; -import { Service } from './fields/service'; - -type BaseMetric = APMBaseDoc & { - processor: { - name: 'metric'; - event: 'metric'; - }; - cloud?: Cloud; - container?: Container; - kubernetes?: Kubernetes; - service?: Service; - host?: Host; -}; - -type BaseBreakdownMetric = BaseMetric & { - transaction: { - name: string; - type: string; - }; - span: { - self_time: { - count: number; - sum: { - us: number; - }; - }; - }; -}; - -type TransactionBreakdownMetric = BaseBreakdownMetric & { - transaction: { - duration: { - count: number; - sum: { - us: number; - }; - }; - breakdown: { - count: number; - }; - }; -}; - -type SpanBreakdownMetric = BaseBreakdownMetric & { - span: { - type: string; - subtype?: string; - }; -}; - -type SystemMetric = BaseMetric & { - system: unknown; - service: { - node?: { - name: string; - }; - }; -}; - -type CGroupMetric = SystemMetric; -type JVMMetric = SystemMetric & { - jvm: unknown; -}; - -type TransactionDurationMetric = BaseMetric & { - transaction: { - name: string; - type: string; - result?: string; - duration: { - histogram: { - values: number[]; - counts: number[]; - }; - }; - }; - service: { - name: string; - node?: { - name: string; - }; - environment?: string; - version?: string; - }; -}; - -export type SpanDestinationMetric = BaseMetric & { - span: { - destination: { - service: { - resource: string; - response_time: { - count: number; - sum: { - us: number; - }; - }; - }; - }; - }; -}; - -export type MetricRaw = - | BaseMetric - | TransactionBreakdownMetric - | SpanBreakdownMetric - | TransactionDurationMetric - | SpanDestinationMetric - | SystemMetric - | CGroupMetric - | JVMMetric; +export { MetricRaw } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/span_raw.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/span_raw.ts index 301a4c96dfa35..2aaa65ce9e365 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/span_raw.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/span_raw.ts @@ -5,75 +5,4 @@ * 2.0. */ -import { APMBaseDoc } from './apm_base_doc'; -import { EventOutcome } from './fields/event_outcome'; -import { Http } from './fields/http'; -import { SpanLink } from './fields/span_links'; -import { Stackframe } from './fields/stackframe'; -import { TimestampUs } from './fields/timestamp_us'; -import { Url } from './fields/url'; - -interface Processor { - name: 'transaction'; - event: 'span'; -} - -export interface SpanRaw extends APMBaseDoc { - processor: Processor; - trace: { id: string }; // trace is required - event?: { outcome?: EventOutcome }; - service: { - name: string; - environment?: string; - }; - span: { - destination?: { - service: { - resource: string; - }; - }; - action?: string; - duration: { us: number }; - id: string; - name: string; - stacktrace?: Stackframe[]; - subtype?: string; - sync?: boolean; - type: string; - http?: { - url?: { - original?: string; - }; - response: { - status_code: number; - }; - method?: string; - }; - db?: { - statement?: string; - type?: string; - }; - message?: { - queue?: { name: string }; - age?: { ms: number }; - body?: string; - headers?: Record; - }; - composite?: { - count: number; - sum: { us: number }; - compression_strategy: string; - }; - links?: SpanLink[]; - }; - timestamp: TimestampUs; - transaction?: { - id: string; - }; - child?: { id: string[] }; - code?: { - stacktrace?: string; - }; - http?: Http; - url?: Url; -} +export { SpanRaw } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/transaction_raw.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/transaction_raw.ts index 4046bb9470fb7..0915275df3a42 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/transaction_raw.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/raw/transaction_raw.ts @@ -5,74 +5,4 @@ * 2.0. */ -import { APMBaseDoc } from './apm_base_doc'; -import { Cloud } from './fields/cloud'; -import { Container } from './fields/container'; -import { EventOutcome } from './fields/event_outcome'; -import { Host } from './fields/host'; -import { Http } from './fields/http'; -import { Kubernetes } from './fields/kubernetes'; -import { Page } from './fields/page'; -import { Process } from './fields/process'; -import { Service } from './fields/service'; -import { TimestampUs } from './fields/timestamp_us'; -import { Url } from './fields/url'; -import { User } from './fields/user'; -import { UserAgent } from './fields/user_agent'; -import { Faas } from './fields/faas'; -import { SpanLink } from './fields/span_links'; - -interface Processor { - name: 'transaction'; - event: 'transaction'; -} - -export interface TransactionRaw extends APMBaseDoc { - processor: Processor; - timestamp: TimestampUs; - trace: { id: string }; // trace is required - event?: { outcome?: EventOutcome }; - transaction: { - duration: { us: number }; - id: string; - marks?: { - // "agent": not defined by APM Server - only sent by RUM agent - agent?: { - [name: string]: number; - }; - }; - name?: string; - page?: Page; // special property for RUM: shared by error and transaction - result?: string; - sampled: boolean; - span_count?: { - started?: number; - dropped?: number; - }; - type: string; - custom?: Record; - message?: { - queue?: { name: string }; - age?: { ms: number }; - body?: string; - headers?: Record; - }; - }; - - // Shared by errors and transactions - container?: Container; - ecs?: { version?: string }; - host?: Host; - http?: Http; - kubernetes?: Kubernetes; - process?: Process; - service: Service; - url?: Url; - user?: User; - user_agent?: UserAgent; - cloud?: Cloud; - faas?: Faas; - span?: { - links?: SpanLink[]; - }; -} +export { TransactionRaw } from '@kbn/apm-utils/es_schemas_raw'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/apm_error.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/apm_error.ts index 13521d90a84aa..7238ec4bd0a0b 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/apm_error.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/apm_error.ts @@ -5,9 +5,4 @@ * 2.0. */ -import { ErrorRaw } from '../raw/error_raw'; -import { Agent } from './fields/agent'; - -export interface APMError extends ErrorRaw { - agent: Agent; -} +export { APMError } from '@kbn/apm-utils/es_schemas_ui'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/event.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/event.ts index 8d9fccea1c8bf..5a3228ffd2b8d 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/event.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/event.ts @@ -5,9 +5,4 @@ * 2.0. */ -import { EventRaw } from '../raw/event_raw'; -import { Agent } from './fields/agent'; - -export interface Event extends EventRaw { - agent: Agent; -} +export { Event } from '@kbn/apm-utils/es_schemas_ui'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/fields/agent.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/fields/agent.ts index 67f4a6b2ba10b..bca37e3a4bd56 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/fields/agent.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/fields/agent.ts @@ -5,12 +5,9 @@ * 2.0. */ -import type { AgentName } from '@kbn/elastic-agent-utils'; - -export type { ElasticAgentName, OpenTelemetryAgentName, AgentName } from '@kbn/elastic-agent-utils'; - -export interface Agent { - ephemeral_id?: string; - name: AgentName; - version: string; -} +export { + Agent, + ElasticAgentName, + OpenTelemetryAgentName, + AgentName, +} from '@kbn/apm-utils/es_schemas_ui'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/metric.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/metric.ts index b06a686c23ef7..5ac10b0e8ec16 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/metric.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/metric.ts @@ -5,6 +5,4 @@ * 2.0. */ -import { MetricRaw } from '../raw/metric_raw'; - -export type Metric = MetricRaw; +export { Metric } from '@kbn/apm-utils/es_schemas_ui'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/span.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/span.ts index cfee36de51429..bb4b263676f72 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/span.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/span.ts @@ -5,9 +5,4 @@ * 2.0. */ -import { SpanRaw } from '../raw/span_raw'; -import { Agent } from './fields/agent'; - -export interface Span extends SpanRaw { - agent: Agent; -} +export { Span } from '@kbn/apm-utils/es_schemas_ui'; diff --git a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/transaction.ts b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/transaction.ts index 2dfbc860ec05a..2dabe13d5dc51 100644 --- a/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/transaction.ts +++ b/x-pack/plugins/observability_solution/apm/typings/es_schemas/ui/transaction.ts @@ -5,18 +5,4 @@ * 2.0. */ -import { TransactionRaw } from '../raw/transaction_raw'; -import { Agent } from './fields/agent'; - -// Make `transaction.name` required instead of optional. -// `transaction.name` can be missing in Elasticsearch but the UI will only aggregate on transactions with a name, -// and thus it doesn't make sense to treat it as optional -type InnerTransaction = TransactionRaw['transaction']; -interface InnerTransactionWithName extends InnerTransaction { - name: string; -} - -export interface Transaction extends TransactionRaw { - agent: Agent; - transaction: InnerTransactionWithName; -} +export { Transaction } from '@kbn/apm-utils/es_schemas_ui'; diff --git a/x-pack/plugins/observability_solution/apm_data_access/common/data_source.ts b/x-pack/plugins/observability_solution/apm_data_access/common/data_source.ts new file mode 100644 index 0000000000000..dfbb705d3aef7 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/common/data_source.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ApmDocumentType } from '@kbn/apm-plugin/common/document_type'; +import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; + +type AnyApmDocumentType = + | ApmDocumentType.ServiceTransactionMetric + | ApmDocumentType.TransactionMetric + | ApmDocumentType.TransactionEvent + | ApmDocumentType.ServiceDestinationMetric + | ApmDocumentType.ServiceSummaryMetric + | ApmDocumentType.ErrorEvent + | ApmDocumentType.SpanEvent; + +export interface ApmDataSource { + rollupInterval: RollupInterval; + documentType: TDocumentType; +} + +export type ApmDataSourceWithSummary = + ApmDataSource & { + hasDurationSummaryField: boolean; + hasDocs: boolean; + }; diff --git a/x-pack/plugins/observability_solution/apm_data_access/common/document_type.ts b/x-pack/plugins/observability_solution/apm_data_access/common/document_type.ts new file mode 100644 index 0000000000000..e8a29e8d08c43 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/common/document_type.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export enum ApmDocumentType { + TransactionMetric = 'transactionMetric', + ServiceTransactionMetric = 'serviceTransactionMetric', + TransactionEvent = 'transactionEvent', + ServiceDestinationMetric = 'serviceDestinationMetric', + ServiceSummaryMetric = 'serviceSummaryMetric', + ErrorEvent = 'error', + SpanEvent = 'span', +} + +export type ApmServiceTransactionDocumentType = + | ApmDocumentType.ServiceTransactionMetric + | ApmDocumentType.TransactionMetric + | ApmDocumentType.TransactionEvent; + +export type ApmTransactionDocumentType = + | ApmDocumentType.TransactionMetric + | ApmDocumentType.TransactionEvent; diff --git a/x-pack/plugins/observability_solution/apm_data_access/common/index.ts b/x-pack/plugins/observability_solution/apm_data_access/common/index.ts index 19d4963c3cec5..df61d8d9c3702 100644 --- a/x-pack/plugins/observability_solution/apm_data_access/common/index.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/common/index.ts @@ -7,3 +7,17 @@ export const PLUGIN_ID = 'apmDataAccess'; export const PLUGIN_NAME = 'apmDataAccess'; + +export type { ApmDataSource, ApmDataSourceWithSummary } from './data_source'; +export { + ApmDocumentType, + type ApmServiceTransactionDocumentType, + type ApmTransactionDocumentType, +} from './document_type'; + +export type { TimeRangeMetadata } from './time_range_metadata'; + +export { getPreferredBucketSizeAndDataSource } from './utils/get_preferred_bucket_size_and_data_source'; +export { getBucketSize } from './utils/get_bucket_size'; + +export { RollupInterval } from './rollup'; diff --git a/x-pack/plugins/observability_solution/apm_data_access/common/rollup.ts b/x-pack/plugins/observability_solution/apm_data_access/common/rollup.ts new file mode 100644 index 0000000000000..500337e3fc06b --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/common/rollup.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export enum RollupInterval { + OneMinute = '1m', + TenMinutes = '10m', + SixtyMinutes = '60m', + None = 'none', +} diff --git a/x-pack/plugins/observability_solution/apm_data_access/common/time_range_metadata.ts b/x-pack/plugins/observability_solution/apm_data_access/common/time_range_metadata.ts new file mode 100644 index 0000000000000..f13ab5a89d6d1 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/common/time_range_metadata.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ApmDataSource } from './data_source'; + +export interface TimeRangeMetadata { + isUsingServiceDestinationMetrics: boolean; + sources: Array; +} diff --git a/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/calculate_auto.test.ts b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/calculate_auto.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/calculate_auto.test.ts rename to x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/calculate_auto.test.ts diff --git a/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/calculate_auto.js b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/calculate_auto.ts similarity index 60% rename from x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/calculate_auto.js rename to x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/calculate_auto.ts index bd4d6e51ccc0d..720a924dddcb5 100644 --- a/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/calculate_auto.js +++ b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/calculate_auto.ts @@ -5,10 +5,12 @@ * 2.0. */ -import moment from 'moment'; +import moment, { Duration } from 'moment'; const d = moment.duration; -const roundingRules = [ +type RoundingRule = [Duration, Duration]; + +const roundingRules: RoundingRule[] = [ [d(500, 'ms'), d(100, 'ms')], [d(5, 'second'), d(1, 'second')], [d(7.5, 'second'), d(5, 'second')], @@ -24,19 +26,21 @@ const roundingRules = [ [d(1, 'week'), d(1, 'd')], [d(3, 'week'), d(1, 'week')], [d(1, 'year'), d(1, 'month')], - [Infinity, d(1, 'year')], + [d(Infinity, 'year'), d(1, 'year')], ]; -const revRoundingRules = roundingRules.slice(0).reverse(); +const revRoundingRules = [...roundingRules].reverse(); + +type CheckFunction = (bound: Duration, interval: Duration, target: number) => Duration | null; -function find(rules, check, last) { - function pick(buckets, duration) { - const target = duration / buckets; - let lastResp = null; +function find(rules: RoundingRule[], check: CheckFunction, last?: boolean) { + function pick(buckets: number, duration: Duration): Duration | null { + const target = duration.asMilliseconds() / buckets; + let lastResp: Duration | null = null; for (let i = 0; i < rules.length; i++) { - const rule = rules[i]; - const resp = check(rule[0], rule[1], target); + const [bound, interval] = rules[i]; + const resp = check(bound, interval, target); if (resp == null) { if (!last) continue; @@ -53,9 +57,9 @@ function find(rules, check, last) { return moment.duration(ms, 'ms'); } - return (buckets, duration) => { + return (buckets: number, duration: Duration): Duration | undefined => { const interval = pick(buckets, duration); - if (interval) return moment.duration(interval._data); + if (interval) return moment.duration(interval); }; } @@ -63,16 +67,19 @@ export const calculateAuto = { near: find( revRoundingRules, function near(bound, interval, target) { - if (bound > target) return interval; + if (bound.asMilliseconds() > target) return interval; + return null; }, true ), lessThan: find(revRoundingRules, function lessThan(_bound, interval, target) { - if (interval < target) return interval; + if (interval.asMilliseconds() < target) return interval; + return null; }), atLeast: find(revRoundingRules, function atLeast(_bound, interval, target) { - if (interval <= target) return interval; + if (interval.asMilliseconds() <= target) return interval; + return null; }), }; diff --git a/x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/get_bucket_size.test.ts b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/get_bucket_size.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/apm/common/utils/get_bucket_size/get_bucket_size.test.ts rename to x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/get_bucket_size.test.ts diff --git a/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/index.ts b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/index.ts new file mode 100644 index 0000000000000..a2946137cf911 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_bucket_size/index.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment'; +import { calculateAuto } from './calculate_auto'; + +export function getBucketSize({ + start, + end, + numBuckets = 50, + minBucketSize, +}: { + start: number; + end: number; + numBuckets?: number; + minBucketSize?: number; +}) { + const duration = moment.duration(end - start, 'ms'); + const bucketSize = Math.max( + calculateAuto.near(numBuckets, duration)?.asSeconds() ?? 0, + minBucketSize || 1 + ); + + return { bucketSize, intervalString: `${bucketSize}s` }; +} diff --git a/x-pack/plugins/observability_solution/apm/common/utils/get_preferred_bucket_size_and_data_source.test.ts b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_preferred_bucket_size_and_data_source.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/apm/common/utils/get_preferred_bucket_size_and_data_source.test.ts rename to x-pack/plugins/observability_solution/apm_data_access/common/utils/get_preferred_bucket_size_and_data_source.test.ts diff --git a/x-pack/plugins/observability_solution/apm/common/utils/get_preferred_bucket_size_and_data_source.ts b/x-pack/plugins/observability_solution/apm_data_access/common/utils/get_preferred_bucket_size_and_data_source.ts similarity index 100% rename from x-pack/plugins/observability_solution/apm/common/utils/get_preferred_bucket_size_and_data_source.ts rename to x-pack/plugins/observability_solution/apm_data_access/common/utils/get_preferred_bucket_size_and_data_source.ts diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/helpers.ts b/x-pack/plugins/observability_solution/apm_data_access/server/helpers.ts new file mode 100644 index 0000000000000..0b27317463a83 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/helpers.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export { + getDocumentTypeFilterForServiceDestinationStatistics, + getBackwardCompatibleDocumentTypeFilter, + callAsyncWithDebug, + cancelEsRequestOnAbort, + getDebugBody, + getDebugTitle, +} from './lib/helpers'; diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/index.ts b/x-pack/plugins/observability_solution/apm_data_access/server/index.ts index f322ff2eb910d..643db1cdde32a 100644 --- a/x-pack/plugins/observability_solution/apm_data_access/server/index.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/index.ts @@ -82,4 +82,10 @@ export async function plugin(initializerContext: PluginInitializerContext) { return new ApmDataAccessPlugin(initializerContext); } -export type { ApmDataAccessPluginSetup, ApmDataAccessPluginStart } from './types'; +export type { + ApmDataAccessPluginSetup, + ApmDataAccessPluginStart, + ApmDataAccessClient, +} from './types'; + +export { APMEventClient } from './lib/helpers'; diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/call_async_with_debug.ts similarity index 93% rename from x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts rename to x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/call_async_with_debug.ts index f1899b8f4c2db..e3ebb34146324 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/call_async_with_debug.ts @@ -12,7 +12,7 @@ import { KibanaRequest } from '@kbn/core/server'; import { RequestStatus } from '@kbn/inspector-plugin/common'; import { WrappedElasticsearchClientError } from '@kbn/observability-plugin/server'; import { getInspectResponse } from '@kbn/observability-shared-plugin/common'; -import { inspectableEsQueriesMap } from '../../../routes/apm_routes/register_apm_server_routes'; +import { InspectResponse } from '@kbn/observability-plugin/typings/common'; function formatObj(obj: Record) { return JSON.stringify(obj, null, 2); @@ -26,6 +26,7 @@ export async function callAsyncWithDebug({ requestParams, operationName, isCalledWithInternalUser, + inspectableEsQueriesMap = new WeakMap(), }: { cb: () => Promise; getDebugMessage: () => { body: string; title: string }; @@ -34,6 +35,7 @@ export async function callAsyncWithDebug({ requestParams: Record; operationName: string; isCalledWithInternalUser: boolean; // only allow inspection of queries that were retrieved with credentials of the end user + inspectableEsQueriesMap?: WeakMap; }): Promise { if (!debug) { return cb(); diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts similarity index 100% rename from x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts rename to x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.test.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.test.ts similarity index 94% rename from x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.test.ts rename to x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.test.ts index 253a0993d1a8c..9f9f6e01d2af6 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.test.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.test.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { APMIndices } from '../../../..'; import { APMEventESSearchRequest } from '.'; -import type { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { getRequestBase } from './get_request_base'; describe('getRequestBase', () => { diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.ts similarity index 92% rename from x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.ts rename to x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.ts index 8a305c9601de5..c1e7998a586c3 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/get_request_base.ts @@ -6,12 +6,12 @@ */ import type { ESFilter } from '@kbn/es-types'; -import type { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { uniq } from 'lodash'; -import { ApmDataSource } from '../../../../../common/data_source'; -import { PROCESSOR_EVENT } from '../../../../../common/es_fields/apm'; +import { PROCESSOR_EVENT } from '@kbn/apm-utils/src/es_fields/apm'; +import type { APMIndices } from '../../../..'; import { getConfigForDocumentType, getProcessorEventForDocumentType } from '../document_type'; +import { ApmDataSource } from '../../../../../common/data_source'; const processorEventIndexMap = { [ProcessorEvent.transaction]: 'transaction', diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts rename to x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.ts new file mode 100644 index 0000000000000..a2120fc760a30 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -0,0 +1,333 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + EqlSearchRequest, + FieldCapsRequest, + FieldCapsResponse, + MsearchMultisearchBody, + MsearchMultisearchHeader, + TermsEnumRequest, + TermsEnumResponse, +} from '@elastic/elasticsearch/lib/api/types'; +import { ElasticsearchClient, KibanaRequest } from '@kbn/core/server'; +import type { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types'; +import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { unwrapEsResponse } from '@kbn/observability-plugin/server'; +import { compact, omit } from 'lodash'; +import { ValuesType } from 'utility-types'; +import { APMError, Metric, Span, Transaction, Event } from '@kbn/apm-utils/es_schemas_ui'; +import { withApmSpan } from '@kbn/apm-plugin/server/utils/with_apm_span'; +import { InspectResponse } from '@kbn/observability-plugin/typings/common'; +import { ApmDataSource } from '../../../../../common/data_source'; +import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort'; +import { callAsyncWithDebug, getDebugBody, getDebugTitle } from '../call_async_with_debug'; +import { ProcessorEventOfDocumentType } from '../document_type'; +import type { APMIndices } from '../../../..'; +import { getRequestBase, processorEventsToIndex } from './get_request_base'; + +export type APMEventESSearchRequest = Omit & { + apm: { + includeLegacyData?: boolean; + } & ({ events: ProcessorEvent[] } | { sources: ApmDataSource[] }); + body: { + size: number; + track_total_hits: boolean | number; + }; +}; + +export type APMLogEventESSearchRequest = Omit & { + body: { + size: number; + track_total_hits: boolean | number; + }; +}; + +type APMEventWrapper = Omit & { + apm: { events: ProcessorEvent[] }; +}; + +type APMEventTermsEnumRequest = APMEventWrapper; +type APMEventEqlSearchRequest = APMEventWrapper; +type APMEventFieldCapsRequest = APMEventWrapper; + +type TypeOfProcessorEvent = { + [ProcessorEvent.error]: APMError; + [ProcessorEvent.transaction]: Transaction; + [ProcessorEvent.span]: Span; + [ProcessorEvent.metric]: Metric; +}[T]; + +type TypedLogEventSearchResponse = + InferSearchResponseOf; + +type TypedSearchResponse = InferSearchResponseOf< + TypeOfProcessorEvent< + TParams['apm'] extends { events: ProcessorEvent[] } + ? ValuesType + : TParams['apm'] extends { sources: ApmDataSource[] } + ? ProcessorEventOfDocumentType['documentType']> + : never + >, + TParams +>; + +interface TypedMSearchResponse { + responses: Array>; +} + +export interface APMEventClientConfig { + esClient: ElasticsearchClient; + debug: boolean; + request: KibanaRequest; + indices: APMIndices; + options: { + includeFrozen: boolean; + inspectableEsQueriesMap?: WeakMap; + }; +} + +export class APMEventClient { + private readonly esClient: ElasticsearchClient; + private readonly debug: boolean; + private readonly request: KibanaRequest; + public readonly indices: APMIndices; + private readonly includeFrozen: boolean; + private readonly inspectableEsQueriesMap?: WeakMap; + + constructor(config: APMEventClientConfig) { + this.esClient = config.esClient; + this.debug = config.debug; + this.request = config.request; + this.indices = config.indices; + this.includeFrozen = config.options.includeFrozen; + this.inspectableEsQueriesMap = config.options.inspectableEsQueriesMap; + } + + private callAsyncWithDebug({ + requestType, + params, + cb, + operationName, + }: { + requestType: string; + params: Record; + cb: (requestOpts: { signal: AbortSignal; meta: true }) => Promise; + operationName: string; + }): Promise { + return callAsyncWithDebug({ + getDebugMessage: () => ({ + body: getDebugBody({ + params, + requestType, + operationName, + }), + title: getDebugTitle(this.request), + }), + isCalledWithInternalUser: false, + debug: this.debug, + request: this.request, + operationName, + requestParams: params, + inspectableEsQueriesMap: this.inspectableEsQueriesMap, + cb: () => { + const controller = new AbortController(); + + const promise = withApmSpan(operationName, () => { + return cancelEsRequestOnAbort( + cb({ signal: controller.signal, meta: true }), + this.request, + controller + ); + }); + + return unwrapEsResponse(promise); + }, + }); + } + + async search( + operationName: string, + params: TParams + ): Promise> { + const { index, filters } = getRequestBase({ + apm: params.apm, + indices: this.indices, + }); + + const searchParams = { + ...omit(params, 'apm', 'body'), + index, + body: { + ...params.body, + query: { + bool: { + filter: filters, + must: compact([params.body.query]), + }, + }, + }, + ...(this.includeFrozen ? { ignore_throttled: false } : {}), + ignore_unavailable: true, + preference: 'any', + expand_wildcards: ['open' as const, 'hidden' as const], + }; + + return this.callAsyncWithDebug({ + cb: (opts) => + this.esClient.search(searchParams, opts) as unknown as Promise<{ + body: TypedSearchResponse; + }>, + operationName, + params: searchParams, + requestType: 'search', + }); + } + + async logEventSearch( + operationName: string, + params: TParams + ): Promise> { + // Reusing indices configured for errors since both events and errors are stored as logs. + const index = processorEventsToIndex([ProcessorEvent.error], this.indices); + + const searchParams = { + ...omit(params, 'body'), + index, + body: { + ...params.body, + query: { + bool: { + must: compact([params.body.query]), + }, + }, + }, + ...(this.includeFrozen ? { ignore_throttled: false } : {}), + ignore_unavailable: true, + preference: 'any', + expand_wildcards: ['open' as const, 'hidden' as const], + }; + + return this.callAsyncWithDebug({ + cb: (opts) => + this.esClient.search(searchParams, opts) as unknown as Promise<{ + body: TypedLogEventSearchResponse; + }>, + operationName, + params: searchParams, + requestType: 'search', + }); + } + + async msearch( + operationName: string, + ...allParams: TParams[] + ): Promise> { + const searches = allParams + .map((params) => { + const { index, filters } = getRequestBase({ + apm: params.apm, + indices: this.indices, + }); + + const searchParams: [MsearchMultisearchHeader, MsearchMultisearchBody] = [ + { + index, + preference: 'any', + ...(this.includeFrozen ? { ignore_throttled: false } : {}), + ignore_unavailable: true, + expand_wildcards: ['open' as const, 'hidden' as const], + }, + { + ...omit(params, 'apm', 'body'), + ...params.body, + query: { + bool: { + filter: compact([params.body.query, ...filters]), + }, + }, + }, + ]; + + return searchParams; + }) + .flat(); + + return this.callAsyncWithDebug({ + cb: (opts) => + this.esClient.msearch( + { + searches, + }, + opts + ) as unknown as Promise<{ + body: TypedMSearchResponse; + }>, + operationName, + params: searches, + requestType: 'msearch', + }); + } + + async eqlSearch(operationName: string, params: APMEventEqlSearchRequest) { + const index = processorEventsToIndex(params.apm.events, this.indices); + + const requestParams = { + ...omit(params, 'apm'), + index, + }; + + return this.callAsyncWithDebug({ + operationName, + requestType: 'eql_search', + params: requestParams, + cb: (opts) => this.esClient.eql.search(requestParams, opts), + }); + } + + async fieldCaps( + operationName: string, + params: APMEventFieldCapsRequest + ): Promise { + const index = processorEventsToIndex(params.apm.events, this.indices); + + const requestParams = { + ...omit(params, 'apm'), + index, + }; + + return this.callAsyncWithDebug({ + operationName, + requestType: '_field_caps', + params: requestParams, + cb: (opts) => this.esClient.fieldCaps(requestParams, opts), + }); + } + + async termsEnum( + operationName: string, + params: APMEventTermsEnumRequest + ): Promise { + const index = processorEventsToIndex(params.apm.events, this.indices); + + const requestParams = { + ...omit(params, 'apm'), + index: index.join(','), + }; + + return this.callAsyncWithDebug({ + operationName, + requestType: '_terms_enum', + params: requestParams, + cb: (opts) => this.esClient.termsEnum(requestParams, opts), + }); + } + + getIndicesFromProcessorEvent(processorEvent: ProcessorEvent) { + return processorEventsToIndex([processorEvent], this.indices); + } +} diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/document_type.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/document_type.ts similarity index 95% rename from x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/document_type.ts rename to x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/document_type.ts index 8165c7329b6b1..bb81f0a9e8950 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/document_type.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/create_es_client/document_type.ts @@ -6,10 +6,10 @@ */ import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { termQuery } from '@kbn/observability-plugin/server'; +import { METRICSET_INTERVAL, METRICSET_NAME } from '@kbn/apm-utils/src/es_fields/apm'; import { ApmDocumentType } from '../../../../common/document_type'; -import { METRICSET_INTERVAL, METRICSET_NAME } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; -import { termQuery } from '../../../../common/utils/term_query'; import { getDocumentTypeFilterForServiceDestinationStatistics } from '../spans/get_is_using_service_destination_metrics'; import { getBackwardCompatibleDocumentTypeFilter } from '../transactions'; diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/index.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/index.ts new file mode 100644 index 0000000000000..764661a8e5f7e --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { getDocumentTypeFilterForServiceDestinationStatistics } from './spans/get_is_using_service_destination_metrics'; +export { getBackwardCompatibleDocumentTypeFilter } from './transactions'; +export { APMEventClient } from './create_es_client/create_apm_event_client'; + +export { + callAsyncWithDebug, + getDebugBody, + getDebugTitle, +} from './create_es_client/call_async_with_debug'; + +export { cancelEsRequestOnAbort } from './create_es_client/cancel_es_request_on_abort'; diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/spans/get_is_using_service_destination_metrics.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/spans/get_is_using_service_destination_metrics.ts new file mode 100644 index 0000000000000..de013844a7a6d --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/spans/get_is_using_service_destination_metrics.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { termQuery } from '@kbn/observability-plugin/server'; +import { METRICSET_NAME, METRICSET_INTERVAL } from '@kbn/apm-utils/src/es_fields/apm'; + +export function getDocumentTypeFilterForServiceDestinationStatistics( + searchServiceDestinationMetrics: boolean +) { + return searchServiceDestinationMetrics + ? [ + { + bool: { + filter: termQuery(METRICSET_NAME, 'service_destination'), + must_not: { + terms: { + [METRICSET_INTERVAL]: ['10m', '60m'], + }, + }, + }, + }, + ] + : []; +} diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/transactions/index.ts b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/transactions/index.ts new file mode 100644 index 0000000000000..ec5fe75e9dcb5 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/lib/helpers/transactions/index.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { + TRANSACTION_DURATION_HISTOGRAM, + METRICSET_INTERVAL, + METRICSET_NAME, + TRANSACTION_DURATION_SUMMARY, +} from '@kbn/apm-utils/src/es_fields/apm'; + +// The function returns Document type filter for 1m Transaction Metrics +export function getBackwardCompatibleDocumentTypeFilter(searchAggregatedTransactions: boolean) { + return searchAggregatedTransactions + ? [ + { + bool: { + filter: [{ exists: { field: TRANSACTION_DURATION_HISTOGRAM } }], + must_not: [ + { terms: { [METRICSET_INTERVAL]: ['10m', '60m'] } }, + { term: { [METRICSET_NAME]: 'service_transaction' } }, + ], + }, + }, + ] + : []; +} + +export function isDurationSummaryNotSupportedFilter(): QueryDslQueryContainer { + return { + bool: { + must_not: [{ exists: { field: TRANSACTION_DURATION_SUMMARY } }], + }, + }; +} diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/plugin.ts b/x-pack/plugins/observability_solution/apm_data_access/server/plugin.ts index a1ebce9d6eed0..df4b8068fc692 100644 --- a/x-pack/plugins/observability_solution/apm_data_access/server/plugin.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/plugin.ts @@ -19,8 +19,7 @@ import { apmIndicesSavedObjectDefinition, getApmIndicesSavedObject, } from './saved_objects/apm_indices'; -import { registerServices } from './services/register_services'; -import { getTypedSearch } from '../utils/create_typed_es_client'; +import { getClient } from './services/get_client'; export class ApmDataAccessPlugin implements Plugin @@ -43,23 +42,11 @@ export class ApmDataAccessPlugin core.savedObjects.registerType(apmIndicesSavedObjectDefinition); // expose - const getCoreStart = () => core.getStartServices().then(([coreStart]) => coreStart); - const getResourcesForServices = async () => { - const coreStart = await getCoreStart(); - const soClient = coreStart.savedObjects.createInternalRepository(); - const apmIndices = await getApmIndices(soClient); - return { - apmIndices, - esClient: getTypedSearch(coreStart.elasticsearch.client.asInternalUser), - }; - }; - - const services = registerServices({ getResourcesForServices }); return { apmIndicesFromConfigFile, getApmIndices, - services, + getClient, }; } diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/services/get_client.ts b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_client.ts new file mode 100644 index 0000000000000..d16d048003038 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_client.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IUiSettingsClient } from '@kbn/core-ui-settings-server'; +import { APMEventClient } from '../lib/helpers/create_es_client/create_apm_event_client'; +import { createGetDocumentSources } from './get_document_sources'; +import { createGetHostNames } from './get_host_names'; + +export interface ApmDataAccessClientParams { + apmEventClient: APMEventClient; + deps: { + uiSettings: IUiSettingsClient; + }; +} + +export function getClient(params: ApmDataAccessClientParams) { + return { + getHostNames: createGetHostNames(params), + getDocumentSources: createGetDocumentSources(params), + }; +} diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_document_sources.ts b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_document_sources/get_document_sources.ts similarity index 92% rename from x-pack/plugins/observability_solution/apm/server/lib/helpers/get_document_sources.ts rename to x-pack/plugins/observability_solution/apm_data_access/server/services/get_document_sources/get_document_sources.ts index ca049603b5c52..3d5c7c7c90b0b 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/get_document_sources.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_document_sources/get_document_sources.ts @@ -6,18 +6,27 @@ */ import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { ApmDocumentType } from '../../../common/document_type'; import { RollupInterval } from '../../../common/rollup'; -import { APMEventClient } from './create_es_client/create_apm_event_client'; -import { getConfigForDocumentType } from './create_es_client/document_type'; import { TimeRangeMetadata } from '../../../common/time_range_metadata'; -import { isDurationSummaryNotSupportedFilter } from './transactions'; +import { isDurationSummaryNotSupportedFilter } from '../../lib/helpers/transactions'; +import { ApmDocumentType } from '../../../common/document_type'; +import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client'; +import { getConfigForDocumentType } from '../../lib/helpers/create_es_client/document_type'; const QUERY_INDEX = { DOCUMENT_TYPE: 0, DURATION_SUMMARY_NOT_SUPPORTED: 1, } as const; +export interface DocumentSorcesRequest { + apmEventClient: APMEventClient; + start: number; + end: number; + kuery: string; + enableServiceTransactionMetrics: boolean; + enableContinuousRollups: boolean; +} + const getRequest = ({ documentType, rollupInterval, diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/services/get_document_sources/index.ts b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_document_sources/index.ts new file mode 100644 index 0000000000000..279431ed3b1f3 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_document_sources/index.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ApmDataAccessClientParams } from '../get_client'; +import { getDocumentSources, type DocumentSorcesRequest } from './get_document_sources'; + +export function createGetDocumentSources({ apmEventClient }: ApmDataAccessClientParams) { + return async ({ + enableContinuousRollups, + enableServiceTransactionMetrics, + end, + kuery, + start, + }: Omit) => { + return getDocumentSources({ + apmEventClient, + enableContinuousRollups, + enableServiceTransactionMetrics, + end, + kuery, + start, + }); + }; +} + +export { getDocumentSources }; diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/services/get_host_names/index.ts b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_host_names/index.ts index f33e2bbc46d54..c53e39beca7cc 100644 --- a/x-pack/plugins/observability_solution/apm_data_access/server/services/get_host_names/index.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/services/get_host_names/index.ts @@ -7,34 +7,78 @@ import { estypes } from '@elastic/elasticsearch'; import { rangeQuery } from '@kbn/observability-plugin/server'; -import { RegisterParams } from '../register_services'; +import { HOST_NAME } from '@kbn/apm-utils/es_fields'; +import { + apmEnableContinuousRollups, + apmEnableServiceMetrics, +} from '@kbn/observability-plugin/common'; +import { getBucketSize } from '../../../common/utils/get_bucket_size'; +import { getPreferredBucketSizeAndDataSource } from '../../../common/utils/get_preferred_bucket_size_and_data_source'; +import { ApmDocumentType } from '../../../common/document_type'; +import { getDocumentSources } from '../get_document_sources'; +import { ApmDataAccessClientParams } from '../get_client'; +const MAX_LIMIT = 1000; export interface ServicesHostNamesParams { query: estypes.QueryDslQueryContainer; + kuery?: string; from: number; to: number; - limit: number; + limit?: number; } -export function createGetHostNames(params: RegisterParams) { - return async ({ from: timeFrom, to: timeTo, query, limit }: ServicesHostNamesParams) => { - const { apmIndices, esClient } = await params.getResourcesForServices(); - - const esResponse = await esClient.search({ - index: [apmIndices.metric, apmIndices.transaction, apmIndices.span, apmIndices.error], - track_total_hits: false, - ignore_unavailable: true, - size: 0, - query: { - bool: { - filter: [query, ...rangeQuery(timeFrom, timeTo)], - }, +const suitableTypes = [ApmDocumentType.TransactionMetric]; + +export function createGetHostNames({ apmEventClient, deps }: ApmDataAccessClientParams) { + return async ({ + from: start, + to: end, + limit = MAX_LIMIT, + query, + kuery = '', + }: ServicesHostNamesParams) => { + const [enableContinuousRollups, enableServiceTransactionMetrics] = await Promise.all([ + deps.uiSettings.get(apmEnableContinuousRollups), + deps.uiSettings.get(apmEnableServiceMetrics), + ]); + + const documentSources = await getDocumentSources({ + apmEventClient, + start, + end, + kuery, + enableContinuousRollups, + enableServiceTransactionMetrics, + }); + + const sourcesToUse = getPreferredBucketSizeAndDataSource({ + sources: documentSources.filter((s) => suitableTypes.includes(s.documentType)), + bucketSizeInSeconds: getBucketSize({ start, end, numBuckets: 100 }).bucketSize, + }); + + const esResponse = await apmEventClient.search('get_apm_host_names', { + apm: { + sources: [ + { + documentType: sourcesToUse.source.documentType, + rollupInterval: sourcesToUse.source.rollupInterval, + }, + ], }, - aggs: { - hostNames: { - terms: { - field: 'host.name', - size: limit, + body: { + track_total_hits: false, + size: 0, + query: { + bool: { + filter: [query, ...rangeQuery(start, end)], + }, + }, + aggs: { + hostNames: { + terms: { + field: HOST_NAME, + size: limit, + }, }, }, }, diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/services/register_services.ts b/x-pack/plugins/observability_solution/apm_data_access/server/services/register_services.ts deleted file mode 100644 index 10b0d501acc5f..0000000000000 --- a/x-pack/plugins/observability_solution/apm_data_access/server/services/register_services.ts +++ /dev/null @@ -1,24 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { APMIndices } from '..'; -import { getTypedSearch } from '../../utils/create_typed_es_client'; -import { createGetHostNames } from './get_host_names'; - -interface Resources { - apmIndices: APMIndices; - esClient: ReturnType; -} -export interface RegisterParams { - getResourcesForServices: () => Promise; -} - -export function registerServices(params: RegisterParams) { - return { - getHostNames: createGetHostNames(params), - }; -} diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/types.ts b/x-pack/plugins/observability_solution/apm_data_access/server/types.ts index ef8ff58a49d80..b22ff8d54455e 100644 --- a/x-pack/plugins/observability_solution/apm_data_access/server/types.ts +++ b/x-pack/plugins/observability_solution/apm_data_access/server/types.ts @@ -7,12 +7,14 @@ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { APMIndices } from '.'; -import { registerServices } from './services/register_services'; +import { getClient } from './services/get_client'; export interface ApmDataAccessPluginSetup { apmIndicesFromConfigFile: APMIndices; getApmIndices: (soClient: SavedObjectsClientContract) => Promise; - services: ReturnType; + getClient: typeof getClient; } // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ApmDataAccessPluginStart {} + +export type ApmDataAccessClient = ReturnType; diff --git a/x-pack/plugins/observability_solution/apm_data_access/server/utils/with_apm_span.ts b/x-pack/plugins/observability_solution/apm_data_access/server/utils/with_apm_span.ts new file mode 100644 index 0000000000000..1343970f04a3f --- /dev/null +++ b/x-pack/plugins/observability_solution/apm_data_access/server/utils/with_apm_span.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { withSpan, SpanOptions, parseSpanOptions } from '@kbn/apm-utils'; + +export function withApmSpan( + optionsOrName: SpanOptions | string, + cb: () => Promise +): Promise { + const options = parseSpanOptions(optionsOrName); + + const optionsWithDefaults = { + ...(options.intercept ? {} : { type: 'plugin:apm' }), + ...options, + labels: { + plugin: 'apm', + ...options.labels, + }, + }; + + return withSpan(optionsWithDefaults, cb); +} diff --git a/x-pack/plugins/observability_solution/apm_data_access/utils/create_typed_es_client.ts b/x-pack/plugins/observability_solution/apm_data_access/utils/create_typed_es_client.ts deleted file mode 100644 index 0e92f9532f2c6..0000000000000 --- a/x-pack/plugins/observability_solution/apm_data_access/utils/create_typed_es_client.ts +++ /dev/null @@ -1,25 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types'; - -type RequiredParams = ESSearchRequest & { - size: number; - track_total_hits: boolean | number; -}; - -export type TypedSearch = ReturnType; -export function getTypedSearch(esClient: ElasticsearchClient) { - async function search( - opts: TParams - ): Promise> { - return esClient.search(opts) as Promise; - } - - return { search }; -} diff --git a/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_apm_client.ts b/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_apm_client.ts new file mode 100644 index 0000000000000..c4adef4d1198a --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_apm_client.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ApmDataAccessPluginSetup, APMEventClient } from '@kbn/apm-data-access-plugin/server'; +import { KibanaRequest } from '@kbn/core/server'; +import { InfraPluginRequestHandlerContext } from '../../types'; + +export const getApmDataAccessClient = async ({ + apmDataAccess, + requestContext, + request, +}: { + apmDataAccess: ApmDataAccessPluginSetup; + requestContext: InfraPluginRequestHandlerContext; + request: KibanaRequest; +}) => { + const coreContext = await requestContext.core; + const savedObjectsClient = coreContext.savedObjects.client; + const apmIndices = await apmDataAccess.getApmIndices(savedObjectsClient); + const esClient = coreContext.elasticsearch.client.asCurrentUser; + + return apmDataAccess.getClient({ + apmEventClient: new APMEventClient({ + indices: apmIndices, + options: { + includeFrozen: false, + }, + debug: false, + esClient, + request, + }), + deps: { + uiSettings: coreContext.uiSettings.client, + }, + }); +}; diff --git a/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_metrics_client.ts b/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_metrics_client.ts index 8e8934fb7b3f0..591decb2f0b45 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_metrics_client.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/helpers/get_infra_metrics_client.ts @@ -32,7 +32,7 @@ export async function getInfraMetricsClient({ requestContext: InfraPluginRequestHandlerContext; request?: KibanaRequest; }) { - const soClient = (await requestContext.core).savedObjects.getClient(); + const soClient = (await requestContext.core).savedObjects.client; const source = await infraSources.getSourceConfiguration(soClient, sourceId); return { diff --git a/x-pack/plugins/observability_solution/infra/server/routes/infra/index.ts b/x-pack/plugins/observability_solution/infra/server/routes/infra/index.ts index 6075f0da1360c..50104ef039fd8 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/infra/index.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/infra/index.ts @@ -17,6 +17,7 @@ import { InfraBackendLibs } from '../../lib/infra_types'; import { getInfraAlertsClient } from '../../lib/helpers/get_infra_alerts_client'; import { getHosts } from './lib/host/get_hosts'; import { getInfraMetricsClient } from '../../lib/helpers/get_infra_metrics_client'; +import { getApmDataAccessClient } from '../../lib/helpers/get_apm_client'; export const initInfraMetricsRoute = (libs: InfraBackendLibs) => { const validateBody = createRouteValidationFunction(GetInfraMetricsRequestBodyPayloadRT); @@ -48,10 +49,16 @@ export const initInfraMetricsRoute = (libs: InfraBackendLibs) => { request, }); + const apmDataAccessClient = await getApmDataAccessClient({ + apmDataAccess: libs.apmDataAccess, + requestContext, + request, + }); + const hosts = await getHosts({ infraMetricsClient, alertsClient, - apmDataAccess: libs.apmDataAccess, + apmDataAccessClient, ...params, }); diff --git a/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/host/get_hosts.ts b/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/host/get_hosts.ts index 3894c91789e68..0816090952012 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/host/get_hosts.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/host/get_hosts.ts @@ -20,7 +20,7 @@ export const getHosts = async ({ type, query, alertsClient, - apmDataAccess, + apmDataAccessClient, infraMetricsClient, }: Omit): Promise => { const runFilterQuery = hasFilters(query); @@ -28,7 +28,7 @@ export const getHosts = async ({ const hostNamesShortList = runFilterQuery ? await getFilteredHostNames({ infraMetricsClient, - apmDataAccess, + apmDataAccessClient, from, to, limit, @@ -80,14 +80,14 @@ export const getHosts = async ({ const getFilteredHostNames = async ({ infraMetricsClient, - apmDataAccess, + apmDataAccessClient, from, to, limit, query, }: Pick< GetHostParameters, - 'apmDataAccess' | 'infraMetricsClient' | 'from' | 'to' | 'limit' | 'query' + 'apmDataAccessClient' | 'infraMetricsClient' | 'from' | 'to' | 'limit' | 'query' >) => { assertQueryStructure(query); @@ -99,7 +99,7 @@ const getFilteredHostNames = async ({ to, limit, }), - apmDataAccess.services.getHostNames({ + apmDataAccessClient.getHostNames({ query, from: new Date(from).getTime(), to: new Date(to).getTime(), diff --git a/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/types.ts b/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/types.ts index cc0e9e403adae..260819bf8dda4 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/types.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/infra/lib/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ApmDataAccessPluginSetup } from '@kbn/apm-data-access-plugin/server'; +import { ApmDataAccessClient } from '@kbn/apm-data-access-plugin/server'; import { GetInfraMetricsRequestBodyPayload } from '../../../../common/http_api/infra'; import { InfraAlertsClient } from '../../../lib/helpers/get_infra_alerts_client'; import { InfraMetricsClient } from '../../../lib/helpers/get_infra_metrics_client'; @@ -13,5 +13,5 @@ import { InfraMetricsClient } from '../../../lib/helpers/get_infra_metrics_clien export interface GetHostParameters extends GetInfraMetricsRequestBodyPayload { infraMetricsClient: InfraMetricsClient; alertsClient: InfraAlertsClient; - apmDataAccess: ApmDataAccessPluginSetup; + apmDataAccessClient: ApmDataAccessClient; }