From 7f6d0b02fa5148aa11e243edaf765692ff2fc18c Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:14:12 -0500 Subject: [PATCH] [apm] Update APM section information architecture (#4230) (#4353) * move source files * update get started section * update data model section * create collect application data section * create view and analyze data section * create act on data section * update manage storage section * update configure section * create use apm securely section * update advanced setup section * update monitor apm server section * update troubleshooting section * update api section * clean up * update index files * fix apm guide redirects * fix more apm guide redirects * fix more apm guide redirects * adjust some headings * address feedback on data types section * address feedback on collect data section * address feedback on configure section * address feedback on get started section * address feedback on act on data section * fix apm guide redirect * fix diagrams * clean up some to dos * clean up * address feedback from @lahsivjar (cherry picked from commit 265db9a11dd6a151aca9170eb5f17888dd6c5c38) Co-authored-by: Colleen McGinnis --- docs/en/apm-server/redirects.asciidoc | 88 +-- .../{apm-ui => }/apm-alerts.asciidoc | 20 +- .../apm-ui/apm-app-users.asciidoc | 351 ----------- docs/en/observability/apm-ui/index.asciidoc | 76 --- docs/en/observability/apm.asciidoc | 51 +- .../act-on-data}/custom-links.asciidoc | 24 +- .../apm/act-on-data/index.asciidoc | 24 + .../api.asciidoc => apm/api/api-ui.asciidoc} | 154 ++--- .../{ => api/apm-server}/api-config.asciidoc | 14 +- .../{ => api/apm-server}/api-error.asciidoc | 4 +- .../apm-server}/api-event-example.asciidoc | 2 +- .../{ => api/apm-server}/api-events.asciidoc | 24 +- .../{ => api/apm-server}/api-info.asciidoc | 8 +- .../{ => api/apm-server}/api-jaeger.asciidoc | 4 +- .../apm-server}/api-metadata.asciidoc | 6 +- .../apm-server}/api-metricset.asciidoc | 4 +- .../{ => api/apm-server}/api-otlp.asciidoc | 6 +- .../{ => api/apm-server}/api-span.asciidoc | 4 +- .../apm-server}/api-transaction.asciidoc | 4 +- .../apm-server/index.asciidoc} | 6 +- docs/en/observability/apm/api/index.asciidoc | 17 + .../apm/apm-data-security.asciidoc | 596 ------------------ .../agents}/agent-configuration.asciidoc | 10 +- .../agents/index.asciidoc | 41 ++ .../agents/rum.asciidoc} | 2 +- .../agents}/source-map-how-to.asciidoc | 14 +- .../aws-lambda-extension.asciidoc | 4 + .../collect-application-data/index.asciidoc | 86 +++ .../jaeger-integration.asciidoc | 20 +- .../k8s-attacher.asciidoc} | 6 +- .../open-telemetry/index.asciidoc} | 20 +- .../open-telemetry}/otel-attrs.asciidoc | 2 +- .../open-telemetry}/otel-direct.asciidoc | 10 +- .../open-telemetry}/otel-limitations.asciidoc | 12 +- .../open-telemetry}/otel-metrics.asciidoc | 6 +- .../apm/common-problems.asciidoc | 200 ------ .../command-reference.asciidoc | 18 +- .../advanced-setup}/data-ingestion.asciidoc | 12 +- .../high-availability.asciidoc | 2 +- .../configure/advanced-setup/index.asciidoc | 30 + .../advanced-setup}/keystore.asciidoc | 10 +- .../shared-directory-layout.asciidoc | 6 +- .../advanced-setup}/shared-systemd.asciidoc | 8 +- .../apm/configure/agent-config.asciidoc | 8 +- .../apm/configure/anonymous-auth.asciidoc | 18 +- .../observability/apm/configure/auth.asciidoc | 42 +- .../apm/configure/general.asciidoc | 32 +- .../apm/configure/index.asciidoc | 6 +- .../observability/apm/configure/rum.asciidoc | 34 +- .../apm/configure/sampling.asciidoc | 32 +- .../apm/data-model/data-model-errors.asciidoc | 52 ++ .../data-model/data-model-metadata.asciidoc | 99 +++ .../data-model-metrics.asciidoc} | 358 +---------- .../data-model-spans.asciidoc} | 84 ++- .../distributed-tracing.asciidoc} | 23 +- .../apm/data-model/index.asciidoc | 52 ++ .../data-model/transactions/index.asciidoc | 76 +++ .../transactions}/sampling.asciidoc | 50 +- docs/en/observability/apm/features.asciidoc | 37 -- ...t-started-with-apm-server-binary.asciidoc} | 267 +------- ...get-started-with-fleet-apm-server.asciidoc | 70 ++ .../apm/getting-started-apm/index.asciidoc | 154 +++++ docs/en/observability/apm/how-to.asciidoc | 47 -- .../images/active-alert-service.png | Bin .../{apm-ui => apm}/images/add-variable.png | Bin .../images/advanced-discover.png | Bin .../{apm-ui => apm}/images/all-instances.png | Bin .../images/apm-agent-configuration.png | Bin .../images/apm-agent-explorer-flyout.png | Bin .../images/apm-agent-explorer.png | Bin .../{apm-ui => apm}/images/apm-alert.png | Bin .../images/apm-anomaly-alert.png | Bin .../apm-distributed-tracing-apm-ui.png} | Bin .../images/apm-error-group.png | Bin .../images/apm-errors-overview.png | Bin .../images/apm-errors-watcher-assistant.png | Bin .../{apm-ui => apm}/images/apm-geo-ui.png | Bin .../images/apm-index-pattern.png | Bin .../images/apm-integration-config.png | Bin .../{apm-ui => apm}/images/apm-logs-tab.png | Bin .../{apm-ui => apm}/images/apm-metrics.png | Bin .../images/apm-ml-integration.png | Bin .../{apm-ui => apm}/images/apm-query-bar.png | Bin .../images/apm-roles-config.png | Bin .../images/apm-service-group.png | Bin .../images/apm-service-map-anomaly.png | Bin .../images/apm-services-overview.png | Bin .../images/apm-services-trace.png | Bin .../{apm-ui => apm}/images/apm-settings.png | Bin .../{apm-ui => apm}/images/apm-setup.png | Bin .../images/apm-span-detail.png | Bin .../{apm-ui => apm}/images/apm-traces.png | Bin .../images/apm-transaction-annotation.png | Bin .../images/apm-transaction-duration-dist.png | Bin .../images/apm-transaction-response-dist.png | Bin .../images/apm-transaction-sample.png | Bin .../images/apm-transactions-overview.png | Bin .../images/apm-transactions-table.png | Bin .../correlations-failed-transactions.png | Bin .../images/correlations-hover.png | Bin .../images/create-github-issue.png | Bin .../images/create-jira-issue.png | Bin .../images/dependencies-drilldown.png | Bin .../{apm-ui => apm}/images/dependencies.png | Bin .../apm/images/diagram-of-a-trace.png | Bin 0 -> 80569 bytes .../apm/images/distributed-traces.png | Bin 0 -> 114882 bytes .../{apm-ui => apm}/images/dynamic-config.svg | 0 .../{apm-ui => apm}/images/error-rate.png | Bin .../images/example-metadata.png | Bin .../{apm-ui => apm}/images/global-filters.png | Bin .../{apm-ui => apm}/images/green-service.png | Bin .../{apm-ui => apm}/images/infra.png | Bin .../images/jvm-metrics-overview.png | Bin .../{apm-ui => apm}/images/jvm-metrics.png | Bin .../images/lambda-cold-start-trace.png | Bin .../images/lambda-correlations.png | Bin .../images/lambda-overview.png | Bin .../{apm-ui => apm}/images/latency.png | Bin .../{apm-ui => apm}/images/local-filter.png | Bin .../{apm-ui => apm}/images/logs.png | Bin .../{apm-ui => apm}/images/metadata-icons.png | Bin .../images/mobile-location.png | Bin .../images/mobile-most-used.png | Bin .../images/mobile-session-error-details.png | Bin .../images/mobile-session-explorer-apm.png | Bin .../images/mobile-session-explorer-nav.png | Bin .../images/mobile-session-filter-discover.png | Bin .../{apm-ui => apm}/images/mobile-tp.png | Bin .../images/operations-detail.png | Bin .../{apm-ui => apm}/images/operations.png | Bin .../{apm-ui => apm}/images/red-service.png | Bin .../images/service-maps-java.png | Bin .../{apm-ui => apm}/images/service-maps.png | Bin .../images/service-quick-health.png | Bin .../images/spans-dependencies.png | Bin .../images/spans-transactions-and-traces.png | Bin 0 -> 91061 bytes .../images/specific-transaction-search.png | Bin .../images/specific-transaction.png | Bin .../images/storage-explorer-expanded.png | Bin .../images/storage-explorer-overview.png | Bin ...time-series-expected-bounds-comparison.png | Bin .../{apm-ui => apm}/images/trace-explorer.png | Bin .../images/traffic-transactions.png | Bin .../images/transaction-icon.png | Bin .../{apm-ui => apm}/images/yellow-service.png | Bin .../apm/log-correlation.asciidoc | 11 - .../observability/apm/manage-storage.asciidoc | 216 ------- .../custom-index-template.asciidoc | 10 +- .../data-streams.asciidoc | 10 +- .../exploring-es-data.asciidoc | 0 .../{ => manage-storage}/ilm-how-to.asciidoc | 16 +- .../apm/manage-storage/index.asciidoc | 37 ++ .../ingest-pipelines.asciidoc | 14 +- .../reduce-apm-storage.asciidoc | 125 ++++ .../storage-and-sizing.asciidoc | 62 ++ .../manage-storage}/storage-explorer.asciidoc | 20 +- .../{apm-ui => apm}/mobile-errors.asciidoc | 0 .../index.asciidoc} | 18 +- .../{ => monitor-apm-server}/monitor.asciidoc | 6 +- .../monitoring-beats.asciidoc | 11 +- .../monitoring-internal-collection.asciidoc | 2 +- .../monitoring-local-collection.asciidoc | 1 + .../monitoring-metricbeat.asciidoc | 7 +- .../shared-monitor-config.asciidoc | 0 .../observability/apm/repositories.asciidoc | 7 +- .../observability/apm/secure-comms.asciidoc | 23 - .../apm-agents}/anonymous-auth.asciidoc | 8 +- .../apm-agents}/api-keys.asciidoc | 44 +- .../apm-agents/index.asciidoc} | 13 +- .../apm-agents}/secret-token.asciidoc | 6 +- .../apm-agents}/tls-comms.asciidoc | 12 +- .../data-security}/apm-spaces.asciidoc | 16 +- .../data-security/custom-filter.asciidoc | 300 +++++++++ .../security/data-security/delete.asciidoc | 90 +++ .../security/data-security/filtering.asciidoc | 122 ++++ .../apm/security/data-security/index.asciidoc | 92 +++ .../elastic-stack}/access-api-keys.asciidoc | 12 +- .../elastic-stack/index.asciidoc} | 47 +- .../observability/apm/security/index.asciidoc | 45 ++ .../security/user-access/annotation.asciidoc | 44 ++ .../apm/security/user-access/api-ui.asciidoc | 82 +++ .../user-access/central-config.asciidoc | 67 ++ .../apm/security/user-access/index.asciidoc | 37 ++ .../apm/security/user-access/reader.asciidoc | 77 +++ .../user-access/storage-explorer.asciidoc | 22 + .../apm/setting-up-and-running.asciidoc | 31 - .../observability/apm/shared-docker.asciidoc | 15 +- .../apm-app-reader/content.asciidoc | 0 .../apm-app-reader/widget.asciidoc | 0 .../central-config-users/content.asciidoc | 0 .../central-config-users/widget.asciidoc | 0 .../install-agents-widget.asciidoc | 2 +- .../storage-explorer-user/content.asciidoc | 0 .../storage-explorer-user/widget.asciidoc | 0 .../apm-performance-diagnostic.asciidoc | 6 +- .../apm-response-codes.asciidoc | 12 +- .../apm-server-down.asciidoc | 2 +- .../troubleshooting/common-problems.asciidoc} | 240 ++++++- .../{ => troubleshooting}/debugging.asciidoc | 2 +- .../index.asciidoc} | 30 +- .../processing-performance.asciidoc | 2 +- .../apm/upgrading-to-8.x.asciidoc | 4 +- .../view-and-analyze}/agent-explorer.asciidoc | 2 +- .../drill-down}/errors.asciidoc | 2 +- .../drill-down/index.asciidoc | 26 + .../drill-down}/infrastructure.asciidoc | 2 +- .../drill-down}/logs.asciidoc | 14 +- .../drill-down}/metrics.asciidoc | 2 +- .../drill-down}/spans.asciidoc | 6 +- .../drill-down}/transactions.asciidoc | 14 +- .../advanced-queries.asciidoc | 14 +- .../cross-cluster-search.asciidoc | 8 +- .../filter-and-search}/filters.asciidoc | 8 +- .../filter-and-search/index.asciidoc | 22 + .../apm/view-and-analyze/index.asciidoc | 39 ++ .../interpret}/correlations.asciidoc | 6 +- .../deployment-annotations.asciidoc | 2 +- .../view-and-analyze/interpret/index.asciidoc | 33 + .../interpret}/lambda.asciidoc | 10 +- .../mobile-session-explorer.asciidoc | 4 +- .../machine-learning.asciidoc | 8 +- .../view-and-analyze}/settings.asciidoc | 6 +- .../ui-overview}/dependencies.asciidoc | 4 +- .../ui-overview/index.asciidoc | 31 + .../ui-overview}/mobile-service.asciidoc | 10 +- .../new-experience-services.asciidoc | 0 .../ui-overview}/service-maps.asciidoc | 12 +- .../ui-overview}/service-overview.asciidoc | 18 +- .../ui-overview}/services.asciidoc | 4 +- .../ui-overview}/traces.asciidoc | 4 +- docs/en/observability/create-alerts.asciidoc | 2 + docs/en/observability/images/icons/check.svg | 1 + docs/en/observability/images/icons/cross.svg | 1 + docs/en/observability/redirects.asciidoc | 25 + 234 files changed, 3106 insertions(+), 2859 deletions(-) rename docs/en/observability/{apm-ui => }/apm-alerts.asciidoc (95%) delete mode 100644 docs/en/observability/apm-ui/apm-app-users.asciidoc delete mode 100644 docs/en/observability/apm-ui/index.asciidoc rename docs/en/observability/{apm-ui => apm/act-on-data}/custom-links.asciidoc (97%) create mode 100644 docs/en/observability/apm/act-on-data/index.asciidoc rename docs/en/observability/{apm-ui/api.asciidoc => apm/api/api-ui.asciidoc} (94%) rename docs/en/observability/apm/{ => api/apm-server}/api-config.asciidoc (94%) rename docs/en/observability/apm/{ => api/apm-server}/api-error.asciidoc (93%) rename docs/en/observability/apm/{ => api/apm-server}/api-event-example.asciidoc (89%) rename docs/en/observability/apm/{ => api/apm-server}/api-events.asciidoc (92%) rename docs/en/observability/apm/{ => api/apm-server}/api-info.asciidoc (94%) rename docs/en/observability/apm/{ => api/apm-server}/api-jaeger.asciidoc (92%) rename docs/en/observability/apm/{ => api/apm-server}/api-metadata.asciidoc (97%) rename docs/en/observability/apm/{ => api/apm-server}/api-metricset.asciidoc (92%) rename docs/en/observability/apm/{ => api/apm-server}/api-otlp.asciidoc (93%) rename docs/en/observability/apm/{ => api/apm-server}/api-span.asciidoc (93%) rename docs/en/observability/apm/{ => api/apm-server}/api-transaction.asciidoc (91%) rename docs/en/observability/apm/{api.asciidoc => api/apm-server/index.asciidoc} (86%) create mode 100644 docs/en/observability/apm/api/index.asciidoc delete mode 100644 docs/en/observability/apm/apm-data-security.asciidoc rename docs/en/observability/{apm-ui => apm/collect-application-data/agents}/agent-configuration.asciidoc (93%) create mode 100644 docs/en/observability/apm/collect-application-data/agents/index.asciidoc rename docs/en/observability/apm/{apm-rum.asciidoc => collect-application-data/agents/rum.asciidoc} (96%) rename docs/en/observability/apm/{ => collect-application-data/agents}/source-map-how-to.asciidoc (96%) rename docs/en/observability/apm/{ => collect-application-data}/aws-lambda-extension.asciidoc (93%) create mode 100644 docs/en/observability/apm/collect-application-data/index.asciidoc rename docs/en/observability/apm/{ => collect-application-data}/jaeger-integration.asciidoc (94%) rename docs/en/observability/apm/{apm-k8s-attacher.asciidoc => collect-application-data/k8s-attacher.asciidoc} (63%) rename docs/en/observability/apm/{open-telemetry.asciidoc => collect-application-data/open-telemetry/index.asciidoc} (96%) rename docs/en/observability/apm/{ => collect-application-data/open-telemetry}/otel-attrs.asciidoc (98%) rename docs/en/observability/apm/{ => collect-application-data/open-telemetry}/otel-direct.asciidoc (97%) rename docs/en/observability/apm/{ => collect-application-data/open-telemetry}/otel-limitations.asciidoc (95%) rename docs/en/observability/apm/{ => collect-application-data/open-telemetry}/otel-metrics.asciidoc (96%) delete mode 100644 docs/en/observability/apm/common-problems.asciidoc rename docs/en/observability/apm/{ => configure/advanced-setup}/command-reference.asciidoc (98%) rename docs/en/observability/apm/{ => configure/advanced-setup}/data-ingestion.asciidoc (93%) rename docs/en/observability/apm/{ => configure/advanced-setup}/high-availability.asciidoc (97%) create mode 100644 docs/en/observability/apm/configure/advanced-setup/index.asciidoc rename docs/en/observability/apm/{ => configure/advanced-setup}/keystore.asciidoc (96%) rename docs/en/observability/apm/{ => configure/advanced-setup}/shared-directory-layout.asciidoc (95%) rename docs/en/observability/apm/{ => configure/advanced-setup}/shared-systemd.asciidoc (96%) create mode 100644 docs/en/observability/apm/data-model/data-model-errors.asciidoc create mode 100644 docs/en/observability/apm/data-model/data-model-metadata.asciidoc rename docs/en/observability/apm/{data-model.asciidoc => data-model/data-model-metrics.asciidoc} (54%) rename docs/en/observability/apm/{span-compression.asciidoc => data-model/data-model-spans.asciidoc} (54%) rename docs/en/observability/apm/{apm-distributed-tracing.asciidoc => data-model/distributed-tracing.asciidoc} (84%) create mode 100644 docs/en/observability/apm/data-model/index.asciidoc create mode 100644 docs/en/observability/apm/data-model/transactions/index.asciidoc rename docs/en/observability/apm/{ => data-model/transactions}/sampling.asciidoc (93%) delete mode 100644 docs/en/observability/apm/features.asciidoc rename docs/en/observability/apm/{getting-started-apm-server.asciidoc => getting-started-apm/get-started-with-apm-server-binary.asciidoc} (55%) create mode 100644 docs/en/observability/apm/getting-started-apm/get-started-with-fleet-apm-server.asciidoc create mode 100644 docs/en/observability/apm/getting-started-apm/index.asciidoc delete mode 100644 docs/en/observability/apm/how-to.asciidoc rename docs/en/observability/{apm-ui => apm}/images/active-alert-service.png (100%) rename docs/en/observability/{apm-ui => apm}/images/add-variable.png (100%) rename docs/en/observability/{apm-ui => apm}/images/advanced-discover.png (100%) rename docs/en/observability/{apm-ui => apm}/images/all-instances.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-agent-configuration.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-agent-explorer-flyout.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-agent-explorer.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-alert.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-anomaly-alert.png (100%) rename docs/en/observability/{apm-ui/images/apm-distributed-tracing.png => apm/images/apm-distributed-tracing-apm-ui.png} (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-error-group.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-errors-overview.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-errors-watcher-assistant.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-geo-ui.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-index-pattern.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-integration-config.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-logs-tab.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-metrics.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-ml-integration.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-query-bar.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-roles-config.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-service-group.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-service-map-anomaly.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-services-overview.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-services-trace.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-settings.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-setup.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-span-detail.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-traces.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-transaction-annotation.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-transaction-duration-dist.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-transaction-response-dist.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-transaction-sample.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-transactions-overview.png (100%) rename docs/en/observability/{apm-ui => apm}/images/apm-transactions-table.png (100%) rename docs/en/observability/{apm-ui => apm}/images/correlations-failed-transactions.png (100%) rename docs/en/observability/{apm-ui => apm}/images/correlations-hover.png (100%) rename docs/en/observability/{apm-ui => apm}/images/create-github-issue.png (100%) rename docs/en/observability/{apm-ui => apm}/images/create-jira-issue.png (100%) rename docs/en/observability/{apm-ui => apm}/images/dependencies-drilldown.png (100%) rename docs/en/observability/{apm-ui => apm}/images/dependencies.png (100%) create mode 100644 docs/en/observability/apm/images/diagram-of-a-trace.png create mode 100644 docs/en/observability/apm/images/distributed-traces.png rename docs/en/observability/{apm-ui => apm}/images/dynamic-config.svg (100%) rename docs/en/observability/{apm-ui => apm}/images/error-rate.png (100%) rename docs/en/observability/{apm-ui => apm}/images/example-metadata.png (100%) rename docs/en/observability/{apm-ui => apm}/images/global-filters.png (100%) rename docs/en/observability/{apm-ui => apm}/images/green-service.png (100%) rename docs/en/observability/{apm-ui => apm}/images/infra.png (100%) rename docs/en/observability/{apm-ui => apm}/images/jvm-metrics-overview.png (100%) rename docs/en/observability/{apm-ui => apm}/images/jvm-metrics.png (100%) rename docs/en/observability/{apm-ui => apm}/images/lambda-cold-start-trace.png (100%) rename docs/en/observability/{apm-ui => apm}/images/lambda-correlations.png (100%) rename docs/en/observability/{apm-ui => apm}/images/lambda-overview.png (100%) rename docs/en/observability/{apm-ui => apm}/images/latency.png (100%) rename docs/en/observability/{apm-ui => apm}/images/local-filter.png (100%) rename docs/en/observability/{apm-ui => apm}/images/logs.png (100%) rename docs/en/observability/{apm-ui => apm}/images/metadata-icons.png (100%) rename docs/en/observability/{apm-ui => apm}/images/mobile-location.png (100%) rename docs/en/observability/{apm-ui => apm}/images/mobile-most-used.png (100%) rename docs/en/observability/{apm-ui => apm}/images/mobile-session-error-details.png (100%) rename docs/en/observability/{apm-ui => apm}/images/mobile-session-explorer-apm.png (100%) rename docs/en/observability/{apm-ui => apm}/images/mobile-session-explorer-nav.png (100%) rename docs/en/observability/{apm-ui => apm}/images/mobile-session-filter-discover.png (100%) rename docs/en/observability/{apm-ui => apm}/images/mobile-tp.png (100%) rename docs/en/observability/{apm-ui => apm}/images/operations-detail.png (100%) rename docs/en/observability/{apm-ui => apm}/images/operations.png (100%) rename docs/en/observability/{apm-ui => apm}/images/red-service.png (100%) rename docs/en/observability/{apm-ui => apm}/images/service-maps-java.png (100%) rename docs/en/observability/{apm-ui => apm}/images/service-maps.png (100%) rename docs/en/observability/{apm-ui => apm}/images/service-quick-health.png (100%) rename docs/en/observability/{apm-ui => apm}/images/spans-dependencies.png (100%) create mode 100644 docs/en/observability/apm/images/spans-transactions-and-traces.png rename docs/en/observability/{apm-ui => apm}/images/specific-transaction-search.png (100%) rename docs/en/observability/{apm-ui => apm}/images/specific-transaction.png (100%) rename docs/en/observability/{apm-ui => apm}/images/storage-explorer-expanded.png (100%) rename docs/en/observability/{apm-ui => apm}/images/storage-explorer-overview.png (100%) rename docs/en/observability/{apm-ui => apm}/images/time-series-expected-bounds-comparison.png (100%) rename docs/en/observability/{apm-ui => apm}/images/trace-explorer.png (100%) rename docs/en/observability/{apm-ui => apm}/images/traffic-transactions.png (100%) rename docs/en/observability/{apm-ui => apm}/images/transaction-icon.png (100%) rename docs/en/observability/{apm-ui => apm}/images/yellow-service.png (100%) delete mode 100644 docs/en/observability/apm/log-correlation.asciidoc delete mode 100644 docs/en/observability/apm/manage-storage.asciidoc rename docs/en/observability/apm/{ => manage-storage}/custom-index-template.asciidoc (96%) rename docs/en/observability/apm/{ => manage-storage}/data-streams.asciidoc (97%) rename docs/en/observability/apm/{ => manage-storage}/exploring-es-data.asciidoc (100%) rename docs/en/observability/apm/{ => manage-storage}/ilm-how-to.asciidoc (95%) create mode 100644 docs/en/observability/apm/manage-storage/index.asciidoc rename docs/en/observability/apm/{ => manage-storage}/ingest-pipelines.asciidoc (85%) create mode 100644 docs/en/observability/apm/manage-storage/reduce-apm-storage.asciidoc create mode 100644 docs/en/observability/apm/manage-storage/storage-and-sizing.asciidoc rename docs/en/observability/{apm-ui => apm/manage-storage}/storage-explorer.asciidoc (93%) rename docs/en/observability/{apm-ui => apm}/mobile-errors.asciidoc (100%) rename docs/en/observability/apm/{monitor-apm-server.asciidoc => monitor-apm-server/index.asciidoc} (79%) rename docs/en/observability/apm/{ => monitor-apm-server}/monitor.asciidoc (97%) rename docs/en/observability/apm/{monitoring => monitor-apm-server}/monitoring-beats.asciidoc (94%) rename docs/en/observability/apm/{monitoring => monitor-apm-server}/monitoring-internal-collection.asciidoc (98%) rename docs/en/observability/apm/{monitoring => monitor-apm-server}/monitoring-local-collection.asciidoc (99%) rename docs/en/observability/apm/{monitoring => monitor-apm-server}/monitoring-metricbeat.asciidoc (98%) rename docs/en/observability/apm/{monitoring => monitor-apm-server}/shared-monitor-config.asciidoc (100%) delete mode 100644 docs/en/observability/apm/secure-comms.asciidoc rename docs/en/observability/apm/{ => security/apm-agents}/anonymous-auth.asciidoc (93%) rename docs/en/observability/apm/{ => security/apm-agents}/api-keys.asciidoc (95%) rename docs/en/observability/apm/{secure-agent-communication.asciidoc => security/apm-agents/index.asciidoc} (90%) rename docs/en/observability/apm/{ => security/apm-agents}/secret-token.asciidoc (96%) rename docs/en/observability/apm/{ => security/apm-agents}/tls-comms.asciidoc (93%) rename docs/en/observability/{apm-ui => apm/security/data-security}/apm-spaces.asciidoc (97%) create mode 100644 docs/en/observability/apm/security/data-security/custom-filter.asciidoc create mode 100644 docs/en/observability/apm/security/data-security/delete.asciidoc create mode 100644 docs/en/observability/apm/security/data-security/filtering.asciidoc create mode 100644 docs/en/observability/apm/security/data-security/index.asciidoc rename docs/en/observability/apm/{ => security/elastic-stack}/access-api-keys.asciidoc (96%) rename docs/en/observability/apm/{feature-roles.asciidoc => security/elastic-stack/index.asciidoc} (92%) create mode 100644 docs/en/observability/apm/security/index.asciidoc create mode 100644 docs/en/observability/apm/security/user-access/annotation.asciidoc create mode 100644 docs/en/observability/apm/security/user-access/api-ui.asciidoc create mode 100644 docs/en/observability/apm/security/user-access/central-config.asciidoc create mode 100644 docs/en/observability/apm/security/user-access/index.asciidoc create mode 100644 docs/en/observability/apm/security/user-access/reader.asciidoc create mode 100644 docs/en/observability/apm/security/user-access/storage-explorer.asciidoc delete mode 100644 docs/en/observability/apm/setting-up-and-running.asciidoc rename docs/en/observability/{apm-ui => apm}/tab-widgets/apm-app-reader/content.asciidoc (100%) rename docs/en/observability/{apm-ui => apm}/tab-widgets/apm-app-reader/widget.asciidoc (100%) rename docs/en/observability/{apm-ui => apm}/tab-widgets/central-config-users/content.asciidoc (100%) rename docs/en/observability/{apm-ui => apm}/tab-widgets/central-config-users/widget.asciidoc (100%) rename docs/en/observability/{apm-ui => apm}/tab-widgets/storage-explorer-user/content.asciidoc (100%) rename docs/en/observability/{apm-ui => apm}/tab-widgets/storage-explorer-user/widget.asciidoc (100%) rename docs/en/observability/apm/{ => troubleshooting}/apm-performance-diagnostic.asciidoc (97%) rename docs/en/observability/apm/{ => troubleshooting}/apm-response-codes.asciidoc (86%) rename docs/en/observability/apm/{ => troubleshooting}/apm-server-down.asciidoc (96%) rename docs/en/observability/{apm-ui/troubleshooting.asciidoc => apm/troubleshooting/common-problems.asciidoc} (52%) rename docs/en/observability/apm/{ => troubleshooting}/debugging.asciidoc (97%) rename docs/en/observability/apm/{troubleshoot-apm.asciidoc => troubleshooting/index.asciidoc} (66%) rename docs/en/observability/apm/{ => troubleshooting}/processing-performance.asciidoc (98%) rename docs/en/observability/{apm-ui => apm/view-and-analyze}/agent-explorer.asciidoc (95%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/drill-down}/errors.asciidoc (99%) create mode 100644 docs/en/observability/apm/view-and-analyze/drill-down/index.asciidoc rename docs/en/observability/{apm-ui => apm/view-and-analyze/drill-down}/infrastructure.asciidoc (97%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/drill-down}/logs.asciidoc (63%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/drill-down}/metrics.asciidoc (98%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/drill-down}/spans.asciidoc (98%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/drill-down}/transactions.asciidoc (98%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/filter-and-search}/advanced-queries.asciidoc (95%) rename docs/en/observability/apm/{ => view-and-analyze/filter-and-search}/cross-cluster-search.asciidoc (94%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/filter-and-search}/filters.asciidoc (94%) create mode 100644 docs/en/observability/apm/view-and-analyze/filter-and-search/index.asciidoc create mode 100644 docs/en/observability/apm/view-and-analyze/index.asciidoc rename docs/en/observability/{apm-ui => apm/view-and-analyze/interpret}/correlations.asciidoc (96%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/interpret}/deployment-annotations.asciidoc (98%) create mode 100644 docs/en/observability/apm/view-and-analyze/interpret/index.asciidoc rename docs/en/observability/{apm-ui => apm/view-and-analyze/interpret}/lambda.asciidoc (94%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/interpret}/mobile-session-explorer.asciidoc (95%) rename docs/en/observability/{apm-ui => apm/view-and-analyze}/machine-learning.asciidoc (96%) rename docs/en/observability/{apm-ui => apm/view-and-analyze}/settings.asciidoc (95%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/ui-overview}/dependencies.asciidoc (98%) create mode 100644 docs/en/observability/apm/view-and-analyze/ui-overview/index.asciidoc rename docs/en/observability/{apm-ui => apm/view-and-analyze/ui-overview}/mobile-service.asciidoc (94%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/ui-overview}/new-experience-services.asciidoc (100%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/ui-overview}/service-maps.asciidoc (97%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/ui-overview}/service-overview.asciidoc (96%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/ui-overview}/services.asciidoc (98%) rename docs/en/observability/{apm-ui => apm/view-and-analyze/ui-overview}/traces.asciidoc (98%) create mode 100644 docs/en/observability/images/icons/check.svg create mode 100644 docs/en/observability/images/icons/cross.svg diff --git a/docs/en/apm-server/redirects.asciidoc b/docs/en/apm-server/redirects.asciidoc index f733cc02c8..80df5b06e6 100644 --- a/docs/en/apm-server/redirects.asciidoc +++ b/docs/en/apm-server/redirects.asciidoc @@ -35,7 +35,7 @@ The error endpoint has been deprecated. Please see {observability-guide}/apm-api [role="exclude",id="error-schema-definition"] === Error schema definition -The error schema has moved. Please see {observability-guide}/apm-api-error.html[Error Schema]. +The error schema has moved. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="error-api-examples"] === Error API examples @@ -45,42 +45,42 @@ The error API examples have moved. Please see {observability-guide}/apm-api-even [role="exclude",id="error-payload-schema"] === Error payload schema -The error schema has moved. Please see {observability-guide}/apm-api-error.html[Error Schema]. +The error schema has moved. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="error-service-schema"] === Error service schema -The error schema has moved. Please see {observability-guide}/apm-api-error.html[Error Schema]. +The error schema has moved. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="error-system-schema"] === Error system schema -The error schema has moved. Please see {observability-guide}/apm-api-error.html[Error Schema]. +The error schema has moved. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="error-context-schema"] === Error context schema -The error schema has moved. Please see {observability-guide}/apm-api-error.html[Error Schema]. +The error schema has moved. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="error-stacktraceframe-schema"] === Error stack trace frame schema -The error schema has moved. Please see {observability-guide}/apm-api-error.html[Error Schema]. +The error schema has moved. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="payload-with-error"] === Payload with error -This is no longer helpful. Please see {observability-guide}/apm-api-error.html[Error Schema]. +This is no longer helpful. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="payload-with-minimal-exception"] === Payload with minimal exception -This is no longer helpful. Please see {observability-guide}/apm-api-error.html[Error Schema]. +This is no longer helpful. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. [role="exclude",id="payload-with-minimal-log"] === Payload with minimal log -This is no longer helpful. Please see {observability-guide}/apm-api-error.html[Error Schema]. +This is no longer helpful. Please see {observability-guide}/apm-api-events.html#apm-api-error[Error Schema]. // Transaction API @@ -92,7 +92,7 @@ The transaction endpoint has been deprecated. Please see {observability-guide}/a [role="exclude",id="transaction-schema-definition"] === Transaction schema definition -The transaction schema has moved. Please see {observability-guide}/apm-api-transaction.html#apm-api-transaction-schema[Transaction Schema]. +The transaction schema has moved. Please see {observability-guide}/apm-api-events.html#apm-api-transaction-schema[Transaction Schema]. [role="exclude",id="transaction-api-examples"] === Transaction API examples @@ -102,62 +102,62 @@ The transaction API examples have moved. Please see {observability-guide}/apm-ap [role="exclude",id="transaction-span-schema"] === Transaction span schema -This schema has changed. Please see {observability-guide}/apm-api-span.html[Spans]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-span[Spans]. [role="exclude",id="transaction-payload-schema"] === Transaction payload schema -This schema has changed. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="transaction-service-schema"] === Transaction service schema -This schema has changed. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="transaction-system-schema"] === Transaction system schema -This schema has changed. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="transaction-context-schema"] === Transaction context schema -This schema has changed. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="transaction-stacktraceframe-schema"] === Transaction stack trace frame schema -This schema has changed. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="transaction-request-schema"] === Transaction request schema -This schema has changed. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="transaction-user-schema"] === Transaction user schema -This schema has changed. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This schema has changed. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="payload-with-transactions"] === Payload with transactions -This is no longer helpful. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This is no longer helpful. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="payload-with-minimal-transaction"] === Payload with minimal transaction -This is no longer helpful. Please see {observability-guide}/apm-api-transaction.html[Transactions]. +This is no longer helpful. Please see {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="payload-with-minimal-span"] === Payload with minimal span -This is no longer helpful. Please see {observability-guide}/apm-api-span.html[Spans]. +This is no longer helpful. Please see {observability-guide}/apm-api-events.html#apm-api-span[Spans]. [role="exclude",id="example-intakev2-events"] === Example Request Body -Refer to {observability-guide}/apm-api-event-example.html[Example request body]. +Refer to {observability-guide}/apm-api-events.html#apm-api-event-example[Example request body]. // V1 intake API @@ -442,49 +442,49 @@ Refer to {observability-guide}/apm-getting-started-apm-server.html[Self manage A {move-notice} -Refer to {observability-guide}/_apm_server_binary.html[APM Server binary]. +Refer to {observability-guide}/get-started-with-apm-server-binary.html[APM Server binary]. [role="exclude",id="installing"] === Step 1: Install {move-notice} -Refer to {observability-guide}/apm-installing.html[Step 1: Install]. +Refer to {observability-guide}/get-started-with-apm-server-binary.html#apm-installing[Step 1: Install]. [role="exclude",id="apm-server-configuration"] === Step 2: Set up and configure {move-notice} -Refer to {observability-guide}/apm-server-configuration.html[Step 2: Set up and configure]. +Refer to {observability-guide}/get-started-with-apm-server-binary.html#apm-server-configuration[Step 2: Set up and configure]. [role="exclude",id="apm-server-starting"] === Step 3: Start {move-notice} -Refer to {observability-guide}/apm-server-starting.html[Step 3: Start]. +Refer to {observability-guide}/get-started-with-apm-server-binary.html#apm-server-starting[Step 3: Start]. [role="exclude",id="next-steps"] === Step 4: Next steps {move-notice} -Refer to {observability-guide}/apm-next-steps.html[Step 4: Next steps]. +Refer to {observability-guide}/get-started-with-apm-server-binary.html#apm-next-steps[Step 4: Next steps]. [role="exclude",id="setup-repositories"] === Repositories for APT and YUM {move-notice} -Refer to {observability-guide}/apm-setup-repositories.html[Repositories for APT and YUM]. +Refer to {observability-guide}/get-started-with-apm-server-binary.html#apm-setup-repositories[Repositories for APT and YUM]. [role="exclude",id="running-on-docker"] === Run APM Server on Docker {move-notice} -Refer to {observability-guide}/apm-running-on-docker.html[Run APM Server on Docker]. +Refer to {observability-guide}/get-started-with-apm-server-binary.html#apm-running-on-docker[Run APM Server on Docker]. [role="exclude",id="_fleet_managed_apm_server"] === Fleet-managed APM Server @@ -498,28 +498,28 @@ Refer to {observability-guide}/get-started-with-fleet-apm-server.html[Fleet-mana {move-notice} -Refer to {observability-guide}/_step_1_set_up_fleet.html[Step 1: Set up Fleet]. +Refer to {observability-guide}/get-started-with-fleet-apm-server.html#_step_1_set_up_fleet[Step 1: Set up Fleet]. [role="exclude",id="_step_2_add_and_configure_the_apm_integration"] === Step 2: Add and configure the APM integration {move-notice} -Refer to {observability-guide}/add-apm-integration.html[Step 2: Add and configure the APM integration]. +Refer to {observability-guide}/get-started-with-fleet-apm-server.html#add-apm-integration[Step 2: Add and configure the APM integration]. [role="exclude",id="_step_3_install_apm_agents"] === Step 3: Install APM agents {move-notice} -Refer to {observability-guide}/_step_3_install_apm_agents.html[Step 3: Install APM agents]. +Refer to {observability-guide}/get-started-with-fleet-apm-server.html#_step_3_install_apm_agents[Step 3: Install APM agents]. [role="exclude",id="_step_4_view_your_data"] === Step 4: View your data {move-notice} -Refer to {observability-guide}/_step_4_view_your_data.html[Step 4: View your data]. +Refer to {observability-guide}/get-started-with-fleet-apm-server.html#_step_4_view_your_data[Step 4: View your data]. [role="exclude",id="data-model"] === Data Model @@ -621,7 +621,7 @@ Refer to {observability-guide}/apm-data-security-delete.html[Delete sensitive da {move-notice} -Refer to {observability-guide}/apm-distributed-tracing.html[Distributed tracing]. +Refer to {observability-guide}/apm-data-model-traces.html#apm-distributed-tracing[Distributed tracing]. [role="exclude",id="apm-rum"] === Real User Monitoring (RUM) @@ -642,14 +642,14 @@ Refer to {observability-guide}/apm-sampling.html[Transaction sampling]. {move-notice} -Refer to {observability-guide}/apm-configure-head-based-sampling.html[Configure head-based sampling]. +Refer to {observability-guide}/apm-sampling.html#apm-configure-head-based-sampling[Configure head-based sampling]. [role="exclude",id="configure-tail-based-sampling"] === Configure tail-based sampling {move-notice} -Refer to {observability-guide}/apm-configure-tail-based-sampling.html[Configure tail-based sampling]. +Refer to {observability-guide}/apm-sampling.html#apm-configure-tail-based-sampling[Configure tail-based sampling]. [role="exclude",id="log-correlation"] === Logging integration @@ -1191,7 +1191,7 @@ Refer to {observability-guide}/apm-monitoring-local-collection.html[Use local co {move-notice} -Refer to {observability-guide}/apm-select-metrics.html[The select metrics]. +Refer to {observability-guide}/apm-monitoring-local-collection.html#apm-select-metrics[The select metrics]. [role="exclude",id="monitoring-metricbeat-collection"] === Use Metricbeat collection @@ -1226,45 +1226,45 @@ Refer to {observability-guide}/apm-api-events.html[Elastic APM events intake API {move-notice} -Refer to {observability-guide}/apm-api-metadata.html[Metadata]. +Refer to {observability-guide}/apm-api-events.html#apm-api-metadata[Metadata]. [discrete] [[api-metadata-schema]] ==== Metadata scheme -Refer to {observability-guide}/apm-api-metadata.html#apm-api-metadata-schema[Metadata scheme]. +Refer to {observability-guide}/apm-api-events.html#apm-api-metadata-schema[Metadata scheme]. [role="exclude",id="api-transaction"] === Transactions {move-notice} -Refer to {observability-guide}/apm-api-transaction.html[Transactions]. +Refer to {observability-guide}/apm-api-events.html#apm-api-transaction[Transactions]. [role="exclude",id="api-span"] === Spans {move-notice} -Refer to {observability-guide}/apm-api-span.html[Spans]. +Refer to {observability-guide}/apm-api-events.html#apm-api-span[Spans]. [role="exclude",id="api-error"] === Errors {move-notice} -Refer to {observability-guide}/apm-api-error.html[Errors]. +Refer to {observability-guide}/apm-api-events.html#apm-api-error[Errors]. [role="exclude",id="api-metricset"] === Metrics -Refer to {observability-guide}/apm-api-metricset.html[Metrics] +Refer to {observability-guide}/apm-api-events.html#apm-api-metricset[Metrics] [role="exclude",id="api-event-example"] === Example request body {move-notice} -Refer to {observability-guide}/apm-api-event-example.html[Example request body]. +Refer to {observability-guide}/apm-api-events.html#apm-api-event-example[Example request body]. [role="exclude",id="api-config"] === Elastic APM agent configuration API diff --git a/docs/en/observability/apm-ui/apm-alerts.asciidoc b/docs/en/observability/apm-alerts.asciidoc similarity index 95% rename from docs/en/observability/apm-ui/apm-alerts.asciidoc rename to docs/en/observability/apm-alerts.asciidoc index 99a6b6f5ef..063322a2cd 100644 --- a/docs/en/observability/apm-ui/apm-alerts.asciidoc +++ b/docs/en/observability/apm-alerts.asciidoc @@ -1,9 +1,5 @@ [[apm-alerts]] -=== Alerts and rules - -++++ -Create an alert -++++ += APM alerts and rules The APM UI allows you to define **rules** to detect complex conditions within your APM data and trigger built-in **actions** when those conditions are met. @@ -28,7 +24,7 @@ see Kibana's {kibana-ref}/create-and-manage-rules.html[Create and manage rules]. [float] [[apm-create-transaction-alert]] -=== Example: create a latency anomaly rule +== Example: create a latency anomaly rule Latency anomaly rules trigger when the latency of a service is abnormal. Because some parts of an application are more important than others, and have a different @@ -71,7 +67,7 @@ Click **Save**. Your rule has been created and is now active! [float] [[apm-create-error-alert]] -=== Example: create an error count threshold alert +== Example: create an error count threshold alert The error count threshold alert triggers when the number of errors in a service exceeds a defined threshold. Because some errors are more important than others, this guide will focus a specific error group ID. @@ -131,13 +127,13 @@ Click **Save**. The alert has been created and is now active! [float] [[apm-alert-view-active]] -=== View active alerts +== View active alerts Active alerts are displayed and grouped in multiple ways in the APM UI. [float] [[apm-alert-view-group]] -==== View alerts by service group +=== View alerts by service group If you're using the <> feature, you can view alerts by service group. From the service group overview page, click the red alert indicator to open the **Alerts** tab with a predefined filter that matches the filter used when creating the service group. @@ -147,7 +143,7 @@ image::./images/apm-service-group.png[Example view of service group in the APM U [float] [[apm-alert-view-service]] -==== View alerts by service +=== View alerts by service Alerts can be viewed within the context of any service. After selecting a service, go to the **Alerts** tab to view any alerts that are active for the selected service. @@ -157,7 +153,7 @@ image::./images/active-alert-service.png[View active alerts by service] [float] [[apm-alert-manage]] -=== Manage alerts and rules +== Manage alerts and rules From the APM UI, select **Alerts and rules** > **Manage rules** to be taken to the {kib} *{rules-ui}* page. @@ -165,7 +161,7 @@ From this page, you can disable, mute, and delete APM alerts. [float] [[apm-alert-more-info]] -=== More information +== More information See {kibana-ref}/alerting-getting-started.html[Alerting] for more information. diff --git a/docs/en/observability/apm-ui/apm-app-users.asciidoc b/docs/en/observability/apm-ui/apm-app-users.asciidoc deleted file mode 100644 index d54c913fac..0000000000 --- a/docs/en/observability/apm-ui/apm-app-users.asciidoc +++ /dev/null @@ -1,351 +0,0 @@ -[[apm-app-users]] -== APM UI users and privileges - -:beat_default_index_prefix: apm -:annotation_index: observability-annotations - -++++ -Users and privileges -++++ - -Use role-based access control to grant users access to secured -resources. The roles that you set up depend on your organization's security -requirements and the minimum privileges required to use specific features. - -{es-security-features} provides {ref}/built-in-roles.html[built-in roles] that grant a -subset of the privileges needed by APM users. -When possible, assign users the built-in roles to minimize the affect of future changes on your security strategy. -If no built-in role is available, you can assign users the privileges needed to accomplish a specific task. -In general, there are three types of privileges you'll work with: - -* **Elasticsearch cluster privileges**: Manage the actions a user can perform against your cluster. -* **Elasticsearch index privileges**: Control access to the data in specific indices your cluster. -* **Kibana feature privileges**: Grant users write or read access to features and apps within Kibana. - -Select your use-case to get started: - -* <> -* <> -* <> -* <> -* <> - -//// -*********************************** *********************************** -//// - -[[apm-app-reader]] -=== APM reader user - -++++ -Create an APM reader user -++++ - -APM reader users typically need to view the APM UI and dashboards and visualizations that use APM data. -These users might also need to create and edit dashboards, visualizations, and machine learning jobs. - -[float] -[[apm-app-reader-full]] -==== APM reader - -To create an APM reader user: - -. Create a new role, named something like `read-apm`, and assign the following privileges: -+ --- -:apm-read-view: -:apm-monitor: -include::./tab-widgets/apm-app-reader/widget.asciidoc[] -:!apm-read-view: -:!apm-monitor: --- - -. Assign the `read-apm` role created in the previous step, and the following built-in roles to -any APM reader users: -+ -[options="header"] -|==== -|Role | Purpose - -|`kibana_admin` -|Grants access to all features in Kibana. - -|`machine_learning_admin` -|Grants the privileges required to create, update, and view machine learning jobs -|==== - -[float] -[[apm-app-reader-partial]] -==== Partial APM reader - -In some instances, you may wish to restrict certain Kibana apps that a user has access to. - -. Create a new role, named something like `read-apm-partial`, and assign the following privileges: -+ --- -include::./tab-widgets/apm-app-reader/widget.asciidoc[] --- - -. Assign feature privileges to any Kibana feature that the user needs access to. -Here are two examples: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -| Kibana -| `Read` or `All` on the APM and User Experience feature -| Allow the use of the the APM and User Experience apps - -| Kibana -| `Read` or `All` on Dashboards and Discover -| Allow the user to view, edit, and create dashboards, as well as browse data. -|==== - -. Finally, assign the following role if a user needs to enable and edit machine learning features: -+ -[options="header"] -|==== -|Role | Purpose - -|`machine_learning_admin` -|Grants the privileges required to create, update, and view machine learning jobs -|==== - -//// -*********************************** *********************************** -//// - -[[apm-app-annotation-user-create]] -=== APM UI annotation user - -++++ -Create an annotation user -++++ - -NOTE: By default, the `viewer` and `editor` built-in roles provide read access to Observability annotations. -You only need to create an annotation user to write to the annotations index -({kibana-ref}/apm-settings-kb.html[`xpack.observability.annotations.index`]). - -[float] -[[apm-app-annotation-user]] -==== Annotation user - -View deployment annotations in the APM UI. - -. Create a new role, named something like `annotation_user`, -and assign the following privileges: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -|Index -|`read` on +\{ANNOTATION_INDEX\}+^1^ -|Read-only access to the observability annotation index - -|Index -|`view_index_metadata` on +\{ANNOTATION_INDEX\}+^1^ -|Read-only access to observability annotation index metadata -|==== -+ -^1^ +\{ANNOTATION_INDEX\}+ should be the index name you've defined in -{kibana-ref}/apm-settings-kb.html[`xpack.observability.annotations.index`]. - -. Assign the `annotation_user` created previously, and the roles and privileges necessary to create -a <> or <> APM reader to any users that need to view annotations in the APM UI - -[float] -[[apm-app-annotation-api]] -==== Annotation API - -See <>. - -//// -*********************************** *********************************** -//// - -[[apm-app-central-config-user]] -=== APM UI central config user - -++++ -Create a central config user -++++ - -[float] -[[apm-app-central-config-manager]] -==== Central configuration manager - -Central configuration users need to be able to view, create, update, and delete APM agent configurations. - -. Create a new role, named something like `central-config-manager`, and assign the following privileges: -+ --- -include::./tab-widgets/central-config-users/widget.asciidoc[] --- -+ -TIP: Using the deprecated APM Server binaries? -Add the privileges under the **Classic APM indices** tab above. - -. Assign the `central-config-manager` role created in the previous step, -and the following Kibana feature privileges to anyone who needs to manage central configurations: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -| Kibana -|`All` on the APM and User Experience feature -|Allow full use of the APM and User Experience apps -|==== - -[float] -[[apm-app-central-config-reader]] -==== Central configuration reader - -In some instances, you may wish to create a user that can only read central configurations, -but not create, update, or delete them. - -. Create a new role, named something like `central-config-reader`, and assign the following privileges: -+ --- -include::./tab-widgets/central-config-users/widget.asciidoc[] --- -+ -TIP: Using the deprecated APM Server binaries? -Add the privileges under the **Classic APM indices** tab above. - -. Assign the `central-config-reader` role created in the previous step, -and the following Kibana feature privileges to anyone who needs to read central configurations: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -| Kibana -|`read` on the APM and User Experience feature -|Allow read access to the APM and User Experience apps -|==== - -[float] -[[apm-app-central-config-api]] -==== Central configuration API - -See <>. - -//// -*********************************** *********************************** -//// - -[[apm-app-storage-explorer-user-create]] -=== APM UI storage explorer user - -++++ -Create a storage explorer user -++++ - -[float] -[[apm-app-storage-explorer-user]] -==== Storage Explorer user - -View the **Storage Explorer** in the APM UI. - -. Create a new role, named something like `storage-explorer_user`, -and assign the following privileges: -+ --- -include::./tab-widgets/storage-explorer-user/widget.asciidoc[] --- - -. Assign the `storage-explorer_user` created previously, and the roles and privileges necessary to create -a <> or <> APM reader to any users that need to view **Storage Explorer** in the APM UI. - -//// -*********************************** *********************************** -//// - -[[apm-app-api-user]] -=== APM UI API user - -++++ -Create an API user -++++ - -[float] -[[apm-app-api-config-manager]] -==== Central configuration API - -Users can list, search, create, update, and delete central configurations via the APM UI API. - -. Assign the following Kibana feature privileges: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -| Kibana -|`all` on the APM and User Experience feature -|Allow all access to the APM and User Experience apps -|==== - -[float] -[[apm-app-api-config-reader]] -==== Central configuration API reader - -Sometimes a user only needs to list and search central configurations via the APM UI API. - -. Assign the following Kibana feature privileges: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -| Kibana -|`read` on the APM and User Experience feature -|Allow read access to the APM and User Experience apps -|==== - -[float] -[[apm-app-api-annotation-manager]] -==== Annotation API - -Users can use the annotation API to create annotations on their APM data. - -. Create a new role, named something like `annotation_role`, -and assign the following privileges: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -|Index -|`manage` on +{annotation_index}+ index -|Check if the +{annotation_index}+ index exists - -|Index -|`read` on +{annotation_index}+ index -|Read the +{annotation_index}+ index - -|Index -|`create_index` on +{annotation_index}+ index -|Create the +{annotation_index}+ index - -|Index -|`create_doc` on +{annotation_index}+ index -|Create new annotations in the +{annotation_index}+ index -|==== - -. Assign the `annotation_role` created previously, -and the following Kibana feature privileges to any annotation API users: -+ -[options="header"] -|==== -|Type | Privilege | Purpose - -| Kibana -|`all` on the APM and User Experience feature -|Allow all access to the APM and User Experience apps -|==== - -//LEARN MORE -//Learn more about <>. diff --git a/docs/en/observability/apm-ui/index.asciidoc b/docs/en/observability/apm-ui/index.asciidoc deleted file mode 100644 index 5c3303acd7..0000000000 --- a/docs/en/observability/apm-ui/index.asciidoc +++ /dev/null @@ -1,76 +0,0 @@ -[[apm-ui]] -= Navigate the APM UI - -TIP: For task-oriented guides, see the <>. - -The APM UI in {kib} allows you to monitor your software services and applications in real-time; -visualize detailed performance information on your services, -identify and analyze errors, -and monitor host-level and APM agent-specific metrics like JVM and Go runtime metrics. - -Having access to application-level insights with just a few clicks can drastically decrease the time you spend -debugging errors, slow response times, and crashes. - -For example, you can see information about response times, requests per minute, and status codes per endpoint. -You can even dive into a specific request sample and get a complete waterfall view of what your application is spending its time on. -You might see that your bottlenecks are in database queries, cache calls, or external requests. -For each incoming request and each application error, -you can also see contextual information such as the request header, user information, -system values, or custom data that you manually attached to the request. - -For a quick, high-level overview of the health and performance of your application, -start with: - -* <> -* <> -* <> -* <> - -Notice something awry? Select a service or trace and dive deeper with: - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -Configure and troubleshoot the APM UI: - -* <> -* <> -* <> - -include::services.asciidoc[leveloffset=-1] - -include::new-experience-services.asciidoc[leveloffset=+2] - -include::traces.asciidoc[leveloffset=-1] - -include::dependencies.asciidoc[leveloffset=-1] - -include::service-maps.asciidoc[leveloffset=-1] - -include::service-overview.asciidoc[leveloffset=-1] - -include::mobile-service.asciidoc[leveloffset=-1] - -include::transactions.asciidoc[leveloffset=-1] - -include::spans.asciidoc[leveloffset=-1] - -include::errors.asciidoc[leveloffset=-1] - -include::metrics.asciidoc[leveloffset=-1] - -include::infrastructure.asciidoc[leveloffset=-1] - -include::logs.asciidoc[leveloffset=-1] - -include::apm-app-users.asciidoc[] - -include::settings.asciidoc[] - -include::troubleshooting.asciidoc[] diff --git a/docs/en/observability/apm.asciidoc b/docs/en/observability/apm.asciidoc index 4c9e3693c0..ba2f844727 100644 --- a/docs/en/observability/apm.asciidoc +++ b/docs/en/observability/apm.asciidoc @@ -46,36 +46,27 @@ like JVM metrics in the Java Agent, and Go runtime metrics in the Go Agent. Use <> to quickly spin up an APM deployment. Want to host everything yourself instead? See <>. -include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm-server.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/data-model.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/features.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm-ui/index.asciidoc[leveloffset=+1] - -include::{observability-docs-root}/docs/en/observability/apm/how-to.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/open-telemetry.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/manage-storage.asciidoc[] - +//// +Subsections +//// + +// Intro content +include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/data-model/index.asciidoc[leveloffset=+1] +// Get data +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/index.asciidoc[leveloffset=+1] +// Do things with that data +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/act-on-data/index.asciidoc[leveloffset=+1] +// Fine-tune your implementation +include::{observability-docs-root}/docs/en/observability/apm/security/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/index.asciidoc[leveloffset=+1] include::{observability-docs-root}/docs/en/observability/apm/configure/index.asciidoc[leveloffset=+1] - -include::{observability-docs-root}/docs/en/observability/apm/setting-up-and-running.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/secure-comms.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/monitor-apm-server.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/api.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm-ui/api.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/troubleshoot-apm.asciidoc[] - +include::{observability-docs-root}/docs/en/observability/apm/monitor-apm-server/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/api/index.asciidoc[leveloffset=+1] +// Fix something +include::{observability-docs-root}/docs/en/observability/apm/troubleshooting/index.asciidoc[leveloffset=+1] +// Update an existing implementation include::{observability-docs-root}/docs/en/observability/apm/upgrading.asciidoc[] - include::{observability-docs-root}/docs/en/observability/apm/release-notes.asciidoc[leveloffset=+1] - -include::{observability-docs-root}/docs/en/observability/apm/known-issues.asciidoc[leveloffset=+1] \ No newline at end of file +include::{observability-docs-root}/docs/en/observability/apm/known-issues.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm-ui/custom-links.asciidoc b/docs/en/observability/apm/act-on-data/custom-links.asciidoc similarity index 97% rename from docs/en/observability/apm-ui/custom-links.asciidoc rename to docs/en/observability/apm/act-on-data/custom-links.asciidoc index 0e235c125e..f4bc31408b 100644 --- a/docs/en/observability/apm-ui/custom-links.asciidoc +++ b/docs/en/observability/apm/act-on-data/custom-links.asciidoc @@ -1,5 +1,5 @@ [[apm-custom-links]] -=== Custom links += Custom links in the APM UI ++++ Create custom links @@ -14,7 +14,7 @@ Ready to dive in? Jump straight to the <>. [float] [[custom-links-create]] -=== Create a link +== Create a link Each custom link consists of a label, URL, and optional filter. The easiest way to create a custom link is from within the actions dropdown in the transaction detail page. @@ -26,7 +26,7 @@ and selecting **Create custom link**. [float] [[custom-links-label]] -==== Label +=== Label The name of your custom link. The actions context menu displays this text, so keep it as short as possible. @@ -35,7 +35,7 @@ TIP: Custom links are displayed alphabetically in the actions menu. [float] [[custom-links-url]] -==== URL +=== URL The URL your link points to. URLs support dynamic field name variables, encapsulated in double curly brackets: `{{field.name}}`. @@ -50,7 +50,7 @@ image::./images/example-metadata.png[Example metadata] [float] [[custom-links-filters]] -==== Filters +=== Filters Filter each link to only appear for specific services or transactions. You can filter on the following fields: @@ -64,7 +64,7 @@ Multiple values are allowed when comma-separated. [float] [[custom-links-examples]] -=== Custom link examples +== Custom link examples // Relevant documentation links :jira-query-params: https://confluence.atlassian.com/jirakb/how-to-create-issues-using-direct-html-links-in-jira-server-159474.html @@ -75,7 +75,7 @@ Take a look at the examples below and customize them to your liking! [float] [[custom-links-examples-email]] -==== Email +=== Email Email the owner of a service. @@ -98,7 +98,7 @@ It will only appear on services with the name `python-backend`. [float] [[custom-links-examples-gh]] -==== GitHub issue +=== GitHub issue Open a GitHub issue with pre-populated metadata from the selected trace sample. @@ -127,7 +127,7 @@ See the {github-query-params}[GitHub automation documentation] for a full list o [float] [[custom-links-examples-jira]] -==== Jira task +=== Jira task Create a Jira task with pre-populated metadata from the selected trace sample. @@ -155,7 +155,7 @@ for a full list of supported query parameters. [float] [[custom-links-examples-kib]] -==== Kibana dashboards +=== Kibana dashboards Link to a custom dashboard in Kibana. @@ -176,7 +176,7 @@ There are no filters set. [float] [[custom-links-examples-slack]] -==== Slack channel +=== Slack channel Open a specified slack channel. @@ -199,7 +199,7 @@ It only appears when `transaction.name` is `GET user/login`. [float] [[custom-links-examples-web]] -==== Website +=== Website Open an internal or external website. diff --git a/docs/en/observability/apm/act-on-data/index.asciidoc b/docs/en/observability/apm/act-on-data/index.asciidoc new file mode 100644 index 0000000000..a3036dcf71 --- /dev/null +++ b/docs/en/observability/apm/act-on-data/index.asciidoc @@ -0,0 +1,24 @@ +[[apm-act-on-data]] += Act on application data + +++++ +Act on data +++++ + +In addition to exploring visualizations in the APM UI in {kib}, you can make your application data +more actionable with: + +* *Alerts and rules*: The APM UI allows you to define rules to detect complex + conditions within your APM data and trigger built-in actions when those conditions are met. + Read more about alerts and rules in the <>. +* *Custom links*: Build URLs that contain relevant metadata from a specific trace. + For example, you can create a link that will take you to a page where you can open a new GitHub issue + with context already auto-populated in the issue body. + These links will be shown in the _Actions_ context menu in selected areas of the APM UI (for example, by transaction details). + Read more in <>. + +:leveloffset: +1 + +include::{observability-docs-root}/docs/en/observability/apm/act-on-data/custom-links.asciidoc[] + +:!leveloffset: diff --git a/docs/en/observability/apm-ui/api.asciidoc b/docs/en/observability/apm/api/api-ui.asciidoc similarity index 94% rename from docs/en/observability/apm-ui/api.asciidoc rename to docs/en/observability/apm/api/api-ui.asciidoc index 33a64d5d75..8bf85cf5ff 100644 --- a/docs/en/observability/apm-ui/api.asciidoc +++ b/docs/en/observability/apm/api/api-ui.asciidoc @@ -1,5 +1,5 @@ [[apm-app-api]] -== APM UI API += APM UI API Some APM UI features are provided via a REST API: @@ -10,7 +10,7 @@ Some APM UI features are provided via a REST API: [float] [[apm-api-example]] -=== Using the APIs +== Using the APIs // The following content is reused throughout the API docs // tag::using-the-APIs[] @@ -68,7 +68,7 @@ curl -X POST \ [float] [[kibana-api]] -=== Kibana API +== Kibana API In addition to the APM specific API endpoints, Kibana provides its own <> which you can use to automate certain aspects of configuring and deploying Kibana. @@ -79,7 +79,7 @@ which you can use to automate certain aspects of configuring and deploying Kiban //// [[apm-agent-config-api]] -=== Agent Configuration API +== Agent Configuration API The APM agent configuration API allows you to fine-tune your APM agent configuration, without needing to redeploy your application. @@ -93,44 +93,44 @@ The following APM agent configuration APIs are available: [float] [[use-agent-config-api]] -==== How to use APM APIs +=== How to use APM APIs .Expand for required headers, privileges, and usage details [%collapsible%closed] -====== -include::api.asciidoc[tag=using-the-APIs] -====== +===== +include::api-ui.asciidoc[tag=using-the-APIs] +===== //// ******************************************************* //// [[apm-update-config]] -==== Create or update configuration +=== Create or update configuration [float] [[apm-update-config-req]] -===== Request +==== Request `PUT /api/apm/settings/agent-configuration` [float] [role="child_attributes"] [[apm-update-config-req-body]] -===== Request body +==== Request body `service`:: (required, object) Service identifying the configuration to create or update. + .Properties of `service` [%collapsible%open] -====== +===== `name` ::: (required, string) Name of service `environment` ::: (optional, string) Environment of service -====== +===== `settings`:: (required) Key/value object with option name and option value. @@ -141,7 +141,7 @@ include::api.asciidoc[tag=using-the-APIs] [float] [[apm-update-config-example]] -===== Example +==== Example [source,curl] -------------------------------------------------- @@ -166,35 +166,35 @@ PUT /api/apm/settings/agent-configuration [[apm-delete-config]] -==== Delete configuration +=== Delete configuration [float] [[apm-delete-config-req]] -===== Request +==== Request `DELETE /api/apm/settings/agent-configuration` [float] [role="child_attributes"] [[apm-delete-config-req-body]] -===== Request body +==== Request body `service`:: (required, object) Service identifying the configuration to delete + .Properties of `service` [%collapsible%open] -====== +===== `name` ::: (required, string) Name of service `environment` ::: (optional, string) Environment of service -====== +===== [float] [[apm-delete-config-example]] -===== Example +==== Example [source,curl] -------------------------------------------------- @@ -212,17 +212,17 @@ DELETE /api/apm/settings/agent-configuration //// [[apm-list-config]] -==== List configuration +=== List configuration [float] [[apm-list-config-req]] -===== Request +==== Request `GET /api/apm/settings/agent-configuration` [float] [[apm-list-config-body]] -===== Response body +==== Response body [source,js] -------------------------------------------------- @@ -273,7 +273,7 @@ DELETE /api/apm/settings/agent-configuration [float] [[apm-list-config-example]] -===== Example +==== Example [source,curl] -------------------------------------------------- @@ -285,38 +285,38 @@ GET /api/apm/settings/agent-configuration //// [[apm-search-config]] -==== Search configuration +=== Search configuration [float] [[apm-search-config-req]] -===== Request +==== Request `POST /api/apm/settings/agent-configuration/search` [float] [role="child_attributes"] [[apm-search-config-req-body]] -===== Request body +==== Request body `service`:: (required, object) Service identifying the configuration. + .Properties of `service` [%collapsible%open] -====== +===== `name` ::: (required, string) Name of service `environment` ::: (optional, string) Environment of service -====== +===== `etag`:: (required) etag is sent by the APM agent to indicate the etag of the last successfully applied configuration. If the etag matches an existing configuration its `applied_by_agent` property will be set to `true`. Every time a configuration is edited `applied_by_agent` is reset to `false`. [float] [[apm-search-config-body]] -===== Response body +==== Response body [source,js] -------------------------------------------------- @@ -341,7 +341,7 @@ GET /api/apm/settings/agent-configuration [float] [[apm-search-config-example]] -===== Example +==== Example [source,curl] -------------------------------------------------- @@ -361,7 +361,7 @@ POST /api/apm/settings/agent-configuration/search //// [[apm-annotation-api]] -=== Annotation API +== Annotation API The Annotation API allows you to annotate visualizations in the APM UI with significant events, like deployments, allowing you to easily see how these events are impacting the performance of your existing applications. @@ -379,44 +379,44 @@ The following APIs are available: [float] [[use-annotation-api]] -==== How to use APM APIs +=== How to use APM APIs .Expand for required headers, privileges, and usage details [%collapsible%closed] -====== -include::api.asciidoc[tag=using-the-APIs] -====== +===== +include::api-ui.asciidoc[tag=using-the-APIs] +===== //// ******************************************************* //// [[apm-annotation-create]] -==== Create or update annotation +=== Create or update annotation [float] [[apm-annotation-config-req]] -===== Request +==== Request `POST /api/apm/services/:serviceName/annotation` [float] [role="child_attributes"] [[apm-annotation-config-req-body]] -===== Request body +==== Request body `service`:: (required, object) Service identifying the configuration to create or update. + .Properties of `service` [%collapsible%open] -====== +===== `version` ::: (required, string) Version of service. `environment` ::: (optional, string) Environment of service. -====== +===== `@timestamp`:: (required, string) The date and time of the annotation. Must be in https://www.w3.org/TR/NOTE-datetime[ISO 8601] format. @@ -431,7 +431,7 @@ While you can add additional tags, you cannot remove the `apm` tag. [float] [[apm-annotation-config-example]] -===== Example +==== Example The following example creates an annotation for a service named `opbeans-java`. @@ -453,7 +453,7 @@ curl -X POST \ [float] [[apm-annotation-config-body]] -===== Response body +==== Response body [source,js] -------------------------------------------------- @@ -492,7 +492,7 @@ curl -X POST \ //// [[apm-rum-sourcemap-api]] -=== RUM source map API +== RUM source map API IMPORTANT: This endpoint is only compatible with the {apm-guide-ref}/index.html[APM integration for Elastic Agent]. @@ -514,7 +514,7 @@ The following APIs are available: [float] [[limit-sourcemap-api]] -==== Max payload size +=== Max payload size {kib}'s maximum payload size is 1mb. If you attempt to upload a source map that exceeds the max payload size, you will get a `413` error. @@ -524,40 +524,40 @@ with the `server.maxPayload` variable. [float] [[use-sourcemap-api]] -==== How to use APM APIs +=== How to use APM APIs .Expand for required headers, privileges, and usage details [%collapsible%closed] -====== -include::api.asciidoc[tag=using-the-APIs] -====== +===== +include::api-ui.asciidoc[tag=using-the-APIs] +===== //// ******************************************************* //// [[rum-sourcemap-post]] -==== Create or update source map +=== Create or update source map Create or update a source map for a specific service and version. [float] [[rum-sourcemap-post-privs]] -===== Privileges +==== Privileges The user accessing this endpoint requires `All` Kibana privileges for the APM and User Experience feature. For more information, see {kibana-ref}/kibana-privileges.html[Kibana privileges]. [float] [[apm-sourcemap-post-req]] -===== Request +==== Request `POST /api/apm/sourcemaps` [float] [role="child_attributes"] [[apm-sourcemap-post-req-body]] -===== Request body +==== Request body `service_name`:: (required, string) The name of the service that the service map should apply to. @@ -574,7 +574,7 @@ https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k[ [float] [[apm-sourcemap-post-example]] -===== Examples +==== Examples The following example uploads a source map for a service named `foo` and a service version of `1.0.0`: @@ -593,7 +593,7 @@ curl -X POST "http://localhost:5601/api/apm/sourcemaps" \ [float] [[apm-sourcemap-post-body]] -===== Response body +==== Response body [source,js] -------------------------------------------------- @@ -619,26 +619,26 @@ curl -X POST "http://localhost:5601/api/apm/sourcemaps" \ //// [[rum-sourcemap-get]] -==== Get source maps +=== Get source maps Returns an array of Fleet artifacts, including source map uploads. [float] [[rum-sourcemap-get-privs]] -===== Privileges +==== Privileges The user accessing this endpoint requires `Read` or `All` Kibana privileges for the APM and User Experience feature. For more information, see {kibana-ref}/kibana-privileges.html[Kibana privileges]. [float] [[apm-sourcemap-get-req]] -===== Request +==== Request `GET /api/apm/sourcemaps` [float] [[apm-sourcemap-get-example]] -===== Example +==== Example The following example requests all uploaded source maps: @@ -652,7 +652,7 @@ curl -X GET "http://localhost:5601/api/apm/sourcemaps" \ [float] [[apm-sourcemap-get-body]] -===== Response body +==== Response body [source,js] -------------------------------------------------- @@ -702,26 +702,26 @@ curl -X GET "http://localhost:5601/api/apm/sourcemaps" \ //// [[rum-sourcemap-delete]] -==== Delete source map +=== Delete source map Delete a previously uploaded source map. [float] [[rum-sourcemap-delete-privs]] -===== Privileges +==== Privileges The user accessing this endpoint requires `All` Kibana privileges for the APM and User Experience feature. For more information, see {kibana-ref}/kibana-privileges.html[Kibana privileges]. [float] [[apm-sourcemap-delete-req]] -===== Request +==== Request `DELETE /api/apm/sourcemaps/:id` [float] [[apm-sourcemap-delete-example]] -===== Example +==== Example The following example deletes a source map with an id of `apm:foo-1.0.0-644fd5a9`: @@ -735,7 +735,7 @@ curl -X DELETE "http://localhost:5601/api/apm/sourcemaps/apm:foo-1.0.0-644fd5a9" [float] [[apm-sourcemap-delete-body]] -===== Response body +==== Response body [source,js] -------------------------------------------------- @@ -748,7 +748,7 @@ curl -X DELETE "http://localhost:5601/api/apm/sourcemaps/apm:foo-1.0.0-644fd5a9" //// [[apm-agent-key-api]] -=== APM agent Key API +== APM agent Key API The APM agent Key API allows you to configure APM agent keys to authorize requests from APM agents to the APM Server. @@ -758,34 +758,34 @@ The following APM agent key APIs are available: [float] [[use-agent-key-api]] -==== How to use APM APIs +=== How to use APM APIs .Expand for required headers, privileges, and usage details [%collapsible%closed] -====== -include::api.asciidoc[tag=using-the-APIs] -====== +===== +include::api-ui.asciidoc[tag=using-the-APIs] +===== //// ******************************************************* //// [[apm-create-agent-key]] -==== Create agent key +=== Create agent key Create an APM agent API key. Specify API key privileges in the request body at creation time. [float] [[apm-create-agent-key-privileges]] -===== Privileges +==== Privileges The user creating an APM agent API key must have at least the `manage_own_api_key` cluster privilege and the APM application-level privileges that it wishes to grant. [float] -====== Example role +===== Example role The example below uses the Kibana {kibana-ref}/role-management-api.html[role management API] to create a role named `apm_agent_key_user`. Create and assign this role to a user that wishes to create APM agent API keys. @@ -813,7 +813,7 @@ POST /_security/role/apm_agent_key_user [float] [[apm-create-agent-key-req]] -===== Request +==== Request `POST /api/apm/agent_keys` @@ -821,7 +821,7 @@ POST /_security/role/apm_agent_key_user [float] [role="child_attributes"] [[apm-create-agent-key-req-body]] -===== Request body +==== Request body `name`:: (required, string) Name of the APM agent key. @@ -835,7 +835,7 @@ POST /_security/role/apm_agent_key_user [float] [[apm-agent-key-create-example]] -===== Example +==== Example [source,curl] -------------------------------------------------- @@ -849,7 +849,7 @@ POST /api/apm/agent_keys [float] [[apm-agent-key-create-body]] -===== Response body +==== Response body [source,js] -------------------------------------------------- diff --git a/docs/en/observability/apm/api-config.asciidoc b/docs/en/observability/apm/api/apm-server/api-config.asciidoc similarity index 94% rename from docs/en/observability/apm/api-config.asciidoc rename to docs/en/observability/apm/api/apm-server/api-config.asciidoc index f98d464432..9077f13c7a 100644 --- a/docs/en/observability/apm/api-config.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-config.asciidoc @@ -1,12 +1,12 @@ [[apm-api-config]] -=== Elastic APM agent configuration API += Elastic APM agent configuration API APM Server exposes API endpoints that allow Elastic APM agents to query the APM Server for configuration changes. More information on this feature is available in <>. [float] [[apm-api-config-endpoint]] -=== Agent configuration endpoints +== Agent configuration endpoints [options="header"] |==== @@ -20,7 +20,7 @@ If an <> or <> is configured, requests to this en [float] [[apm-api-config-api-get]] -==== HTTP GET +=== HTTP GET `service.name` is a required query string parameter. @@ -31,7 +31,7 @@ http(s)://{hostname}:{port}/config/v1/agents?service.name=SERVICE_NAME [float] [[apm-api-config-api-post]] -==== HTTP POST +=== HTTP POST Encode parameters as a JSON object in the body. `service.name` is a required parameter. @@ -50,7 +50,7 @@ http(s)://{hostname}:{port}/config/v1/agents [float] [[apm-api-config-api-response]] -==== Responses +=== Responses * Successful - `200` * APM Server is configured to fetch agent configuration from {es} but the configuration is invalid - `403` @@ -58,7 +58,7 @@ http(s)://{hostname}:{port}/config/v1/agents [float] [[apm-api-config-api-example]] -==== Example request +=== Example request Example Agent configuration `GET` request including the service name "test-service": @@ -79,7 +79,7 @@ curl -X POST http://127.0.0.1:8200/config/v1/agents \ [float] [[apm-api-config-api-ex-response]] -==== Example response +=== Example response ["source","sh",subs="attributes"] --------------------------------------------------------------------------- diff --git a/docs/en/observability/apm/api-error.asciidoc b/docs/en/observability/apm/api/apm-server/api-error.asciidoc similarity index 93% rename from docs/en/observability/apm/api-error.asciidoc rename to docs/en/observability/apm/api/apm-server/api-error.asciidoc index 3e49ac2f2e..3044b6ead4 100644 --- a/docs/en/observability/apm/api-error.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-error.asciidoc @@ -1,11 +1,11 @@ [[apm-api-error]] -==== Errors += Errors An error or a logged error message captured by an agent occurring in a monitored service. [float] [[apm-api-error-schema]] -==== Error Schema +== Error Schema APM Server uses JSON Schema to validate requests. The specification for errors is defined on https://github.com/elastic/apm-server/blob/{minor-version}/docs/spec/v2/error.json[GitHub] and included below: diff --git a/docs/en/observability/apm/api-event-example.asciidoc b/docs/en/observability/apm/api/apm-server/api-event-example.asciidoc similarity index 89% rename from docs/en/observability/apm/api-event-example.asciidoc rename to docs/en/observability/apm/api/apm-server/api-event-example.asciidoc index 7dea62cf5a..43252fa7f9 100644 --- a/docs/en/observability/apm/api-event-example.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-event-example.asciidoc @@ -1,5 +1,5 @@ [[apm-api-event-example]] -==== Example request body += Example request body A request body example containing one event for all currently supported event types. diff --git a/docs/en/observability/apm/api-events.asciidoc b/docs/en/observability/apm/api/apm-server/api-events.asciidoc similarity index 92% rename from docs/en/observability/apm/api-events.asciidoc rename to docs/en/observability/apm/api/apm-server/api-events.asciidoc index da1b2f7f67..dd289b0840 100644 --- a/docs/en/observability/apm/api-events.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-events.asciidoc @@ -1,5 +1,5 @@ [[apm-api-events]] -=== Elastic APM events intake API += Elastic APM events intake API NOTE: Most users do not need to interact directly with the events intake API. @@ -24,7 +24,7 @@ See the <> to learn more about the different type [[apm-api-events-endpoint]] [float] -=== Endpoints +== Endpoints APM Server exposes the following endpoints for Elastic APM agent data intake: @@ -38,7 +38,7 @@ APM Server exposes the following endpoints for Elastic APM agent data intake: [[apm-api-events-example]] [float] -=== Request +== Request Send an `HTTP POST` request to the APM Server `intake/v2/events` endpoint: @@ -72,7 +72,7 @@ http(s)://{hostname}:{port}/intake/v3/rum/events [[apm-api-events-response]] [float] -=== Response +== Response On success, the server will respond with a 202 Accepted status code and no body. @@ -80,7 +80,7 @@ Keep in mind that events can succeed and fail independently of each other. Only [[apm-api-events-errors]] [float] -=== Errors +== Errors There are two types of errors that the APM Server may return to an agent: @@ -134,7 +134,7 @@ If you're developing an agent, these errors can be useful for debugging. [[apm-api-events-schema-definition]] [float] -=== Event API Schemas +== Event API Schemas The APM Server uses a collection of JSON Schemas for validating requests to the intake API: @@ -145,9 +145,9 @@ The APM Server uses a collection of JSON Schemas for validating requests to the * <> * <> -include::./api-metadata.asciidoc[] -include::./api-transaction.asciidoc[] -include::./api-span.asciidoc[] -include::./api-error.asciidoc[] -include::./api-metricset.asciidoc[] -include::./api-event-example.asciidoc[] +include::./api-metadata.asciidoc[leveloffset=+1] +include::./api-transaction.asciidoc[leveloffset=+1] +include::./api-span.asciidoc[leveloffset=+1] +include::./api-error.asciidoc[leveloffset=+1] +include::./api-metricset.asciidoc[leveloffset=+1] +include::./api-event-example.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/api-info.asciidoc b/docs/en/observability/apm/api/apm-server/api-info.asciidoc similarity index 94% rename from docs/en/observability/apm/api-info.asciidoc rename to docs/en/observability/apm/api/apm-server/api-info.asciidoc index b1f315ad92..01e2ef14ef 100644 --- a/docs/en/observability/apm/api-info.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-info.asciidoc @@ -1,12 +1,12 @@ [[apm-api-info]] -=== APM Server information API += APM Server information API The APM Server exposes an API endpoint to query general server information. This lightweight endpoint is useful as a server up/down health check. [float] [[apm-api-info-endpoint]] -=== Server Information endpoint +== Server Information endpoint This is the server information endpoint: @@ -28,7 +28,7 @@ the response payload will include some information about the APM server. [float] [[apm-api-info-example-get-without-credentials]] -==== Example: GET, without credentials +=== Example: GET, without credentials Example APM Server status request with GET, without credentials: @@ -55,7 +55,7 @@ curl --verbose -X GET http://127.0.0.1:8200 [float] [[apm-api-info-example-post-with-secret-token]] -==== Example: POST, with secret token +=== Example: POST, with secret token Example APM Server information request with POST, with a <>: diff --git a/docs/en/observability/apm/api-jaeger.asciidoc b/docs/en/observability/apm/api/apm-server/api-jaeger.asciidoc similarity index 92% rename from docs/en/observability/apm/api-jaeger.asciidoc rename to docs/en/observability/apm/api/apm-server/api-jaeger.asciidoc index 9750316a9b..89f249344c 100644 --- a/docs/en/observability/apm/api-jaeger.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-jaeger.asciidoc @@ -1,5 +1,5 @@ [[apm-api-jaeger]] -=== Jaeger event intake += Jaeger event intake Elastic APM natively supports Jaeger, an open-source, distributed tracing system. <>. @@ -11,4 +11,4 @@ Elastic APM natively supports Jaeger, an open-source, distributed tracing system |Name |Endpoint |Jaeger span intake |`/jaeger.api_v2.CollectorService/PostSpans` |Sampling endpoint |`/jaeger.api_v2.SamplingManager/GetSamplingStrategy` -|==== \ No newline at end of file +|==== diff --git a/docs/en/observability/apm/api-metadata.asciidoc b/docs/en/observability/apm/api/apm-server/api-metadata.asciidoc similarity index 97% rename from docs/en/observability/apm/api-metadata.asciidoc rename to docs/en/observability/apm/api/apm-server/api-metadata.asciidoc index 1d8a29e5c1..db3dad5e3f 100644 --- a/docs/en/observability/apm/api-metadata.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-metadata.asciidoc @@ -1,5 +1,5 @@ [[apm-api-metadata]] -==== Metadata += Metadata Every new connection to the APM Server starts with a `metadata` stanza. This provides general metadata concerning the other objects in the stream. @@ -14,7 +14,7 @@ TIP: Metadata is stored under `context` when viewing documents in {es}. [[apm-api-kubernetes-data]] [float] -==== Kubernetes data +== Kubernetes data APM agents automatically read Kubernetes data and send it to the APM Server. In most instances, agents are able to read this data from inside the container. @@ -55,7 +55,7 @@ The table below maps these environment variables to the APM metadata event field [[apm-api-metadata-schema]] [float] -==== Metadata Schema +== Metadata Schema APM Server uses JSON Schema to validate requests. The specification for metadata is defined on https://github.com/elastic/apm-server/blob/{minor-version}/docs/spec/v2/metadata.json[GitHub] and included below: diff --git a/docs/en/observability/apm/api-metricset.asciidoc b/docs/en/observability/apm/api/apm-server/api-metricset.asciidoc similarity index 92% rename from docs/en/observability/apm/api-metricset.asciidoc rename to docs/en/observability/apm/api/apm-server/api-metricset.asciidoc index 8e9b701f67..42eafa1f3b 100644 --- a/docs/en/observability/apm/api-metricset.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-metricset.asciidoc @@ -1,11 +1,11 @@ [[apm-api-metricset]] -==== Metrics += Metrics Metrics contain application metric data captured by an {apm-agent}. [[apm-api-metricset-schema]] [float] -==== Metric Schema +== Metric Schema APM Server uses JSON Schema to validate requests. The specification for metrics is defined on https://github.com/elastic/apm-server/blob/{minor-version}/docs/spec/v2/metricset.json[GitHub] and included below: diff --git a/docs/en/observability/apm/api-otlp.asciidoc b/docs/en/observability/apm/api/apm-server/api-otlp.asciidoc similarity index 93% rename from docs/en/observability/apm/api-otlp.asciidoc rename to docs/en/observability/apm/api/apm-server/api-otlp.asciidoc index 9e75dc6fc6..4215d9ac59 100644 --- a/docs/en/observability/apm/api-otlp.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-otlp.asciidoc @@ -1,5 +1,5 @@ [[apm-api-otlp]] -=== OpenTelemetry intake API += OpenTelemetry intake API APM Server supports receiving traces, metrics, and logs over the https://opentelemetry.io/docs/specs/otlp/[OpenTelemetry Protocol (OTLP)]. @@ -11,7 +11,7 @@ APM Server supports two OTLP communication protocols on the same port: * OTLP/gRPC [discrete] -=== OTLP/gRPC paths +== OTLP/gRPC paths [options="header"] |==== @@ -22,7 +22,7 @@ APM Server supports two OTLP communication protocols on the same port: |==== [discrete] -==== OTLP/HTTP paths +== OTLP/HTTP paths [options="header"] |==== diff --git a/docs/en/observability/apm/api-span.asciidoc b/docs/en/observability/apm/api/apm-server/api-span.asciidoc similarity index 93% rename from docs/en/observability/apm/api-span.asciidoc rename to docs/en/observability/apm/api/apm-server/api-span.asciidoc index 6805e1fb3d..c47df6814f 100644 --- a/docs/en/observability/apm/api-span.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-span.asciidoc @@ -1,11 +1,11 @@ [[apm-api-span]] -==== Spans += Spans Spans are events captured by an agent occurring in a monitored service. [[apm-api-span-schema]] [float] -==== Span Schema +== Span Schema APM Server uses JSON Schema to validate requests. The specification for spans is defined on https://github.com/elastic/apm-server/blob/{minor-version}/docs/spec/v2/span.json[GitHub] and included below: diff --git a/docs/en/observability/apm/api-transaction.asciidoc b/docs/en/observability/apm/api/apm-server/api-transaction.asciidoc similarity index 91% rename from docs/en/observability/apm/api-transaction.asciidoc rename to docs/en/observability/apm/api/apm-server/api-transaction.asciidoc index ff78ee785f..47ff4a8c16 100644 --- a/docs/en/observability/apm/api-transaction.asciidoc +++ b/docs/en/observability/apm/api/apm-server/api-transaction.asciidoc @@ -1,11 +1,11 @@ [[apm-api-transaction]] -==== Transactions += Transactions Transactions are events corresponding to an incoming request or similar task occurring in a monitored service. [[apm-api-transaction-schema]] [float] -==== Transaction Schema +== Transaction Schema APM Server uses JSON Schema to validate requests. The specification for transactions is defined on https://github.com/elastic/apm-server/blob/{minor-version}/docs/spec/v2/transaction.json[GitHub] and included below: diff --git a/docs/en/observability/apm/api.asciidoc b/docs/en/observability/apm/api/apm-server/index.asciidoc similarity index 86% rename from docs/en/observability/apm/api.asciidoc rename to docs/en/observability/apm/api/apm-server/index.asciidoc index 8d81091ca1..d5a71fce4c 100644 --- a/docs/en/observability/apm/api.asciidoc +++ b/docs/en/observability/apm/api/apm-server/index.asciidoc @@ -1,5 +1,5 @@ [[apm-api]] -== APM Server API += APM Server API The APM Server exposes endpoints for: @@ -9,8 +9,12 @@ The APM Server exposes endpoints for: * <> * <> +:leveloffset: +1 + include::./api-info.asciidoc[] include::./api-events.asciidoc[] include::./api-config.asciidoc[] include::./api-otlp.asciidoc[] include::./api-jaeger.asciidoc[] + +:!leveloffset: diff --git a/docs/en/observability/apm/api/index.asciidoc b/docs/en/observability/apm/api/index.asciidoc new file mode 100644 index 0000000000..f12d2ad666 --- /dev/null +++ b/docs/en/observability/apm/api/index.asciidoc @@ -0,0 +1,17 @@ +[[apm-apis]] += APM APIs + +There are two kinds of APIs related to Elastic APM: + +[cols="1,1"] +|=== +| <> +| {kib} APIs specific to working with the APM UI including updating configuration options, + uploading real user monitoring (RUM) source maps, adding annotations, and more. +| <> +| APIs for working with APM Server. + These are mainly intake APIs that accept data from APM agents and are used primarily by APM agent developers. +|=== + +include::{observability-docs-root}/docs/en/observability/apm/api/api-ui.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/api/apm-server/index.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/apm-data-security.asciidoc b/docs/en/observability/apm/apm-data-security.asciidoc deleted file mode 100644 index 4ff5d4facc..0000000000 --- a/docs/en/observability/apm/apm-data-security.asciidoc +++ /dev/null @@ -1,596 +0,0 @@ -[[apm-data-security]] -=== Data security - -When setting up Elastic APM, it's essential to review all captured data carefully to ensure -it doesn't contain sensitive information like passwords, credit card numbers, or health data. -In addition, you may wish to filter out other identifiable information, like IP addresses, user agent information, -or form field data. - -Depending on the type of data, we offer several different ways to filter, manipulate, -or obfuscate sensitive information during or before ingestion: - -* <> -* <> - -In addition to utilizing filters, you should regularly review the <> table to ensure -sensitive data is not being ingested. If it is, it's possible to remove or redact it. -See <> for more information. - -[float] -[[apm-built-in-data-filters]] -==== Built-in data filters - -// tag::data-filters[] -Built-in data filters allow you to filter or turn off ingestion of the following types of data: - -[options="header"] -|==== -|Data type |Common sensitive data -|<> |Passwords, credit card numbers, authorization, etc. -|<> |Passwords, credit card numbers, etc. -|<> |Client IP address and user agent. -|<> |URLs visited, click events, user browser errors, resources used, etc. -|<> |Sensitive user or business information -|==== -// end::data-filters[] - -[float] -[[apm-custom-data-filters]] -==== Custom filters - -// tag::custom-filters[] -Custom filters allow you to filter or redact other types of APM data on ingestion: - -|==== -|<> | Applied at ingestion time. -All agents and fields are supported. Data leaves the instrumented service. -There are no performance overhead implications on the instrumented service. - -|<> | Not supported by all agents. -Data is sanitized before leaving the instrumented service. -Potential overhead implications on the instrumented service -|==== -// end::custom-filters[] - -[float] -[[apm-sensitive-fields]] -==== Sensitive fields - -You should review the following fields regularly to ensure sensitive data is not being captured: - -[options="header"] -|==== -| Field | Description | Remedy -| `client.ip` | The client IP address, as forwarded by proxy. | <> -| `http.request.body.original` | The body of the monitored HTTP request. | <> -| `http.request.headers` | The canonical headers of the monitored HTTP request. | <> -| `http.request.socket.remote_address` | The address of the last proxy or end-user (if no proxy). | <> -| `http.response.headers` | The canonical headers of the monitored HTTP response. | <> -| `process.args` | Process arguments. | <> -| `span.db.statement` | Database statement. | <> -| `stacktrace.vars` | A flat mapping of local variables captured in the stack frame | <> -| `url.query` | The query string of the request, e.g. `?pass=hunter2`. | <> -| `user.*` | Logged-in user information. | <> -| `user_agent.*` | Device and version making the network request. | <> -|==== - -// **************************************************************** - -[[apm-filtering]] -==== Built-in data filters - -include::./apm-data-security.asciidoc[tag=data-filters] - -[discrete] -[[apm-filters-http-header]] -==== HTTP headers - -By default, APM agents capture HTTP request and response headers (including cookies). -Most Elastic APM agents provide the ability to sanitize HTTP header fields, -including cookies and `application/x-www-form-urlencoded` data (POST form fields). -Query string and captured request bodies, like `application/json` data, are not sanitized. - -The default list of sanitized fields attempts to target common field names for data relating to -passwords, credit card numbers, authorization, etc., but can be customized to fit your data. -This sensitive data never leaves the instrumented service. - -This setting supports <>, -which means the list of sanitized fields can be updated without needing to redeploy your services: - -* Go: {apm-go-ref-v}/configuration.html#config-sanitize-field-names[`ELASTIC_APM_SANITIZE_FIELD_NAMES`] -* Java: {apm-java-ref-v}/config-core.html#config-sanitize-field-names[`sanitize_field_names`] -* .NET: {apm-dotnet-ref-v}/config-core.html#config-sanitize-field-names[`sanitizeFieldNames`] -* Node.js: {apm-node-ref-v}/configuration.html#sanitize-field-names[`sanitizeFieldNames`] -// * PHP: {apm-php-ref-v}[``] -* Python: {apm-py-ref-v}/configuration.html#config-sanitize-field-names[`sanitize_field_names`] -* Ruby: {apm-ruby-ref-v}/configuration.html#config-sanitize-field-names[`sanitize_field_names`] - -Alternatively, you can completely disable the capturing of HTTP headers. -This setting also supports <>: - -* Go: {apm-go-ref-v}/configuration.html#config-capture-headers[`ELASTIC_APM_CAPTURE_HEADERS`] -* Java: {apm-java-ref-v}/config-core.html#config-capture-headers[`capture_headers`] -* .NET: {apm-dotnet-ref-v}/config-http.html#config-capture-headers[`CaptureHeaders`] -* Node.js: {apm-node-ref-v}/configuration.html#capture-headers[`captureHeaders`] -// * PHP: {apm-php-ref-v}[``] -* Python: {apm-py-ref-v}/configuration.html#config-capture-headers[`capture_headers`] -* Ruby: {apm-ruby-ref-v}/configuration.html#config-capture-headers[`capture_headers`] - -[discrete] -[[apm-filters-http-body]] -==== HTTP bodies - -By default, the body of HTTP requests is not recorded. -Request bodies often contain sensitive data like passwords or credit card numbers, -so use care when enabling this feature. - -This setting supports <>, -which means the list of sanitized fields can be updated without needing to redeploy your services: - -* Go: {apm-go-ref-v}/configuration.html#config-capture-body[`ELASTIC_APM_CAPTURE_BODY`] -* Java: {apm-java-ref-v}/config-core.html#config-capture-body[`capture_body`] -* .NET: {apm-dotnet-ref-v}/config-http.html#config-capture-body[`CaptureBody`] -* Node.js: {apm-node-ref-v}/configuration.html#capture-body[`captureBody`] -// * PHP: {apm-php-ref-v}[``] -* Python: {apm-py-ref-v}/configuration.html#config-capture-body[`capture_body`] -* Ruby: {apm-ruby-ref-v}/configuration.html#config-capture-body[`capture_body`] - -[discrete] -[[apm-filters-personal-data]] -==== Personal data - -By default, the APM Server captures some personal data associated with trace events: - -* `client.ip`: The client's IP address. Typically derived from the HTTP headers of incoming requests. -`client.ip` is also used in conjunction with the {ref}/geoip-processor.html[`geoip` processor] to assign -geographical information to trace events. To learn more about how `client.ip` is derived, -see <>. -* `user_agent`: User agent data, including the client operating system, device name, vendor, and version. - -The capturing of this data can be turned off by setting -**Capture personal data** to `false`. - -[discrete] -[[apm-filters-real-user-data]] -==== Real user monitoring data - -Protecting user data is important. -For that reason, individual RUM instrumentations can be disabled in the RUM agent with the -{apm-rum-ref-v}/configuration.html#disable-instrumentations[`disableInstrumentations`] configuration variable. -Disabled instrumentations produce no spans or transactions. - -[options="header"] -|==== -|Disable |Configuration value -|HTTP requests |`fetch` and `xmlhttprequest` -|Page load metrics including static resources |`page-load` -|JavaScript errors on the browser |`error` -|User click events including URLs visited, mouse clicks, and navigation events |`eventtarget` -|Single page application route changes |`history` -|==== - -[discrete] -[[apm-filters-database-statements]] -==== Database statements - -For SQL databases, APM agents do not capture the parameters of prepared statements. -Note that Elastic APM currently does not make an effort to strip parameters of regular statements. -Not using prepared statements makes your code vulnerable to SQL injection attacks, -so be sure to use prepared statements. - -For non-SQL data stores, such as {es} or MongoDB, -Elastic APM captures the full statement for queries. -For inserts or updates, the full document is not stored. -To filter or obfuscate data in non-SQL database statements, -or to remove the statement entirely, -you can set up an ingest node pipeline. - -[discrete] -[[apm-filters-agent-specific]] -==== Agent-specific options - -Certain agents offer additional filtering and obfuscating options: - -**Agent configuration options** - -* (Node.js) Remove errors raised by the server-side process: -disable with {apm-node-ref-v}/configuration.html#capture-exceptions[captureExceptions]. - -* (Java) Remove process arguments from transactions: -disabled by default with {apm-java-ref-v}/config-reporter.html#config-include-process-args[`include_process_args`]. - -// **************************************************************** - -[[apm-custom-filter]] -==== Custom filters - -include::./apm-data-security.asciidoc[tag=custom-filters] - -[discrete] -[[apm-filters-ingest-pipeline]] -==== Create an ingest pipeline filter - -Ingest node pipelines specify a series of processors that transform data in a specific way. -Transformation happens prior to indexing--inflicting no performance overhead on the monitored application. -Pipelines are a flexible and easy way to filter or obfuscate Elastic APM data. - -[discrete] -[[apm-filters-ingest-pipeline-tutorial]] -===== Tutorial: redact sensitive information - -Say you decide to <> -but quickly notice that sensitive information is being collected in the -`http.request.body.original` field: - -[source,json] ----- -{ - "email": "test@abc.com", - "password": "hunter2" -} ----- - -**Create a pipeline** - -To obfuscate the passwords stored in the request body, -you can use a series of {ref}/processors.html[ingest processors]. -To start, create a pipeline with a simple description and an empty array of processors: - -[source,json] ----- -{ - "pipeline": { - "description": "redact http.request.body.original.password", - "processors": [] <1> - } -} ----- -<1> The processors defined below will go in this array - -**Add a JSON processor** - -Add your first processor to the processors array. -Because the agent captures the request body as a string, use the -{ref}/json-processor.html[JSON processor] to convert the original field value into a structured JSON object. -Save this JSON object in a new field: - -[source,json] ----- -{ - "json": { - "field": "http.request.body.original", - "target_field": "http.request.body.original_json", - "ignore_failure": true - } -} ----- - -**Add a set processor** - -If `body.original_json` is not `null`, i.e., it exists, we'll redact the `password` with the {ref}/set-processor.html[set processor], -by setting the value of `body.original_json.password` to `"redacted"`: - -[source,json] ----- -{ - "set": { - "field": "http.request.body.original_json.password", - "value": "redacted", - "if": "ctx?.http?.request?.body?.original_json != null" - } -} ----- - -**Add a convert processor** - -Use the {ref}/convert-processor.html[convert processor] to convert the JSON value of `body.original_json` to a string and set it as the `body.original` value: - -[source,json] ----- -{ - "convert": { - "field": "http.request.body.original_json", - "target_field": "http.request.body.original", - "type": "string", - "if": "ctx?.http?.request?.body?.original_json != null", - "ignore_failure": true - } -} ----- - -**Add a remove processor** - -Finally, use the {ref}/remove-processor.html[remove processor] to remove the `body.original_json` field: - -[source,json] ----- -{ - "remove": { - "field": "http.request.body.original", - "if": "ctx?.http?.request?.body?.original_json != null", - "ignore_failure": true - } -} ----- - -**Register the pipeline** - -Now we'll put it all together. -Use the {ref}/put-pipeline-api.html[create or update pipeline API] to register the new pipeline in {es}. -Name the pipeline `apm_redacted_body_password`: - -[source,console] ----- -PUT _ingest/pipeline/apm_redacted_body_password -{ - "description": "redact http.request.body.original.password", - "processors": [ - { - "json": { - "field": "http.request.body.original", - "target_field": "http.request.body.original_json", - "ignore_failure": true - } - }, - { - "set": { - "field": "http.request.body.original_json.password", - "value": "redacted", - "if": "ctx?.http?.request?.body?.original_json != null" - } - }, - { - "convert": { - "field": "http.request.body.original_json", - "target_field": "http.request.body.original", - "type": "string", - "if": "ctx?.http?.request?.body?.original_json != null", - "ignore_failure": true - } - }, - { - "remove": { - "field": "http.request.body.original_json", - "if": "ctx?.http?.request?.body?.original_json != null", - "ignore_failure": true - } - } - ] -} ----- - -**Test the pipeline** - -Prior to enabling this new pipeline, you can test it with the {ref}/simulate-pipeline-api.html[simulate pipeline API]. -This API allows you to run multiple documents through a pipeline to ensure it is working correctly. - -The request below simulates running three different documents through the pipeline: - -[source,console] ----- -POST _ingest/pipeline/apm_redacted_body_password/_simulate -{ - "docs": [ - { - "_source": { <1> - "http": { - "request": { - "body": { - "original": """{"email": "test@abc.com", "password": "hunter2"}""" - } - } - } - } - }, - { - "_source": { <2> - "some-other-field": true - } - }, - { - "_source": { <3> - "http": { - "request": { - "body": { - "original": """["invalid json" """ - } - } - } - } - } - ] -} ----- -<1> This document features the same sensitive data from the original example above -<2> This document only contains an unrelated field -<3> This document contains invalid JSON - -The API response should be similar to this: - -[source,json] ----- -{ - "docs" : [ - { - "doc" : { - "_source" : { - "http" : { - "request" : { - "body" : { - "original" : { - "password" : "redacted", - "email" : "test@abc.com" - } - } - } - } - } - } - }, - { - "doc" : { - "_source" : { - "nobody" : true - } - } - }, - { - "doc" : { - "_source" : { - "http" : { - "request" : { - "body" : { - "original" : """["invalid json" """ - } - } - } - } - } - } - ] -} ----- - -As expected, only the first simulated document has a redacted password field. -All other documents are unaffected. - -**Create an `@custom` pipeline** - -The final step in this process is to call the newly created `apm_redacted_body_password` pipeline -from the `@custom` pipeline of the data stream you wish to edit. - -include::./ingest-pipelines.asciidoc[tag=ingest-pipeline-naming] - -Use the {ref}/put-pipeline-api.html[create or update pipeline API] to register the new pipeline in {es}. -Name the pipeline `traces-apm@custom`: - -[source,console] ----- -PUT _ingest/pipeline/traces-apm@custom -{ - "processors": [ - { - "pipeline": { - "name": "apm_redacted_body_password" <1> - } - } - ] -} ----- -<1> The name of the pipeline we previously created - -TIP: If you prefer using a GUI, you can instead open {kib} and navigate to -**Stack Management** -> **Ingest Pipelines** -> **Create pipeline**. -Use the same naming convention explained previously to ensure your new pipeline matches the correct APM data stream. - -That's it! Passwords will now be redacted from your APM HTTP body data. - -To learn more about ingest pipelines, see <>. - -[discrete] -[[apm-filters-in-agent]] -==== APM agent filters - -Some APM agents offer a way to manipulate or drop APM events _before_ they are sent to the APM Server. -Please see the relevant agent's documentation for more information and examples: - -// * Go: {apm-go-ref-v}/[] -// * Java: {apm-java-ref-v}/[] -* .NET: {apm-dotnet-ref-v}/public-api.html#filter-api[Filter API]. -* Node.js: {apm-node-ref-v}/agent-api.html#apm-add-filter[`addFilter()`]. -// * PHP: {apm-php-ref-v}[] -* Python: {apm-py-ref-v}/sanitizing-data.html[custom processors]. -* Ruby: {apm-ruby-ref-v}/api.html#api-agent-add-filter[`add_filter()`]. - -// **************************************************************** - -[[apm-data-security-delete]] -==== Delete sensitive data - -If you accidentally ingest sensitive data, follow these steps to remove or redact the offending data: - -. Stop collecting the sensitive data. -Use the *remedy* column of the <> table to determine how to stop collecting -the offending data. - -. Delete or redact the ingested data. With data collection fixed, you can now delete or redact the offending data: -+ -* <> -* <> - -[float] -[[apm-redact-field-data]] -===== Redact specific fields - -To redact sensitive data in a specific field, use the {ref}/docs-update-by-query.html[update by query API]. - -For example, the following query removes the `client.ip` address -from APM documents in the `logs-apm.error-default` data stream: - -[source, console] ----- -POST /logs-apm.error-default/_update_by_query -{ - "query": { - "exists": { - "field": "client.ip" - } - } - "script": { - "source": "ctx._source.client.ip = params.redacted", - "params": { - "redacted": "[redacted]" - } - } -} ----- - -Or, perhaps you only want to redact IP addresses from European users: - -[source, console] ----- -POST /logs-apm.error-default/_update_by_query -{ - "query": { - "term": { - "client.geo.continent_name": { - "value": "Europe" - } - } - }, - "script": { - "source": "ctx._source.client.ip = params.redacted", - "params": { - "redacted": "[redacted]" - } - } -} ----- - -See {ref}/docs-update-by-query.html[update by query API] for more information and examples. - -[float] -[[apm-delete-doc-data]] -===== Delete {es} documents - -WARNING: This will permanently delete your data. -You should test your queries with the {ref}/search-search.html[search API] prior to deleting data. - -To delete an {es} document, -you can use the {ref}/docs-delete-by-query.html[delete by query API]. - -For example, to delete all documents in the `apm-traces-*` data stream with a `user.email` value, run the following query: - -[source, console] ----- -POST /apm-traces-*/_delete_by_query -{ - "query": { - "exists": { - "field": "user.email" - } - } -} ----- - -See {ref}/docs-delete-by-query.html[delete by query API] for more information and examples. diff --git a/docs/en/observability/apm-ui/agent-configuration.asciidoc b/docs/en/observability/apm/collect-application-data/agents/agent-configuration.asciidoc similarity index 93% rename from docs/en/observability/apm-ui/agent-configuration.asciidoc rename to docs/en/observability/apm/collect-application-data/agents/agent-configuration.asciidoc index 13d929dd53..7441b33b76 100644 --- a/docs/en/observability/apm-ui/agent-configuration.asciidoc +++ b/docs/en/observability/apm/collect-application-data/agents/agent-configuration.asciidoc @@ -1,8 +1,8 @@ [[apm-agent-configuration]] -=== APM Agent central configuration += APM agent central configuration ++++ -Configure APM agents with central config +Centrally configure APM agents in Kibana ++++ APM Agent configuration allows you to fine-tune your APM agent configuration from within the APM UI. @@ -15,7 +15,7 @@ The APM UI will let you know when your APM agents have applied your configuratio image::./images/apm-agent-configuration.png[APM Agent configuration in Kibana] [float] -==== Precedence +== Precedence Configurations set from the APM UI take precedence over configurations set locally in each APM agent. However, if APM Server is slow to respond, is offline, reports an error, etc., @@ -23,7 +23,7 @@ APM agents will use local defaults until they're able to update the configuratio For this reason, it is still essential to set custom default configurations locally in each of your APM agents. [float] -==== Supported configurations +== Supported configurations Each APM agent has a list of supported configurations. After selecting a Service name and environment in the APM UI, @@ -45,7 +45,7 @@ Ruby agent:: {apm-ruby-ref}/configuration.html[Configuration reference] Real User Monitoring (RUM) agent:: {apm-rum-ref}/configuration.html[Configuration reference] [float] -==== APM Server configuration +== APM Server configuration For most users, APM agent configuration should work out-of-the-box. If you run into trouble, it may be because you're not using the {es} output, diff --git a/docs/en/observability/apm/collect-application-data/agents/index.asciidoc b/docs/en/observability/apm/collect-application-data/agents/index.asciidoc new file mode 100644 index 0000000000..d52dab9eee --- /dev/null +++ b/docs/en/observability/apm/collect-application-data/agents/index.asciidoc @@ -0,0 +1,41 @@ +[[apm-agents]] += APM agents + +Elastic APM agents automatically measure application performance and track errors. +They offer built-in support for popular frameworks and technologies, and provide easy-to-use +APIs that allow you to instrument any application. + +[discrete] +== Available APM agents + +Elastic APM agents are built and maintained by Elastic. While they are similar, different +programming languages have different nuances and requirements. Refer to each APM agent's +documentation to learn how to install the agent, configure it, and more: + +* {apm-android-ref}/intro.html[APM Android agent] +* {apm-go-ref}/introduction.html[APM Go agent] +* {apm-ios-ref}/intro.html[APM iOS agent] +* {apm-java-ref}/intro.html[APM Java agent] +* {apm-dotnet-ref}/intro.html[APM .NET agent] +* {apm-node-ref}/intro.html[APM Node.js agent] +* {apm-php-ref}/intro.html[APM PHP agent] +* {apm-py-ref}/getting-started.html[APM Python agent] +* {apm-ruby-ref}/introduction.html[APM Ruby agent] +* {apm-rum-ref}/intro.html[APM Real User Monitoring JavaScript agent] + +[discrete] +== More APM agent resources + +Though you should refer to each APM agent's documentation for information on using the agent, +there are some tasks you can complete in the APM UI: + +* <> +* <> + +//// +Subsections +//// + +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/agents/agent-configuration.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/agents/rum.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/agents/source-map-how-to.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/apm-rum.asciidoc b/docs/en/observability/apm/collect-application-data/agents/rum.asciidoc similarity index 96% rename from docs/en/observability/apm/apm-rum.asciidoc rename to docs/en/observability/apm/collect-application-data/agents/rum.asciidoc index 7ca2368f49..b4750cb14d 100644 --- a/docs/en/observability/apm/apm-rum.asciidoc +++ b/docs/en/observability/apm/collect-application-data/agents/rum.asciidoc @@ -1,5 +1,5 @@ [[apm-rum]] -=== Real User Monitoring (RUM) += Real User Monitoring (RUM) Real User Monitoring captures user interaction with clients such as web browsers. The {apm-rum-ref-v}[JavaScript Agent] is Elastic’s RUM Agent. // To use it you need to {apm-server-ref-v}/configuration-rum.html[enable RUM support] in the APM Server. diff --git a/docs/en/observability/apm/source-map-how-to.asciidoc b/docs/en/observability/apm/collect-application-data/agents/source-map-how-to.asciidoc similarity index 96% rename from docs/en/observability/apm/source-map-how-to.asciidoc rename to docs/en/observability/apm/collect-application-data/agents/source-map-how-to.asciidoc index 12acf196f9..8c76192810 100644 --- a/docs/en/observability/apm/source-map-how-to.asciidoc +++ b/docs/en/observability/apm/collect-application-data/agents/source-map-how-to.asciidoc @@ -1,5 +1,5 @@ [[apm-source-map-how-to]] -=== Create and upload source maps (RUM) += Create and upload source maps (RUM) Minifying JavaScript bundles in production is a common practice; it can greatly improve the load time and network latency of your applications. @@ -32,7 +32,7 @@ Follow the steps below to enable source mapping your error stack traces in the A [float] [[apm-source-map-rum-initialize]] -=== Initialize the RUM Agent +== Initialize the RUM Agent Set the service name and version of your application when initializing the RUM Agent. To make uploading subsequent source maps easier, the `serviceVersion` you choose might be the @@ -62,7 +62,7 @@ The APM integration uses the service name and version to match the correct sourc [float] [[apm-source-map-rum-generate]] -=== Generate a source map +== Generate a source map To be compatible with Elastic APM, source maps must follow the https://sourcemaps.info/spec.html[source map revision 3 proposal spec]. @@ -95,7 +95,7 @@ module.exports = { [float] [[apm-source-map-rum-upload]] -=== Upload the source map +== Upload the source map TIP: When uploading a source map, ensure that RUM support is enabled in the APM integration. @@ -114,7 +114,7 @@ If you have multiple source maps, you'll need to upload each individually. [float] [[apm-source-map-curl]] -==== Upload via curl +=== Upload via curl Here’s an example curl request that uploads the source map file created in the previous step. This request uses an API key for authentication. @@ -136,7 +136,7 @@ curl -X POST "http://localhost:5601/api/apm/sourcemaps" \ [float] [[apm-source-map-custom-app]] -==== Upload via a custom app +=== Upload via a custom app To ensure uploading source maps become a part of your deployment process, consider automating the process with a custom application. @@ -169,7 +169,7 @@ request.post({url: 'http://localhost:5601/api/apm/sourcemaps',formData: formData [float] [[apm-source-map-next]] -=== What happens next +== What happens next Source maps are stored in {es}. When you upload a source map, a new {es} document is created containing the contents of the source map. diff --git a/docs/en/observability/apm/aws-lambda-extension.asciidoc b/docs/en/observability/apm/collect-application-data/aws-lambda-extension.asciidoc similarity index 93% rename from docs/en/observability/apm/aws-lambda-extension.asciidoc rename to docs/en/observability/apm/collect-application-data/aws-lambda-extension.asciidoc index b2efe4673c..f4280f8000 100644 --- a/docs/en/observability/apm/aws-lambda-extension.asciidoc +++ b/docs/en/observability/apm/collect-application-data/aws-lambda-extension.asciidoc @@ -1,6 +1,10 @@ [[apm-monitoring-aws-lambda]] = Monitoring AWS Lambda Functions +++++ +AWS Lambda Functions +++++ + Elastic APM lets you monitor your AWS Lambda functions. The natural integration of <> into your AWS Lambda functions provides insights into the function's execution and runtime behavior as well as its relationships and dependencies to other services. diff --git a/docs/en/observability/apm/collect-application-data/index.asciidoc b/docs/en/observability/apm/collect-application-data/index.asciidoc new file mode 100644 index 0000000000..1d8f3b19d1 --- /dev/null +++ b/docs/en/observability/apm/collect-application-data/index.asciidoc @@ -0,0 +1,86 @@ +[[apm-collect-application-data]] += Collect application data + +[discrete] +== Language-specific options + +Use Elastic APM agents or an OpenTelemetry language SDK to instrument a service in the language its written in: + +* <>: Elastic APM agents are instrumentation libraries written in the same language as your service. +* <>: OpenTelemetry is an open source set of APIs, SDKs, tooling, and integrations that enable the capture and management of telemetry data from your services and applications. +** This option includes Elastic Distributions of OpenTelemetry, which are customized versions of https://opentelemetry.io/docs/languages/[OpenTelemetry language SDKs] that are optimized to work with an Elastic backend. + +*Not sure which method is right for you?* Compare the available options below. + +[discrete] +=== Capabilities + +//// +TO DO: +Is this table even helpful? +Is it missing anything that would make it more helpful? +//// +|=== +| | Elastic APM agent | Elastic Distribution of OpenTelemetry + +| *Support level* +| Fully supported +| Mixed support + +_Refer to the_ <> + +| *Data protocol* +| Elastic protocol +| https://opentelemetry.io/docs/specs/otel/protocol/[OpenTelemetry protocol (OTLP)] + +| *Central configuration* +| Supported + +_Refer to_ <> +| Not supported +|=== + +[discrete] +[[apm-collect-data-availability]] +=== Availability + +:not-available: image:images/icons/cross.svg[Not available] + +//// +TO DO: +Are we ok with maintaining this table? +Are we ok with the gaps it exposes? +//// +[cols="<,^,^"] +|=== +| *Language* | *Elastic APM agent* | *Elastic Distributions of OpenTelemetry (EDOT)* +| *Android* | Android agent | {not-available} +| *Go* | Go agent | {not-available} +| *iOS* | iOS agent | {not-available} +| *Java* | Java agent | EDOT Java +| *.NET* | .NET agent | preview:[] EDOT .NET +| *Node.js* | Node.js agent | preview:[] EDOT Node.js +| *PHP* | PHP agent | preview:[] EDOT PHP +| *Python* | Python agent | preview:[] EDOT Python +| *Ruby* | Ruby agent | {not-available} +|=== + +[discrete] +== Service-specific options + +Elastic also offers several tools to help you collect data from specific services: + +* *Kubernetes*: The Elastic APM attacher for Kubernetes simplifies the instrumentation and configuration of your application pods. + Read more in the {apm-attacher-ref}/apm-attacher.html[APM attacher for Kubernetes docs]. +* *AWS Lambda Functions*: Helps you monitor your AWS Lambda functions. + Read more in the {apm-lambda-ref}/aws-lambda-arch.html[APM Architecture for AWS Lambda docs]. +* deprecated:[8.15.0] *Jaeger*: Helps you to switch an existing Jaeger setup from the default + Jaeger backend to the {stack}. Read more in <>. + +//// +Subsections +//// + +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/agents/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/open-telemetry/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/k8s-attacher.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/aws-lambda-extension.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/collect-application-data/jaeger-integration.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/jaeger-integration.asciidoc b/docs/en/observability/apm/collect-application-data/jaeger-integration.asciidoc similarity index 94% rename from docs/en/observability/apm/jaeger-integration.asciidoc rename to docs/en/observability/apm/collect-application-data/jaeger-integration.asciidoc index d703756c69..47c1cb42d6 100644 --- a/docs/en/observability/apm/jaeger-integration.asciidoc +++ b/docs/en/observability/apm/collect-application-data/jaeger-integration.asciidoc @@ -1,8 +1,8 @@ [[apm-jaeger-integration]] -=== Jaeger integration += Integrate with Jaeger ++++ -Integrate with Jaeger +Jaeger (deprecated) ++++ WARNING: Support for Jaeger is deprecated and will be removed in a future version of Elastic APM. https://www.jaegertracing.io/docs/1.35/client-libraries/[Jaeger clients are deprecated] in favor of OpenTelemetry SDKs, and OpenTelemetry has removed all Jaeger exporters from their https://github.com/open-telemetry/opentelemetry-specification/pull/2858[specification]. @@ -14,7 +14,7 @@ Best of all, no instrumentation changes are needed in your application code. [float] [[apm-jaeger-architecture]] -=== Supported architecture +== Supported architecture Jaeger architecture supports different data formats and transport protocols that define how data can be sent to a collector. Elastic APM, as a Jaeger collector, @@ -33,7 +33,7 @@ for more information on Jaeger architecture. [float] [[apm-get-started-jaeger]] -=== Get started +== Get started Connect your preexisting Jaeger setup to Elastic APM in three steps: @@ -45,7 +45,7 @@ IMPORTANT: There are <> to this integration. [float] [[apm-configure-agent-client-jaeger]] -==== Configure Jaeger agents +=== Configure Jaeger agents The APM integration serves Jaeger gRPC over the same host and port as the Elastic {apm-agent} protocol. @@ -53,7 +53,7 @@ include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/jaeger- [float] [[apm-configure-sampling-jaeger]] -==== Configure Sampling +=== Configure Sampling The APM integration supports probabilistic sampling, which can be used to reduce the amount of data that your agents collect and send. Probabilistic sampling makes a random sampling decision based on the configured sampling value. @@ -66,7 +66,7 @@ There are two different ways to configure the sampling rate of your Jaeger agent [float] [[apm-configure-sampling-central-jaeger]] -===== {apm-agent} central configuration (default) +==== {apm-agent} central configuration (default) Central sampling, with {apm-agent} central configuration, allows Jaeger clients to poll APM Server for the sampling rate. @@ -75,7 +75,7 @@ See <> to learn more. [float] [[apm-configure-sampling-local-jaeger]] -===== Local sampling in each Jaeger client +==== Local sampling in each Jaeger client If you don't have access to the APM UI, you'll need to change the Jaeger client's `sampler.type` and `sampler.param`. @@ -85,13 +85,13 @@ for more information. [float] [[apm-configure-start-jaeger]] -==== Start sending data +=== Start sending data That's it! Data sent from Jaeger clients to the APM Server can now be viewed in the APM UI. [float] [[apm-caveats-jaeger]] -=== Caveats +== Caveats There are some limitations and differences between Elastic APM and Jaeger that you should be aware of. diff --git a/docs/en/observability/apm/apm-k8s-attacher.asciidoc b/docs/en/observability/apm/collect-application-data/k8s-attacher.asciidoc similarity index 63% rename from docs/en/observability/apm/apm-k8s-attacher.asciidoc rename to docs/en/observability/apm/collect-application-data/k8s-attacher.asciidoc index 9267d54132..1e1b070a4d 100644 --- a/docs/en/observability/apm/apm-k8s-attacher.asciidoc +++ b/docs/en/observability/apm/collect-application-data/k8s-attacher.asciidoc @@ -1,7 +1,11 @@ [[apm-k8s-attacher]] = APM K8S Attacher -The {apm-attacher-ref}/apm-attacher.html[APM attacher] for Kubernetes simplifies the instrumentation and configuration of your application pods. +++++ +Kubernetes +++++ + +The {apm-attacher-ref}/apm-attacher.html[APM attacher for Kubernetes] simplifies the instrumentation and configuration of your application pods. The attacher includes a webhook receiver that modifies pods so they are automatically instrumented by an Elastic APM agent. Ready to get started? See {apm-attacher-ref}/apm-get-started-webhook.html[Instrument and configure pods] to get started. diff --git a/docs/en/observability/apm/open-telemetry.asciidoc b/docs/en/observability/apm/collect-application-data/open-telemetry/index.asciidoc similarity index 96% rename from docs/en/observability/apm/open-telemetry.asciidoc rename to docs/en/observability/apm/collect-application-data/open-telemetry/index.asciidoc index 0e387498c3..f1cb772a06 100644 --- a/docs/en/observability/apm/open-telemetry.asciidoc +++ b/docs/en/observability/apm/collect-application-data/open-telemetry/index.asciidoc @@ -1,8 +1,8 @@ [[apm-open-telemetry]] -== Use OpenTelemetry with APM += Use OpenTelemetry with APM ++++ -Use OpenTelemetry +OpenTelemetry ++++ [NOTE] @@ -139,16 +139,14 @@ To get started, follow the official AWS Distro for OpenTelemetry Lambda document https://aws-otel.github.io/docs/getting-started/lambda[*Get started with the AWS Distro for OpenTelemetry Lambda*^] image:images/icons/popout.svg[] -// TODO: I'm not sure what this diagram should look like... -// image::images/apm-otel-lambda.png[] +//// +Subsections +//// -include::./otel-direct.asciidoc[] - -include::./otel-metrics.asciidoc[] - -include::./otel-limitations.asciidoc[] - -include::./otel-attrs.asciidoc[] +include::./otel-direct.asciidoc[leveloffset=+1] +include::./otel-metrics.asciidoc[leveloffset=+1] +include::./otel-limitations.asciidoc[leveloffset=+1] +include::./otel-attrs.asciidoc[leveloffset=+1] // **** // The text below is used in the Quick start guide diff --git a/docs/en/observability/apm/otel-attrs.asciidoc b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-attrs.asciidoc similarity index 98% rename from docs/en/observability/apm/otel-attrs.asciidoc rename to docs/en/observability/apm/collect-application-data/open-telemetry/otel-attrs.asciidoc index 7a4bac9654..a54ebb0a3e 100644 --- a/docs/en/observability/apm/otel-attrs.asciidoc +++ b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-attrs.asciidoc @@ -1,5 +1,5 @@ [[apm-open-telemetry-resource-attributes]] -=== Resource attributes += Resource attributes A resource attribute is a key/value pair containing information about the entity producing telemetry. Resource attributes are mapped to Elastic Common Schema (ECS) fields like `service.*`, `cloud.*`, `process.*`, etc. diff --git a/docs/en/observability/apm/otel-direct.asciidoc b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-direct.asciidoc similarity index 97% rename from docs/en/observability/apm/otel-direct.asciidoc rename to docs/en/observability/apm/collect-application-data/open-telemetry/otel-direct.asciidoc index df1a47d6f2..9761a73dbf 100644 --- a/docs/en/observability/apm/otel-direct.asciidoc +++ b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-direct.asciidoc @@ -1,5 +1,5 @@ [[apm-open-telemetry-direct]] -=== Upstream OpenTelemetry Collectors and language SDKs += Upstream OpenTelemetry Collectors and language SDKs [NOTE] ==== @@ -17,7 +17,7 @@ be sent directly to the {stack}. [discrete] [[apm-connect-open-telemetry-collector]] -==== Send data from an upstream OpenTelemetry Collector +== Send data from an upstream OpenTelemetry Collector Connect your OpenTelemetry Collector instances to Elastic {observability} using the OTLP exporter: @@ -83,7 +83,7 @@ In addition, your data will not be viewable in the {kib} {observability} apps if [discrete] [[apm-instrument-apps-otel]] -==== Send data from an upstream OpenTelemetry SDK +== Send data from an upstream OpenTelemetry SDK [NOTE] ==== @@ -139,7 +139,7 @@ and <> in {kib}. [discrete] [[apm-open-telemetry-proxy-apm]] -==== Proxy requests to APM Server +== Proxy requests to APM Server APM Server supports both the https://opentelemetry.io/docs/specs/otlp/#otlpgrpc[OTLP/gRPC] and https://opentelemetry.io/docs/specs/otlp/#otlphttp[OTLP/HTTP] protocol on the same port as Elastic APM agent requests. For ease of setup, we recommend using OTLP/HTTP when proxying or load balancing requests to the APM Server. @@ -155,7 +155,7 @@ https://github.com/elastic/apm-server/blob/main/dev_docs/otel.md#muxing-grpc-and [discrete] [[apm-open-telemetry-direct-next]] -==== Next steps +== Next steps * <> * Learn about the <> diff --git a/docs/en/observability/apm/otel-limitations.asciidoc b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-limitations.asciidoc similarity index 95% rename from docs/en/observability/apm/otel-limitations.asciidoc rename to docs/en/observability/apm/collect-application-data/open-telemetry/otel-limitations.asciidoc index a438c4f72c..1817d62dff 100644 --- a/docs/en/observability/apm/otel-limitations.asciidoc +++ b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-limitations.asciidoc @@ -1,9 +1,9 @@ [[apm-open-telemetry-known-limitations]] -=== Limitations += Limitations [float] [[apm-open-telemetry-traces-limitations]] -==== OpenTelemetry traces +== OpenTelemetry traces * Traces of applications using `messaging` semantics might be wrongly displayed as `transactions` in the APM UI, while they should be considered `spans` (see issue https://github.com/elastic/apm-server/issues/7001[#7001]). * Inability to see Stack traces in spans. @@ -11,21 +11,21 @@ [float] [[apm-open-telemetry-logs-intake]] -==== OpenTelemetry logs +== OpenTelemetry logs * preview:[] The OpenTelemetry logs intake via APM Server is in technical preview. * The application logs data stream (`app_logs`) has dynamic mapping disabled. This means the automatic detection and mapping of new fields is disabled (see issue https://github.com/elastic/apm-server/issues/9093[#9093]). [float] [[apm-open-telemetry-otlp-limitations]] -==== OpenTelemetry Line Protocol (OTLP) +== OpenTelemetry Line Protocol (OTLP) APM Server supports both the https://opentelemetry.io/docs/specs/otlp/#otlpgrpc[OTLP/gRPC] and https://opentelemetry.io/docs/specs/otlp/#otlphttp[OTLP/HTTP] protocol with ProtoBuf payload. APM Server does not yet support JSON Encoding for OTLP/HTTP. [float] [[apm-open-telemetry-collector-exporter]] -==== OpenTelemetry Collector exporter for Elastic +== OpenTelemetry Collector exporter for Elastic The https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/v0.57.2/exporter/elasticexporter[OpenTelemetry Collector exporter for Elastic] has been deprecated and replaced by the native support of the OpenTelemetry Line Protocol in Elastic Observability (OTLP). @@ -36,7 +36,7 @@ The https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/ [float] [[apm-open-telemetry-tbs]] -==== OpenTelemetry's tail-based sampling +== OpenTelemetry's tail-based sampling Tail-based sampling allows to make sampling decisions after all spans of a trace have been completed. This allows for more powerful and informed sampling rules. diff --git a/docs/en/observability/apm/otel-metrics.asciidoc b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-metrics.asciidoc similarity index 96% rename from docs/en/observability/apm/otel-metrics.asciidoc rename to docs/en/observability/apm/collect-application-data/open-telemetry/otel-metrics.asciidoc index 4ffcf30256..bff834fd90 100644 --- a/docs/en/observability/apm/otel-metrics.asciidoc +++ b/docs/en/observability/apm/collect-application-data/open-telemetry/otel-metrics.asciidoc @@ -1,5 +1,5 @@ [[apm-open-telemetry-collect-metrics]] -=== Collect metrics += Collect metrics IMPORTANT: When collecting metrics, please note that the https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/DoubleValueRecorder.html[`DoubleValueRecorder`] and https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/latest/io/opentelemetry/api/metrics/LongValueObserver.html[`LongValueRecorder`] metrics are not yet supported. @@ -26,7 +26,7 @@ for more information. [float] [[apm-open-telemetry-verify-metrics]] -==== Verify OpenTelemetry metrics data +== Verify OpenTelemetry metrics data Use *Discover* to validate that metrics are successfully reported to {kib}. @@ -44,7 +44,7 @@ only OpenTelemetry metrics documents. [float] [[apm-open-telemetry-visualize]] -==== Visualize in {kib} +== Visualize in {kib} Use *Lens* to create visualizations for OpenTelemetry metrics. Lens enables you to build visualizations by dragging and dropping data fields. It makes smart visualization suggestions for your data, allowing you to switch between visualization types. diff --git a/docs/en/observability/apm/common-problems.asciidoc b/docs/en/observability/apm/common-problems.asciidoc deleted file mode 100644 index 3df7179c2b..0000000000 --- a/docs/en/observability/apm/common-problems.asciidoc +++ /dev/null @@ -1,200 +0,0 @@ -[[apm-common-problems]] -=== Common problems - -This section describes common problems you might encounter when using a Fleet-managed APM Server. - -* <> -* <> -* <> -* <> -* <> -* <> - -[float] -[[apm-no-data-indexed]] -=== No data is indexed - -If no data shows up in {es}, first make sure that your APM components are properly connected. - -include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/no-data-indexed-widget.asciidoc[] - -[[apm-data-indexed-no-apm]] -[float] -=== Data is indexed but doesn't appear in the APM UI - -The APM UI relies on index mappings to query and display data. -If your APM data isn't showing up in the APM UI, but is elsewhere in {kib}, like the Discover app, -you may have a missing index mapping. - -You can determine if a field was mapped correctly with the `_mapping` API. -For example, run the following command in the {kib} {kibana-ref}/console-kibana.html[console]. -This will display the field data type of the `service.name` field. - -[source,curl] ----- -GET *apm*/_mapping/field/service.name ----- - -If the `mapping.name.type` is `"text"`, your APM indices were not set up correctly. - -[source,yml] ----- -".ds-metrics-apm.transaction.1m-default-2023.04.12-000038": { - "mappings": { - "service.name": { - "full_name": "service.name", - "mapping": { - "name": { - "type": "text" <1> - } - } - } - } -} ----- -<1> The `service.name` `mapping.name.type` would be `"keyword"` if this field had been set up correctly. - -To fix this problem, install the APM integration by following these steps: - --- -include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm-server.asciidoc[tag=install-apm-integration] --- - -This will reinstall the APM index templates and trigger a data stream index rollover. - -You can verify the correct index templates were installed by running the following command in the {kib} console: - -[source,curl] ----- -GET /_index_template/traces-apm ----- - -[float] -[[apm-common-ssl-problems]] -=== Common SSL-related problems - -* <> -* <> -* <> -* <> -* <> - - -[float] -[[apm-ssl-client-fails]] -==== SSL client fails to connect - -The target host might be unreachable or the certificate may not be valid. -To fix this problem: - -. Make sure that the APM Server process on the target host is running and you can connect to it. -Try to ping the target host to verify that you can reach it from the host running APM Server. -Then use either `nc` or `telnet` to make sure that the port is available. For example: -+ -[source,shell] ----- -ping -telnet 5044 ----- - -. Verify that the certificate is valid and that the hostname and IP match. -. Use OpenSSL to test connectivity to the target server and diagnose problems. -See the https://www.openssl.org/docs/manmaster/man1/openssl-s_client.html[OpenSSL documentation] for more info. - -[float] -[[apm-cannot-validate-certificate]] -==== x509: cannot validate certificate for because it doesn't contain any IP SANs - -This happens because your certificate is only valid for the hostname present in the Subject field. -To resolve this problem, try one of these solutions: - -* Create a DNS entry for the hostname, mapping it to the server's IP. -* Create an entry in `/etc/hosts` for the hostname. Or, on Windows, add an entry to -`C:\Windows\System32\drivers\etc\hosts`. -* Re-create the server certificate and add a Subject Alternative Name (SAN) for the IP address of the server. This makes the -server's certificate valid for both the hostname and the IP address. - -[float] -[[apm-getsockopt-no-route-to-host]] -==== getsockopt: no route to host - -This is not an SSL problem. It's a networking problem. Make sure the two hosts can communicate. - -[float] -[[apm-getsockopt-connection-refused]] -==== getsockopt: connection refused - -This is not an SSL problem. Make sure that {ls} is running and that there is no firewall blocking the traffic. - -[float] -[[apm-target-machine-refused-connection]] -==== No connection could be made because the target machine actively refused it - -A firewall is refusing the connection. Check if a firewall is blocking the traffic on the client, the network, or the -destination host. - -[[apm-io-timeout]] -[float] -=== I/O Timeout - -I/O Timeouts can occur when your timeout settings across the stack are not configured correctly, -especially when using a load balancer. - -You may see an error like the one below in the {apm-agent} logs, and/or a similar error on the APM Server side: - -[source,logs] ----- -[ElasticAPM] APM Server responded with an error: -"read tcp 123.34.22.313:8200->123.34.22.40:41602: i/o timeout" ----- - -To fix this, ensure timeouts are incrementing from the {apm-agent}, -through your load balancer, to the APM Server. - -By default, the agent timeouts are set at 10 seconds, and the server timeout is set at 3600 seconds. -Your load balancer should be set somewhere between these numbers. - -For example: - -[source,txt] ----- -APM agent --> Load Balancer --> APM Server - 10s 15s 3600s ----- - -The APM Server timeout can be configured by updating the -<>. - -[[apm-field-limit-exceeded]] -[float] -=== Field limit exceeded - -When adding too many distinct tag keys on a transaction or span, -you risk creating a link:{ref}/mapping.html#mapping-limit-settings[mapping explosion]. - -For example, you should avoid that user-specified data, -like URL parameters, is used as a tag key. -Likewise, using the current timestamp or a user ID as a tag key is not a good idea. -However, tag *values* with a high cardinality are not a problem. -Just try to keep the number of distinct tag keys at a minimum. - -The symptom of a mapping explosion is that transactions and spans are not indexed anymore after a certain time. Usually, on the next day, -the spans and transactions will be indexed again because a new index is created each day. -But as soon as the field limit is reached, indexing stops again. - -In the agent logs, you won't see a sign of failures as the APM server asynchronously sends the data it received from the agents to {es}. However, the APM server and {es} log a warning like this: - -[source,logs] ----- -{\"type\":\"illegal_argument_exception\",\"reason\":\"Limit of total fields [1000] in [INDEX_NAME] has been exceeded\"} ----- - -[[apm-tail-based-sampling-memory-disk-io]] -[float] -=== Tail-based sampling causing high system memory usage and high disk IO - -Tail-based sampling requires minimal memory to run, and there should not be a noticeable increase in RSS memory usage. -However, since tail-based sampling writes data to disk, -it is possible to see a significant increase in OS page cache memory usage due to disk IO. -If you see a drop in throughput and excessive disk activity after enabling tail-based sampling, -please ensure that there is enough memory headroom in the system for OS page cache to perform disk IO efficiently. diff --git a/docs/en/observability/apm/command-reference.asciidoc b/docs/en/observability/apm/configure/advanced-setup/command-reference.asciidoc similarity index 98% rename from docs/en/observability/apm/command-reference.asciidoc rename to docs/en/observability/apm/configure/advanced-setup/command-reference.asciidoc index 45e65e570d..d95b0c0f6a 100644 --- a/docs/en/observability/apm/command-reference.asciidoc +++ b/docs/en/observability/apm/configure/advanced-setup/command-reference.asciidoc @@ -26,7 +26,7 @@ endif::serverless[] // end::attributes[] [[apm-command-line-options]] -=== APM Server command reference += APM Server command reference ++++ Command reference @@ -74,7 +74,7 @@ Also see <>. [float] [[apm-apikey-command]] -==== `apikey` command +== `apikey` command experimental::[] @@ -172,7 +172,7 @@ For more information, see <>. [float] [[apm-export-command]] -==== `export` command +== `export` command ifndef::serverless[] {export-command-short-desc}. You can use this @@ -258,7 +258,7 @@ endif::serverless[] [float] [[apm-help-command]] -==== `help` command +== `help` command {help-command-short-desc}. ifndef::serverless[] @@ -291,7 +291,7 @@ apm-server help export ifndef::serverless[] [float] [[apm-keystore-command]] -==== `keystore` command +== `keystore` command {keystore-command-short-desc}. @@ -350,7 +350,7 @@ endif::[] ifndef::serverless[] [float] [[apm-run-command]] -==== `run` command +== `run` command {run-command-short-desc}. @@ -409,7 +409,7 @@ endif::[] [float] [[apm-test-command]] -==== `test` command +== `test` command {test-command-short-desc}. @@ -444,7 +444,7 @@ apm-server test config [float] [[apm-version-command]] -==== `version` command +== `version` command {version-command-short-desc}. @@ -472,7 +472,7 @@ apm-server version [float] [[apm-global-flags]] -=== Global flags +== Global flags These global flags are available whenever you run APM Server. diff --git a/docs/en/observability/apm/data-ingestion.asciidoc b/docs/en/observability/apm/configure/advanced-setup/data-ingestion.asciidoc similarity index 93% rename from docs/en/observability/apm/data-ingestion.asciidoc rename to docs/en/observability/apm/configure/advanced-setup/data-ingestion.asciidoc index 13c825a97d..d4e6373cc0 100644 --- a/docs/en/observability/apm/data-ingestion.asciidoc +++ b/docs/en/observability/apm/configure/advanced-setup/data-ingestion.asciidoc @@ -1,11 +1,11 @@ [[apm-tune-data-ingestion]] -=== Tune data ingestion += Tune data ingestion This section explains how to adapt data ingestion according to your needs. [float] [[apm-tune-apm-server]] -=== Tune APM Server +== Tune APM Server * <> * <> @@ -13,7 +13,7 @@ This section explains how to adapt data ingestion according to your needs. [[apm-add-apm-server-instances]] [float] -==== Add APM Server or {agent} instances +=== Add APM Server or {agent} instances If the APM Server cannot process data quickly enough, you will see request timeouts. @@ -25,7 +25,7 @@ Having several instances will also increase <Advanced setup +++++ + +Before reading this section, see the <> +for basic installation and running instructions. + +This section includes additional information on how to set up and run APM Server, including: + +* <> +* <> +* <> +* <> +* <> +* <> + +:leveloffset: +1 + +include::{observability-docs-root}/docs/en/observability/apm/configure/advanced-setup/shared-directory-layout.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/configure/advanced-setup/keystore.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/configure/advanced-setup/command-reference.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/configure/advanced-setup/data-ingestion.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/configure/advanced-setup/high-availability.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/configure/advanced-setup/shared-systemd.asciidoc[] + +:!leveloffset: diff --git a/docs/en/observability/apm/keystore.asciidoc b/docs/en/observability/apm/configure/advanced-setup/keystore.asciidoc similarity index 96% rename from docs/en/observability/apm/keystore.asciidoc rename to docs/en/observability/apm/configure/advanced-setup/keystore.asciidoc index 39183ab3a3..3e330f8e16 100644 --- a/docs/en/observability/apm/keystore.asciidoc +++ b/docs/en/observability/apm/configure/advanced-setup/keystore.asciidoc @@ -1,5 +1,5 @@ [[apm-keystore]] -=== Secrets keystore for secure settings += Secrets keystore for secure settings ++++ Secrets keystore @@ -45,7 +45,7 @@ APM Server. [discrete] [[apm-creating-keystore]] -=== Create a keystore +== Create a keystore To create a secrets keystore, use: @@ -59,7 +59,7 @@ configuration setting. [discrete] [[apm-add-keys-to-keystore]] -=== Add keys +== Add keys To store sensitive values, such as authentication credentials for {es}, use the `keystore add` command: @@ -88,7 +88,7 @@ cat /file/containing/setting/value | apm-server keystore add ES_PWD --stdin --fo [discrete] [[apm-list-settings]] -=== List keys +== List keys To list the keys defined in the keystore, use: @@ -99,7 +99,7 @@ apm-server keystore list [discrete] [[apm-remove-settings]] -=== Remove keys +== Remove keys To remove a key from the keystore, use: diff --git a/docs/en/observability/apm/shared-directory-layout.asciidoc b/docs/en/observability/apm/configure/advanced-setup/shared-directory-layout.asciidoc similarity index 95% rename from docs/en/observability/apm/shared-directory-layout.asciidoc rename to docs/en/observability/apm/configure/advanced-setup/shared-directory-layout.asciidoc index f9837466cc..49f1f765fd 100644 --- a/docs/en/observability/apm/shared-directory-layout.asciidoc +++ b/docs/en/observability/apm/configure/advanced-setup/shared-directory-layout.asciidoc @@ -10,12 +10,12 @@ ////////////////////////////////////////////////////////////////////////// [[apm-directory-layout]] -=== Installation layout += Installation layout View the installation layout and default paths for both Fleet-managed APM Server and the APM Server binary. [float] -=== Fleet-managed +== Fleet-managed {agent} files are installed in the following locations. You cannot override these installation paths because they are required for upgrades. @@ -25,7 +25,7 @@ include::{ingest-docs-root}/docs/en/ingest-management/tab-widgets/install-layout -- [float] -=== APM Server binary +== APM Server binary APM Server uses the following default paths unless you explicitly change them. diff --git a/docs/en/observability/apm/shared-systemd.asciidoc b/docs/en/observability/apm/configure/advanced-setup/shared-systemd.asciidoc similarity index 96% rename from docs/en/observability/apm/shared-systemd.asciidoc rename to docs/en/observability/apm/configure/advanced-setup/shared-systemd.asciidoc index 6db6d33565..dcad0c74c6 100644 --- a/docs/en/observability/apm/shared-systemd.asciidoc +++ b/docs/en/observability/apm/configure/advanced-setup/shared-systemd.asciidoc @@ -1,5 +1,5 @@ [[apm-running-with-systemd]] -=== APM Server and systemd += APM Server and systemd IMPORTANT: These commands only apply to the APM Server binary installation method. Fleet-managed users should see {fleet-guide}/start-stop-elastic-agent.html[Start and stop {agent}s on edge hosts]. @@ -12,7 +12,7 @@ We recommend that the apm-server process is run as a non-root user. Therefore, that is the default setup for APM Server's DEB package and RPM installation. [float] -==== Start and stop APM Server +== Start and stop APM Server Use `systemctl` to start or stop APM Server: @@ -40,7 +40,7 @@ sudo systemctl disable apm-server ------------------------------------------------ [float] -==== APM Server status and logs +== APM Server status and logs To get the service status, use `systemctl`: @@ -57,7 +57,7 @@ journalctl -u apm-server.service ------------------------------------------------ [float] -=== Customize systemd unit for APM Server +== Customize systemd unit for APM Server The systemd service unit file includes environment variables that you can override to change the default options. diff --git a/docs/en/observability/apm/configure/agent-config.asciidoc b/docs/en/observability/apm/configure/agent-config.asciidoc index 50b6c7eb6e..40abb459f2 100644 --- a/docs/en/observability/apm/configure/agent-config.asciidoc +++ b/docs/en/observability/apm/configure/agent-config.asciidoc @@ -25,7 +25,7 @@ apm-server.agent.config.elasticsearch.api_key: TiNAGG4BaaMdaH1tRfuU:KnR6yE41RrSo ---- [float] -= APM agent configuration options +== APM agent configuration options The following options are only supported for APM Server binary users. You can specify these options in the `apm-server.agent.config` section of the @@ -33,14 +33,14 @@ You can specify these options in the `apm-server.agent.config` section of the [float] [[apm-agent-config-cache]] -== `apm-server.agent.config.cache.expiration` +=== `apm-server.agent.config.cache.expiration` When using APM agent configuration, information fetched from {es} will be cached in memory for some time. Specify the cache expiration time via this setting. Defaults to `30s` (30 seconds). [float] [[apm-agent-config-elasticsearch]] -== `apm-server.agent.config.elasticsearch` +=== `apm-server.agent.config.elasticsearch` Takes the same options as <>. @@ -50,7 +50,7 @@ configuration. If `output.elasticsearch` isn't set or doesn't have sufficient pr use these {es} options to provide {es} access. [float] -== Common problems +=== Common problems You may see either of the following HTTP 403 errors from APM Server when it attempts to fetch APM agent configuration: diff --git a/docs/en/observability/apm/configure/anonymous-auth.asciidoc b/docs/en/observability/apm/configure/anonymous-auth.asciidoc index 16695d34b3..3068eb5a8a 100644 --- a/docs/en/observability/apm/configure/anonymous-auth.asciidoc +++ b/docs/en/observability/apm/configure/anonymous-auth.asciidoc @@ -28,7 +28,7 @@ IMPORTANT: All anonymous access configuration is ignored if [float] [[apm-config-auth-anon-rum]] -= Real User Monitoring (RUM) +== Real User Monitoring (RUM) If an <> or <> is configured, then anonymous authentication must be enabled to collect RUM data. @@ -39,7 +39,7 @@ See <> for additional RUM configuration options. [float] [[apm-config-auth-anon-mitigating]] -== Mitigating malicious requests +=== Mitigating malicious requests There are a few configuration variables that can mitigate the impact of malicious requests to an unauthenticated APM Server endpoint. @@ -53,7 +53,7 @@ This allows you to specify the maximum number of requests allowed per unique IP [float] [[apm-config-auth-anon-client-ip]] -== Deriving an incoming request's `client.ip` address +=== Deriving an incoming request's `client.ip` address The remote IP address of an incoming request might be different from the end-user's actual IP address, for example, because of a proxy. For this reason, @@ -68,7 +68,7 @@ If none of these headers are present, the remote address for the incoming reques [float] [[apm-config-auth-anon-client-ip-concerns]] -== Using a reverse proxy or load balancer +=== Using a reverse proxy or load balancer HTTP headers are easily modified; it's possible for anyone to spoof the derived `client.ip` value by changing or setting, @@ -83,11 +83,11 @@ APM Server's rate limiting feature. [float] [[apm-config-auth-anon]] -= Configuration reference +== Configuration reference [float] [[apm-config-auth-anon-enabled]] -== Anonymous Agent access +=== Anonymous Agent access Enable or disable anonymous authentication. Default: `false` (disabled). (bool) @@ -99,7 +99,7 @@ Default: `false` (disabled). (bool) [float] [[apm-config-auth-anon-allow-agent]] -== Allowed anonymous agents +=== Allowed anonymous agents A list of permitted {apm-agent} names for anonymous authentication. Names in this list must match the agent's `agent.name`. Default: `[rum-js, js-base]` (only RUM agent events are accepted). (array) @@ -124,7 +124,7 @@ Default: Not set (any service name is accepted). (array) [float] [[apm-config-auth-anon-ip-limit]] -== IP limit +=== IP limit The number of unique IP addresses to track in an LRU cache. IP addresses in the cache will be rate limited according to the <> setting. Consider increasing this default if your application has many concurrent clients. @@ -137,7 +137,7 @@ Default: `1000`. (int) [float] [[apm-config-auth-anon-event-limit]] -== Event limit +=== Event limit The maximum number of events allowed per second, per agent IP address. Default: `300`. (int) diff --git a/docs/en/observability/apm/configure/auth.asciidoc b/docs/en/observability/apm/configure/auth.asciidoc index f04958beee..d8c02bd988 100644 --- a/docs/en/observability/apm/configure/auth.asciidoc +++ b/docs/en/observability/apm/configure/auth.asciidoc @@ -13,14 +13,14 @@ include::./tab-widgets/auth-config-widget.asciidoc[] [float] [[apm-api-key-auth-settings]] -= API key authentication options +== API key authentication options These settings apply to API key communication between the APM Server and APM Agents. NOTE: These settings are different from the API key settings used for {es} output and monitoring. [float] -== API key for agent authentication +=== API key for agent authentication Enable API key authorization by setting `enabled` to `true`. By default, `enabled` is set to `false`, and API key support is disabled. (bool) @@ -35,7 +35,7 @@ When enabled, third-party APM agents must include a valid API key in the followi `Authorization: ApiKey `. The key must be the base64 encoded representation of the API key's `id:name`. [float] -== API key limit +=== API key limit Each unique API key triggers one request to {es}. This setting restricts the number of unique API keys are allowed per minute. @@ -48,7 +48,7 @@ The default `limit` is `100`. (int) |==== [float] -== Secret token +=== Secret token Authorization token for sending APM data. The same token must also be set in each {apm-agent}. @@ -60,7 +60,7 @@ This token is not used for RUM endpoints. (text) |==== [float] -= `auth.api_key.elasticsearch.*` configuration options +== `auth.api_key.elasticsearch.*` configuration options **** image:./binary-yes-fm-no.svg[supported deployment methods] @@ -72,51 +72,51 @@ If none are set, configuration settings from the `apm-server.output` section wil **** [float] -== `elasticsearch.hosts` +=== `elasticsearch.hosts` API keys are fetched from {es}. This configuration needs to point to a secured {es} cluster that is able to serve API key requests. [float] -== `elasticsearch.protocol` +=== `elasticsearch.protocol` The name of the protocol {es} is reachable on. The options are: `http` or `https`. The default is `http`. If nothing is configured, configuration settings from the `output` section will be reused. [float] -== `elasticsearch.path` +=== `elasticsearch.path` An optional HTTP path prefix that is prepended to the HTTP API calls. If nothing is configured, configuration settings from the `output` section will be reused. [float] -== `elasticsearch.proxy_url` +=== `elasticsearch.proxy_url` The URL of the proxy to use when connecting to the {es} servers. The value may be either a complete URL or a "host[:port]", in which case the "http"scheme is assumed. If nothing is configured, configuration settings from the `output` section will be reused. [float] -== `elasticsearch.timeout` +=== `elasticsearch.timeout` The HTTP request timeout in seconds for the {es} request. If nothing is configured, configuration settings from the `output` section will be reused. [float] -= `auth.api_key.elasticsearch.ssl.*` configuration options +== `auth.api_key.elasticsearch.ssl.*` configuration options SSL is off by default. Set `elasticsearch.protocol` to `https` if you want to enable `https`. [float] -== `elasticsearch.ssl.enabled` +=== `elasticsearch.ssl.enabled` Enable custom SSL settings. Set to false to ignore custom SSL settings for secure communication. [float] -== `elasticsearch.ssl.verification_mode` +=== `elasticsearch.ssl.verification_mode` Configure SSL verification mode. If `none` is configured, all server hosts and certificates will be accepted. @@ -124,45 +124,45 @@ In this mode, SSL based connections are susceptible to man-in-the-middle attacks **Use only for testing**. Default is `full`. [float] -== `elasticsearch.ssl.supported_protocols` +=== `elasticsearch.ssl.supported_protocols` List of supported/valid TLS versions. By default, all TLS versions from 1.0 to 1.2 are enabled. [float] -== `elasticsearch.ssl.certificate_authorities` +=== `elasticsearch.ssl.certificate_authorities` List of root certificates for HTTPS server verifications. [float] -== `elasticsearch.ssl.certificate` +=== `elasticsearch.ssl.certificate` The path to the certificate for SSL client authentication. [float] -== `elasticsearch.ssl.key` +=== `elasticsearch.ssl.key` The client certificate key used for client authentication. This option is required if certificate is specified. [float] -== `elasticsearch.ssl.key_passphrase` +=== `elasticsearch.ssl.key_passphrase` An optional passphrase used to decrypt an encrypted key stored in the configured key file. [float] -== `elasticsearch.ssl.cipher_suites` +=== `elasticsearch.ssl.cipher_suites` The list of cipher suites to use. The first entry has the highest priority. If this option is omitted, the Go crypto library’s default suites are used (recommended). [float] -== `elasticsearch.ssl.curve_types` +=== `elasticsearch.ssl.curve_types` The list of curve types for ECDHE (Elliptic Curve Diffie-Hellman ephemeral key exchange). [float] -== `elasticsearch.ssl.renegotiation` +=== `elasticsearch.ssl.renegotiation` Configure what types of renegotiation are supported. Valid options are `never`, `once`, and `freely`. Default is `never`. diff --git a/docs/en/observability/apm/configure/general.asciidoc b/docs/en/observability/apm/configure/general.asciidoc index decdc577e8..16d889230a 100644 --- a/docs/en/observability/apm/configure/general.asciidoc +++ b/docs/en/observability/apm/configure/general.asciidoc @@ -13,11 +13,11 @@ include::./tab-widgets/general-config-widget.asciidoc[] [float] [[apm-configuration-apm-server]] -= Configuration options +== Configuration options [[apm-host]] [float] -== Host +=== Host Defines the host and port the server is listening on. Use `"unix:/path/to.sock"` to listen on a Unix domain socket. Defaults to 'localhost:8200'. (text) @@ -28,7 +28,7 @@ Defaults to 'localhost:8200'. (text) |==== [float] -== URL +=== URL The publicly reachable server URL. For deployments on Elastic Cloud or ECK, the default is unchangeable. |==== @@ -38,7 +38,7 @@ The publicly reachable server URL. For deployments on Elastic Cloud or ECK, the [[apm-max_header_size]] [float] -== Max header size +=== Max header size Maximum permitted size of a request's header accepted by the server to be processed (in Bytes). Defaults to 1048576 Bytes (1 MB). (int) @@ -49,7 +49,7 @@ Defaults to 1048576 Bytes (1 MB). (int) [[apm-idle_timeout]] [float] -== Idle timeout +=== Idle timeout Maximum amount of time to wait for the next incoming request before underlying connection is closed. Defaults to `45s` (45 seconds). (text) @@ -60,7 +60,7 @@ Defaults to `45s` (45 seconds). (text) [[apm-read_timeout]] [float] -== Read timeout +=== Read timeout Maximum permitted duration for reading an entire request. Defaults to `3600s` (3600 seconds). (text) @@ -71,7 +71,7 @@ Defaults to `3600s` (3600 seconds). (text) [[apm-write_timeout]] [float] -== Write timeout +=== Write timeout Maximum permitted duration for writing a response. Defaults to `30s` (30 seconds). (text) @@ -82,7 +82,7 @@ Defaults to `30s` (30 seconds). (text) [[apm-shutdown_timeout]] [float] -=== Shutdown timeout +==== Shutdown timeout Maximum duration in seconds before releasing resources when shutting down the server. Defaults to `30s` (30 seconds). (text) @@ -93,7 +93,7 @@ Defaults to `30s` (30 seconds). (text) [[apm-max_event_size]] [float] -== Max event size +=== Max event size Maximum permitted size of an event accepted by the server to be processed (in Bytes). Defaults to `307200` Bytes. (int) @@ -104,7 +104,7 @@ Defaults to `307200` Bytes. (int) [[apm-max_connections]] [float] -== Max connections +=== Max connections Maximum number of TCP connections to accept simultaneously. Default value is 0, which means _unlimited_. (int) @@ -115,7 +115,7 @@ Default value is 0, which means _unlimited_. (int) [[apm-custom_http_headers]] [float] -== Custom HTTP response headers +=== Custom HTTP response headers Custom HTTP headers to add to HTTP responses. Useful for security policy compliance. (text) |==== @@ -125,7 +125,7 @@ Custom HTTP headers to add to HTTP responses. Useful for security policy complia [[apm-capture_personal_data]] [float] -== Capture personal data +=== Capture personal data If true, APM Server captures the IP of the instrumented service and its User Agent if any. Enabled by default. (bool) @@ -138,7 +138,7 @@ Enabled by default. (bool) [[apm-default_service_environment]] [float] -== Default service environment +=== Default service environment Sets the default service environment to associate with data and requests received from agents which have no service environment defined. Default: none. (text) |==== @@ -148,7 +148,7 @@ Sets the default service environment to associate with data and requests receive [[apm-expvar.enabled]] [float] -== expvar support +=== expvar support When set to true APM Server exposes https://golang.org/pkg/expvar/[golang expvar] under `/debug/vars`. Disabled by default. @@ -159,7 +159,7 @@ Disabled by default. [[apm-expvar.url]] [float] -== expvar URL +=== expvar URL Configure the URL to expose expvar. Defaults to `debug/vars`. @@ -170,7 +170,7 @@ Defaults to `debug/vars`. [[apm-data_streams.namespace]] [float] -== Data stream namespace +=== Data stream namespace Change the default namespace. This setting changes the name of the integration's data stream. diff --git a/docs/en/observability/apm/configure/index.asciidoc b/docs/en/observability/apm/configure/index.asciidoc index c4d2722f8e..df3fe704a5 100644 --- a/docs/en/observability/apm/configure/index.asciidoc +++ b/docs/en/observability/apm/configure/index.asciidoc @@ -1,5 +1,5 @@ [[apm-configuring-howto-apm-server]] -= Configure += Configure APM Server How you configure the APM Server depends on your deployment method. @@ -49,4 +49,6 @@ include::tls.asciidoc[leveloffset=+1] include::sampling.asciidoc[leveloffset=+1] -include::env.asciidoc[leveloffset=+1] \ No newline at end of file +include::env.asciidoc[leveloffset=+1] + +include::advanced-setup/index.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/configure/rum.asciidoc b/docs/en/observability/apm/configure/rum.asciidoc index 0156fb0c4b..5dbab0cb8e 100644 --- a/docs/en/observability/apm/configure/rum.asciidoc +++ b/docs/en/observability/apm/configure/rum.asciidoc @@ -23,11 +23,11 @@ you will need to configure {apm-rum-ref-v}/configuring-cors.html[Cross-Origin Re [float] [[apm-enable-rum-support]] -= Configuration reference +== Configuration reference [[apm-rum-enable]] [float] -== Enable RUM +=== Enable RUM To enable RUM support, set to `true`. By default this is disabled. (bool) @@ -45,7 +45,7 @@ Anonymous authentication is required as the RUM agent runs in the browser. [float] [[apm-rum-allow-origins]] -== Allowed Origins +=== Allowed Origins A list of permitted origins for RUM support. User-agents send an Origin header that will be validated against this list. This is done automatically by modern browsers as part of the https://www.w3.org/TR/cors/[CORS specification]. @@ -60,7 +60,7 @@ Default: `['*']` (allows everything). (text) [float] [[apm-rum-allow-headers]] -== Access-Control-Allow-Headers +=== Access-Control-Allow-Headers HTTP requests made from the RUM agent to the APM Server are limited in the HTTP headers they are allowed to have. If any other headers are added, the request will be rejected by the browser due to Cross-Origin Resource Sharing (CORS) restrictions. Use this setting to allow additional headers. @@ -76,7 +76,7 @@ Default: `[]`. (text) [float] [[apm-rum-response-headers]] -== Custom HTTP response headers +=== Custom HTTP response headers Custom HTTP headers to add to RUM responses. This can be useful for security policy compliance. @@ -91,7 +91,7 @@ Default: none. (text) [float] [[apm-rum-library-pattern]] -== Library Frame Pattern +=== Library Frame Pattern RegExp to be matched against a stack trace frame's `file_name` and `abs_path` attributes. If the RegExp matches, the stack trace frame is considered to be a library frame. When source mapping is applied, the `error.culprit` is set to reflect the _function_ and the _filename_ @@ -106,7 +106,7 @@ Default: `"node_modules|bower_components|~"`. (text) |==== [float] -== Exclude from grouping +=== Exclude from grouping RegExp to be matched against a stack trace frame's `file_name`. If the RegExp matches, the stack trace frame is excluded from being used for calculating error groups. @@ -120,7 +120,7 @@ Default: `"^/webpack"` (excludes stack trace frames that have a filename startin [float] [[apm-rum-source-map]] -= Source map configuration options +== Source map configuration options **** image:./binary-yes-fm-no.svg[supported deployment methods] @@ -131,7 +131,7 @@ the options in this section are only supported by the APM Server binary. [[apm-config-sourcemapping-enabled]] [float] -== `source_mapping.enabled` +=== `source_mapping.enabled` Used to enable/disable <> for RUM events. When enabled, the APM Server needs additional privileges to read source maps. See <> for more details. @@ -140,14 +140,14 @@ Default: `true` [[apm-config-sourcemapping-elasticsearch]] [float] -== `source_mapping.elasticsearch` +=== `source_mapping.elasticsearch` Configure the {es} source map retrieval location, taking the same options as <>. This must be set when using an output other than {es}, and that output is writing to {es}. Otherwise leave this section empty. [[apm-rum-sourcemap-cache]] [float] -== `source_mapping.cache.expiration` +=== `source_mapping.cache.expiration` If a source map has been uploaded to the APM Server, <> is automatically applied to documents sent to the RUM endpoint. Source maps are fetched from {es} and then kept in an in-memory cache for the configured time. @@ -156,7 +156,7 @@ Values configured without a time unit are treated as seconds. Default: `5m` (5 minutes) [float] -== `source_mapping.index_pattern` +=== `source_mapping.index_pattern` Previous versions of APM Server stored source maps in `apm-%{[observer.version]}-sourcemap` indices. Search source maps stored in an older version with this setting. @@ -164,11 +164,11 @@ Default: `"apm-*-sourcemap*"` [float] [[apm-rum-deprecated]] -= Deprecated configuration options +== Deprecated configuration options [float] [[apm-event_rate.limit]] -== `event_rate.limit` +=== `event_rate.limit` deprecated::[7.15.0, Replaced by <>.] @@ -177,7 +177,7 @@ The maximum number of events allowed per second, per agent IP address. Default: `300` [float] -== `event_rate.lru_size` +=== `event_rate.lru_size` deprecated::[7.15.0, Replaced by <>.] @@ -189,7 +189,7 @@ Default: `1000` [float] [[apm-rum-allow-service-names]] -== `allow_service_names` +=== `allow_service_names` deprecated::[7.15.0, Replaced by <>.] A list of permitted service names for RUM support. @@ -200,7 +200,7 @@ in order to limit the number of service-specific indices or data streams created Default: Not set (any service name is accepted) [float] -= Ingest pipelines +== Ingest pipelines The default APM Server pipeline includes processors that enrich RUM data prior to indexing in {es}. See <> for details on how to locate, edit, or disable this preprocessing. \ No newline at end of file diff --git a/docs/en/observability/apm/configure/sampling.asciidoc b/docs/en/observability/apm/configure/sampling.asciidoc index 7932ee17d0..cd31a3e079 100644 --- a/docs/en/observability/apm/configure/sampling.asciidoc +++ b/docs/en/observability/apm/configure/sampling.asciidoc @@ -13,7 +13,7 @@ include::./tab-widgets/sampling-config-widget.asciidoc[] [float] [[apm-configuration-tbs]] -= Top-level tail-based sampling settings +== Top-level tail-based sampling settings See <> to learn more. @@ -22,7 +22,7 @@ See <> to learn more. [float] [id="sampling-tail-enabled-{input-type}"] -== Enable tail-based sampling +=== Enable tail-based sampling Set to `true` to enable tail based sampling. Disabled by default. (bool) @@ -33,7 +33,7 @@ Disabled by default. (bool) [float] [id="sampling-tail-interval-{input-type}"] -== Interval +=== Interval Synchronization interval for multiple APM Servers. Should be in the order of tens of seconds or low minutes. Default: `1m` (1 minute). (duration) @@ -45,7 +45,7 @@ Default: `1m` (1 minute). (duration) [float] [id="sampling-tail-policies-{input-type}"] -== Policies +=== Policies Criteria used to match a root transaction to a sample rate. Policies map trace events to a sample rate. @@ -63,7 +63,7 @@ This final policy is used to catch remaining trace events that don't match a str [float] [id="sampling-tail-storage_limit-{input-type}"] -== Storage limit +=== Storage limit The amount of storage space allocated for trace events matching tail sampling policies. Caution: Setting this limit higher than the allowed space may cause APM Server to become unhealthy. If the configured storage limit is insufficient, it logs "configured storage limit reached". The event will bypass sampling and will always be indexed when storage limit is reached. @@ -79,7 +79,7 @@ Default: `3GB`. (text) [float] [[apm-configuration-tbs-policy]] -= Policy-level tail-based sampling settings +== Policy-level tail-based sampling settings See <> to learn more. @@ -87,9 +87,7 @@ See <> to learn more. [float] [id="sampling-tail-sample-rate-{input-type}"] -== Sample rate - -**`sample_rate`** +=== **`sample_rate`** The sample rate to apply to trace events matching this policy. Required in each policy. @@ -100,9 +98,7 @@ A `sample_rate` of `1` means that 100% of trace events matching the policy will [float] [id="sampling-tail-trace-name-{input-type}"] -== Trace name - -**`trace.name`** +=== **`trace.name`** The trace name for events to match a policy. A match occurs when the configured `trace.name` matches the `transaction.name` of the root transaction of a trace. @@ -110,9 +106,7 @@ A root transaction is any transaction without a `parent.id`. (string) [float] [id="sampling-tail-trace-outcome-{input-type}"] -== Trace outcome - -**`trace.outcome`** +=== **`trace.outcome`** The trace outcome for events to match a policy. A match occurs when the configured `trace.outcome` matches a trace's `event.outcome` field. @@ -120,17 +114,13 @@ Trace outcome can be `success`, `failure`, or `unknown`. (string) [float] [id="sampling-tail-service-name-{input-type}"] -== Service name - -**`service.name`** +=== **`service.name`** The service name for events to match a policy. (string) [float] [id="sampling-tail-service-environment-{input-type}"] -== Service Environment - -**`service.environment`** +=== **`service.environment`** The service environment for events to match a policy. (string) diff --git a/docs/en/observability/apm/data-model/data-model-errors.asciidoc b/docs/en/observability/apm/data-model/data-model-errors.asciidoc new file mode 100644 index 0000000000..2f2c749918 --- /dev/null +++ b/docs/en/observability/apm/data-model/data-model-errors.asciidoc @@ -0,0 +1,52 @@ +[[apm-data-model-errors]] += Errors + +An error event contains at least +information about the original `exception` that occurred +or about a `log` created when the exception occurred. +For simplicity, errors are represented by a unique ID. + +An Error contains: + +* Both the captured `exception` and the captured `log` of an error can contain a `stack trace`, +which is helpful for debugging. +* The `culprit` of an error indicates where it originated. +* An error might relate to the <> during which it happened, +via the `transaction.id`. +* Data about the environment in which the event is recorded: +** Service - environment, framework, language, etc. +** Host - architecture, hostname, IP, etc. +** Process - args, PID, PPID, etc. +** URL - full, domain, port, query, etc. +** <> - (if supplied) email, ID, username, etc. + +In addition, agents provide options for users to capture custom <>. +Metadata can be indexed - <>, or not-indexed - <>. + +TIP: Most agents limit keyword fields (e.g. `error.id`) to 1024 characters, +non-keyword fields (e.g. `error.exception.message`) to 10,000 characters. + +Errors are stored in error indices. + +[float] +== Data streams + +Errors are stored in the following data streams: + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[tag=logs-data-streams] + +See <> to learn more. + +[float] +== Example error document + +This example shows what error documents can look like when indexed in {es}. + +[%collapsible] +.Expand {es} document +==== +[source,json] +---- +include::{apm-server-root}/docs/data/elasticsearch/generated/errors.json[] +---- +==== diff --git a/docs/en/observability/apm/data-model/data-model-metadata.asciidoc b/docs/en/observability/apm/data-model/data-model-metadata.asciidoc new file mode 100644 index 0000000000..fa6be2fc94 --- /dev/null +++ b/docs/en/observability/apm/data-model/data-model-metadata.asciidoc @@ -0,0 +1,99 @@ +[[apm-data-model-metadata]] += Metadata + +Metadata can enrich your events and make application performance monitoring even more useful. +Let's explore the different types of metadata that Elastic APM offers. + +[float] +[[apm-data-model-labels]] +== Labels + +Labels add *indexed* information to transactions, spans, and errors. +Indexed means the data is searchable and aggregatable in {es}. +Add additional key-value pairs to define multiple labels. + +* Indexed: Yes +* {es} type: {ref}/object.html[object] +* {es} field: `labels` +* Applies to: <> | <> | <> + +Label values can be a string, boolean, or number, although some agents only support string values at this time. +Because labels for a given key, regardless of agent used, are stored in the same place in {es}, +all label values of a given key must have the same data type. +Multiple data types per key will throw an exception, for example: `{foo: bar}` and `{foo: 42}` is not allowed. + +IMPORTANT: Avoid defining too many user-specified labels. +Defining too many unique fields in an index is a condition that can lead to a +{ref}/mapping.html#mapping-limit-settings[mapping explosion]. + +[float] +=== Agent API reference + +* Go: {apm-go-ref-v}/api.html#context-set-label[`SetLabel`] +* Java: {apm-java-ref-v}/public-api.html#api-transaction-add-tag[`setLabel`] +* .NET: {apm-dotnet-ref-v}/public-api.html#api-transaction-set-label[`SetLabel`] +* Node.js: {apm-node-ref-v}/agent-api.html#apm-set-label[`setLabel`] | {apm-node-ref-v}/agent-api.html#apm-add-labels[`addLabels`] +* PHP: {apm-php-ref}/public-api.html#api-transaction-interface-set-label[`Transaction` `setLabel`] | {apm-php-ref}/public-api.html#api-span-interface-set-label[`Span` `setLabel`] +* Python: {apm-py-ref-v}/api.html#api-label[`elasticapm.label()`] +* Ruby: {apm-ruby-ref-v}/api.html#api-agent-set-label[`set_label`] +* Rum: {apm-rum-ref-v}/agent-api.html#apm-add-labels[`addLabels`] + +[float] +[[apm-data-model-custom]] +== Custom context + +Custom context adds *non-indexed*, +custom contextual information to transactions and errors. +Non-indexed means the data is not searchable or aggregatable in {es}, +and you cannot build dashboards on top of the data. +This also means you don't have to worry about {ref}/mapping.html#mapping-limit-settings[mapping explosions], +as these fields are not added to the mapping. + +Non-indexed information is useful for providing contextual information to help you +quickly debug performance issues or errors. + +* Indexed: No +* {es} type: {ref}/object.html[object] +* {es} fields: `transaction.custom` | `error.custom` +* Applies to: <> | <> + +IMPORTANT: Setting a circular object, a large object, or a non JSON serializable object can lead to errors. + +[float] +=== Agent API reference + +* Go: {apm-go-ref-v}/api.html#context-set-custom[`SetCustom`] +* iOS: _coming soon_ +* Java: {apm-java-ref-v}/public-api.html#api-transaction-add-custom-context[`addCustomContext`] +* .NET: _coming soon_ +* Node.js: {apm-node-ref-v}/agent-api.html#apm-set-custom-context[`setCustomContext`] +* PHP: _coming soon_ +* Python: {apm-py-ref-v}/api.html#api-set-custom-context[`set_custom_context`] +* Ruby: {apm-ruby-ref-v}/api.html#api-agent-set-custom-context[`set_custom_context`] +* Rum: {apm-rum-ref-v}/agent-api.html#apm-set-custom-context[`setCustomContext`] + +[float] +[[apm-data-model-user]] +== User context + +User context adds *indexed* user information to transactions and errors. +Indexed means the data is searchable and aggregatable in {es}. + +* Indexed: Yes +* {es} type: {ref}/keyword.html[keyword] +* {es} fields: `user.email` | `user.name` | `user.id` +* Applies to: <> | <> + +[float] +=== Agent API reference + +* Go: {apm-go-ref-v}/api.html#context-set-username[`SetUsername`] | {apm-go-ref-v}/api.html#context-set-user-id[`SetUserID`] | +{apm-go-ref-v}/api.html#context-set-user-email[`SetUserEmail`] +* iOS: _coming soon_ +* Java: {apm-java-ref-v}/public-api.html#api-transaction-set-user[`setUser`] +* .NET _coming soon_ +* Node.js: {apm-node-ref-v}/agent-api.html#apm-set-user-context[`setUserContext`] +* PHP: _coming soon_ +* Python: {apm-py-ref-v}/api.html#api-set-user-context[`set_user_context`] +* Ruby: {apm-ruby-ref-v}/api.html#api-agent-set-user[`set_user`] +* Rum: {apm-rum-ref-v}/agent-api.html#apm-set-user-context[`setUserContext`] diff --git a/docs/en/observability/apm/data-model.asciidoc b/docs/en/observability/apm/data-model/data-model-metrics.asciidoc similarity index 54% rename from docs/en/observability/apm/data-model.asciidoc rename to docs/en/observability/apm/data-model/data-model-metrics.asciidoc index 60c0a69c07..9f2161c2e1 100644 --- a/docs/en/observability/apm/data-model.asciidoc +++ b/docs/en/observability/apm/data-model/data-model-metrics.asciidoc @@ -1,224 +1,5 @@ -:span-name-type-sheet: https://docs.google.com/spreadsheets/d/1SmWeX5AeqUcayrArUauS_CxGgsjwRgMYH4ZY8yQsMhQ/edit#gid=644582948 -:span-spec: https://github.com/elastic/apm/blob/main/tests/agents/json-specs/span_types.json - -[[apm-data-model]] -== Data Model - -Elastic APM agents capture different types of information from within their instrumented applications. -These are known as events, and can be `spans`, `transactions`, `errors`, or `metrics`. - -* <> -* <> -* <> -* <> - -Events can contain additional <> which further enriches your data. - -[[apm-data-model-spans]] -=== Spans - -*Spans* contain information about the execution of a specific code path. -They measure from the start to the end of an activity, -and they can have a parent/child relationship with other spans. - -Agents automatically instrument a variety of libraries to capture these spans from within your application, -but you can also use the Agent API for custom instrumentation of specific code paths. - -Among other things, spans can contain: - -* A `transaction.id` attribute that refers to its parent <>. -* A `parent.id` attribute that refers to its parent span or transaction. -* Its start time and duration. -* A `name`, `type`, `subtype`, and `action`—see the {span-name-type-sheet}[span name/type alignment] -sheet for span name patterns and examples by {apm-agent}. -In addition, some APM agents test against a public {span-spec}[span type/subtype spec]. -* An optional `stack trace`. Stack traces consist of stack frames, -which represent a function call on the call stack. -They include attributes like function name, file name and path, line number, etc. - -TIP: Most agents limit keyword fields, like `span.id`, to 1024 characters, -and non-keyword fields, like `span.start.us`, to 10,000 characters. - -[float] -[[apm-data-model-dropped-spans]] -==== Dropped spans - -For performance reasons, APM agents can choose to sample or omit spans purposefully. -This can be useful in preventing edge cases, like long-running transactions with over 100 spans, -that would otherwise overload both the Agent and the APM Server. -When this occurs, the APM UI will display the number of spans dropped. - -To configure the number of spans recorded per transaction, see the relevant Agent documentation: - -* Android: _Not yet supported_ -* Go: {apm-go-ref-v}/configuration.html#config-transaction-max-spans[`ELASTIC_APM_TRANSACTION_MAX_SPANS`] -* iOS: _Not yet supported_ -* Java: {apm-java-ref-v}/config-core.html#config-transaction-max-spans[`transaction_max_spans`] -* .NET: {apm-dotnet-ref-v}/config-core.html#config-transaction-max-spans[`TransactionMaxSpans`] -* Node.js: {apm-node-ref-v}/configuration.html#transaction-max-spans[`transactionMaxSpans`] -* PHP: {apm-php-ref-v}/configuration-reference.html#config-transaction-max-spans[`transaction_max_spans`] -* Python: {apm-py-ref-v}/configuration.html#config-transaction-max-spans[`transaction_max_spans`] -* Ruby: {apm-ruby-ref-v}/configuration.html#config-transaction-max-spans[`transaction_max_spans`] - -[float] -[[apm-data-model-missing-spans]] -==== Missing spans - -Agents stream spans to the APM Server separately from their transactions. -Because of this, unforeseen errors may cause spans to go missing. -Agents know how many spans a transaction should have; -if the number of expected spans does not equal the number of spans received by the APM Server, -the APM UI will calculate the difference and display a message. - -[float] -==== Data streams - -Spans are stored with transactions in the following data streams: - -include::./data-streams.asciidoc[tag=traces-data-streams] - -See <> to learn more. - -[float] -==== Example span document - -This example shows what span documents can look like when indexed in {es}. - -[%collapsible] -.Expand {es} document -==== -[source,json] ----- -include::{apm-server-root}/docs/data/elasticsearch/generated/spans.json[] ----- -==== - -[[apm-data-model-transactions]] -=== Transactions - -*Transactions* are a special kind of <> that have additional attributes associated with them. -They describe an event captured by an Elastic {apm-agent} instrumenting a service. -You can think of transactions as the highest level of work you’re measuring within a service. -As an example, a transaction might be a: - -* Request to your server -* Batch job -* Background job -* Custom transaction type - -Agents decide whether to sample transactions or not, -and provide settings to control sampling behavior. -If sampled, the <> of a transaction are sent and stored as separate documents. -Within one transaction there can be 0, 1, or many spans captured. - -A transaction contains: - -* The timestamp of the event -* A unique id, type, and name -* Data about the environment in which the event is recorded: -** Service - environment, framework, language, etc. -** Host - architecture, hostname, IP, etc. -** Process - args, PID, PPID, etc. -** URL - full, domain, port, query, etc. -** <> - (if supplied) email, ID, username, etc. -* Other relevant information depending on the agent. Example: The JavaScript RUM agent captures transaction marks, -which are points in time relative to the start of the transaction with some label. - -In addition, agents provide options for users to capture custom <>. -Metadata can be indexed - <>, or not-indexed - <>. - -Transactions are grouped by their `type` and `name` in the APM UI's -<>. -If you're using a supported framework, APM agents will automatically handle the naming for you. -If you're not, or if you wish to override the default, -all agents have API methods to manually set the `type` and `name`. - -* `type` should be a keyword of specific relevance in the service's domain, -e.g. `request`, `backgroundjob`, etc. -* `name` should be a generic designation of a transaction in the scope of a single service, -e.g. `GET /users/:id`, `UsersController#show`, etc. - -TIP: Most agents limit keyword fields (e.g. `labels`) to 1024 characters, -non-keyword fields (e.g. `span.db.statement`) to 10,000 characters. - -[float] -==== Data streams - -Transactions are stored with spans in the following data streams: - -include::./data-streams.asciidoc[tag=traces-data-streams] - -See <> to learn more. - -[float] -==== Example transaction document - -This example shows what transaction documents can look like when indexed in {es}. - -[%collapsible] -.Expand {es} document -==== -[source,json] ----- -include::{apm-server-root}/docs/data/elasticsearch/generated/transactions.json[] ----- -==== - -[[apm-data-model-errors]] -=== Errors - -An error event contains at least -information about the original `exception` that occurred -or about a `log` created when the exception occurred. -For simplicity, errors are represented by a unique ID. - -An Error contains: - -* Both the captured `exception` and the captured `log` of an error can contain a `stack trace`, -which is helpful for debugging. -* The `culprit` of an error indicates where it originated. -* An error might relate to the <> during which it happened, -via the `transaction.id`. -* Data about the environment in which the event is recorded: -** Service - environment, framework, language, etc. -** Host - architecture, hostname, IP, etc. -** Process - args, PID, PPID, etc. -** URL - full, domain, port, query, etc. -** <> - (if supplied) email, ID, username, etc. - -In addition, agents provide options for users to capture custom <>. -Metadata can be indexed - <>, or not-indexed - <>. - -TIP: Most agents limit keyword fields (e.g. `error.id`) to 1024 characters, -non-keyword fields (e.g. `error.exception.message`) to 10,000 characters. - -Errors are stored in error indices. - -[float] -==== Data streams - -Errors are stored in the following data streams: - -include::./data-streams.asciidoc[tag=logs-data-streams] - -See <> to learn more. - -[float] -==== Example error document - -This example shows what error documents can look like when indexed in {es}. - -[%collapsible] -.Expand {es} document -==== -[source,json] ----- -include::{apm-server-root}/docs/data/elasticsearch/generated/errors.json[] ----- -==== - [[apm-data-model-metrics]] -=== Metrics += Metrics **Metrics** measure the state of a system by gathering information on a regular interval. There are two types of APM metrics: @@ -226,7 +7,7 @@ include::{apm-server-root}/docs/data/elasticsearch/generated/errors.json[] * **Calculated metrics**: Aggregated trace event metrics used to power visualizations in the APM UI. [float] -==== System metrics +== System metrics APM agents automatically pick up basic host-level metrics, including system and process-level CPU and memory metrics. @@ -251,7 +32,7 @@ For a full list of tracked metrics, see the relevant agent documentation: * {apm-ruby-ref-v}/metrics.html[Ruby] [float] -===== Example system metric document +=== Example system metric document This example shows what system metric documents can look like when indexed in {es}. @@ -271,7 +52,7 @@ include::{apm-server-root}/docs/data/elasticsearch/metricset.json[] ==== [float] -==== Calculated metrics +== Calculated metrics APM agents and APM Server calculate metrics from trace events to power visualizations in the APM UI. @@ -281,7 +62,7 @@ the dimensions and concrete limits for aggregations are subject to change within These metrics are described below. [float] -===== Breakdown metrics +=== Breakdown metrics To power the <> graph, agents collect summarized metrics about the timings of spans and transactions, @@ -306,7 +87,7 @@ You can filter and group by these dimensions: -- [float] -===== Example breakdown metric document +=== Example breakdown metric document This example shows what breakdown metric documents can look like when indexed in {es}. @@ -321,7 +102,7 @@ include::{apm-server-root}/docs/data/elasticsearch/span_breakdown.json[] ==== [float] -===== Transaction metrics +=== Transaction metrics To power <> visualizations, APM Server aggregates transaction events into latency distribution metrics. @@ -377,7 +158,7 @@ You can filter and group by these dimensions (some of which are optional, for ex The `@timestamp` field of these documents holds the start of the aggregation interval. [float] -===== Example transaction document +=== Example transaction document This example shows what transaction documents can look like when indexed in {es}. @@ -392,7 +173,7 @@ include::{apm-server-root}/docs/data/elasticsearch/transaction_metric.json[] ==== [float] -===== Service-transaction metrics +=== Service-transaction metrics To power <> visualizations, APM Server aggregates transaction events into service-transaction metrics. @@ -423,7 +204,7 @@ You can filter and group by these dimensions: The `@timestamp` field of these documents holds the start of the aggregation interval. [float] -===== Example service-transaction document +=== Example service-transaction document This example shows what service-transaction documents can look like when indexed in {es}. @@ -438,7 +219,7 @@ include::{apm-server-root}/docs/data/elasticsearch/service_transaction_metric.js ==== [float] -===== Service-destination metrics +=== Service-destination metrics To power <> visualizations, APM Server aggregates span events into service-destination metrics. @@ -471,7 +252,7 @@ You can filter and group by these dimensions: The `@timestamp` field of these documents holds the start of the aggregation interval. [float] -===== Example service-destination document +=== Example service-destination document This example shows what service-destination documents can look like when indexed in {es}. @@ -486,7 +267,7 @@ include::{apm-server-root}/docs/data/elasticsearch/service_destination_metric.js ==== [float] -===== Service-summary metrics +=== Service-summary metrics To power <> visualizations, APM Server aggregates transaction, error, log, and metric events into service-summary metrics. @@ -506,7 +287,7 @@ You can filter and group by these dimensions: The `@timestamp` field of these documents holds the start of the aggregation interval. [float] -===== Example service-summary document +=== Example service-summary document This example shows what service-summary documents can look like when indexed in {es}. @@ -521,22 +302,22 @@ include::{apm-server-root}/docs/data/elasticsearch/service_summary_metric.json[] ==== [float] -==== Data streams +== Data streams Metrics are stored in the following data streams: -include::./data-streams.asciidoc[tag=metrics-data-streams] +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[tag=metrics-data-streams] See <> to learn more. [float] -==== Aggregated metrics: limits and overflows +== Aggregated metrics: limits and overflows For all aggregated metrics, namely transaction, service-transaction, service-destination, and service-summary metrics, there are limits on the number of unique groups tracked at any given time. [float] -===== Limits +=== Limits Note that all the below limits may change in the future with further improvements. @@ -556,7 +337,7 @@ which is 1000 service destination groups for 1GB APM Server with 500 increment p In the above, a service is defined as a combination of `service.name`, `service.environment`, `service.language.name` and `agent.name`. [float] -===== Overflows +=== Overflows When a dimension has a high cardinality and exceeds the limit, the metrics will be aggregated under a dedicated overflow bucket. @@ -577,104 +358,3 @@ that are based on parameters that can change. For example, user ids, product ids should be stripped away from the dimensions. For the same reason, avoid high cardinality global labels (`labels.\*` and `numeric_labels.*`). Aggregated metrics do not consider global labels from RUM agents in order to protect APM server from using too much memory. - -// This heading is linked to from the APM UI section in Kibana -[[apm-data-model-metadata]] -=== Metadata - -Metadata can enrich your events and make application performance monitoring even more useful. -Let's explore the different types of metadata that Elastic APM offers. - -[float] -[[apm-data-model-labels]] -==== Labels - -Labels add *indexed* information to transactions, spans, and errors. -Indexed means the data is searchable and aggregatable in {es}. -Add additional key-value pairs to define multiple labels. - -* Indexed: Yes -* {es} type: {ref}/object.html[object] -* {es} field: `labels` -* Applies to: <> | <> | <> - -Label values can be a string, boolean, or number, although some agents only support string values at this time. -Because labels for a given key, regardless of agent used, are stored in the same place in {es}, -all label values of a given key must have the same data type. -Multiple data types per key will throw an exception, for example: `{foo: bar}` and `{foo: 42}` is not allowed. - -IMPORTANT: Avoid defining too many user-specified labels. -Defining too many unique fields in an index is a condition that can lead to a -{ref}/mapping.html#mapping-limit-settings[mapping explosion]. - -[float] -===== Agent API reference - -* Go: {apm-go-ref-v}/api.html#context-set-label[`SetLabel`] -* Java: {apm-java-ref-v}/public-api.html#api-transaction-add-tag[`setLabel`] -* .NET: {apm-dotnet-ref-v}/public-api.html#api-transaction-set-label[`SetLabel`] -* Node.js: {apm-node-ref-v}/agent-api.html#apm-set-label[`setLabel`] | {apm-node-ref-v}/agent-api.html#apm-add-labels[`addLabels`] -* PHP: {apm-php-ref}/public-api.html#api-transaction-interface-set-label[`Transaction` `setLabel`] | {apm-php-ref}/public-api.html#api-span-interface-set-label[`Span` `setLabel`] -* Python: {apm-py-ref-v}/api.html#api-label[`elasticapm.label()`] -* Ruby: {apm-ruby-ref-v}/api.html#api-agent-set-label[`set_label`] -* Rum: {apm-rum-ref-v}/agent-api.html#apm-add-labels[`addLabels`] - -[float] -[[apm-data-model-custom]] -==== Custom context - -Custom context adds *non-indexed*, -custom contextual information to transactions and errors. -Non-indexed means the data is not searchable or aggregatable in {es}, -and you cannot build dashboards on top of the data. -This also means you don't have to worry about {ref}/mapping.html#mapping-limit-settings[mapping explosions], -as these fields are not added to the mapping. - -Non-indexed information is useful for providing contextual information to help you -quickly debug performance issues or errors. - -* Indexed: No -* {es} type: {ref}/object.html[object] -* {es} fields: `transaction.custom` | `error.custom` -* Applies to: <> | <> - -IMPORTANT: Setting a circular object, a large object, or a non JSON serializable object can lead to errors. - -[float] -===== Agent API reference - -* Go: {apm-go-ref-v}/api.html#context-set-custom[`SetCustom`] -* iOS: _coming soon_ -* Java: {apm-java-ref-v}/public-api.html#api-transaction-add-custom-context[`addCustomContext`] -* .NET: _coming soon_ -* Node.js: {apm-node-ref-v}/agent-api.html#apm-set-custom-context[`setCustomContext`] -* PHP: _coming soon_ -* Python: {apm-py-ref-v}/api.html#api-set-custom-context[`set_custom_context`] -* Ruby: {apm-ruby-ref-v}/api.html#api-agent-set-custom-context[`set_custom_context`] -* Rum: {apm-rum-ref-v}/agent-api.html#apm-set-custom-context[`setCustomContext`] - -[float] -[[apm-data-model-user]] -==== User context - -User context adds *indexed* user information to transactions and errors. -Indexed means the data is searchable and aggregatable in {es}. - -* Indexed: Yes -* {es} type: {ref}/keyword.html[keyword] -* {es} fields: `user.email` | `user.name` | `user.id` -* Applies to: <> | <> - -[float] -===== Agent API reference - -* Go: {apm-go-ref-v}/api.html#context-set-username[`SetUsername`] | {apm-go-ref-v}/api.html#context-set-user-id[`SetUserID`] | -{apm-go-ref-v}/api.html#context-set-user-email[`SetUserEmail`] -* iOS: _coming soon_ -* Java: {apm-java-ref-v}/public-api.html#api-transaction-set-user[`setUser`] -* .NET _coming soon_ -* Node.js: {apm-node-ref-v}/agent-api.html#apm-set-user-context[`setUserContext`] -* PHP: _coming soon_ -* Python: {apm-py-ref-v}/api.html#api-set-user-context[`set_user_context`] -* Ruby: {apm-ruby-ref-v}/api.html#api-agent-set-user[`set_user`] -* Rum: {apm-rum-ref-v}/agent-api.html#apm-set-user-context[`setUserContext`] diff --git a/docs/en/observability/apm/span-compression.asciidoc b/docs/en/observability/apm/data-model/data-model-spans.asciidoc similarity index 54% rename from docs/en/observability/apm/span-compression.asciidoc rename to docs/en/observability/apm/data-model/data-model-spans.asciidoc index 8156639bd3..a0e395b2fb 100644 --- a/docs/en/observability/apm/span-compression.asciidoc +++ b/docs/en/observability/apm/data-model/data-model-spans.asciidoc @@ -1,5 +1,85 @@ -[[apm-span-compression]] -=== Span compression +[[apm-data-model-spans]] += Spans + +*Spans* contain information about the execution of a specific code path. +They measure from the start to the end of an activity, +and they can have a parent/child relationship with other spans. + +Agents automatically instrument a variety of libraries to capture these spans from within your application, +but you can also use the Agent API for custom instrumentation of specific code paths. + +Among other things, spans can contain: + +* A `transaction.id` attribute that refers to its parent <>. +* A `parent.id` attribute that refers to its parent span or transaction. +* Its start time and duration. +* A `name`, `type`, `subtype`, and `action`—see the {span-name-type-sheet}[span name/type alignment] +sheet for span name patterns and examples by {apm-agent}. +In addition, some APM agents test against a public {span-spec}[span type/subtype spec]. +* An optional `stack trace`. Stack traces consist of stack frames, +which represent a function call on the call stack. +They include attributes like function name, file name and path, line number, etc. + +TIP: Most agents limit keyword fields, like `span.id`, to 1024 characters, +and non-keyword fields, like `span.start.us`, to 10,000 characters. + +[float] +[[apm-data-model-dropped-spans]] +== Dropped spans + +For performance reasons, APM agents can choose to sample or omit spans purposefully. +This can be useful in preventing edge cases, like long-running transactions with over 100 spans, +that would otherwise overload both the Agent and the APM Server. +When this occurs, the APM UI will display the number of spans dropped. + +To configure the number of spans recorded per transaction, see the relevant Agent documentation: + +* Android: _Not yet supported_ +* Go: {apm-go-ref-v}/configuration.html#config-transaction-max-spans[`ELASTIC_APM_TRANSACTION_MAX_SPANS`] +* iOS: _Not yet supported_ +* Java: {apm-java-ref-v}/config-core.html#config-transaction-max-spans[`transaction_max_spans`] +* .NET: {apm-dotnet-ref-v}/config-core.html#config-transaction-max-spans[`TransactionMaxSpans`] +* Node.js: {apm-node-ref-v}/configuration.html#transaction-max-spans[`transactionMaxSpans`] +* PHP: {apm-php-ref-v}/configuration-reference.html#config-transaction-max-spans[`transaction_max_spans`] +* Python: {apm-py-ref-v}/configuration.html#config-transaction-max-spans[`transaction_max_spans`] +* Ruby: {apm-ruby-ref-v}/configuration.html#config-transaction-max-spans[`transaction_max_spans`] + +[float] +[[apm-data-model-missing-spans]] +== Missing spans + +Agents stream spans to the APM Server separately from their transactions. +Because of this, unforeseen errors may cause spans to go missing. +Agents know how many spans a transaction should have; +if the number of expected spans does not equal the number of spans received by the APM Server, +the APM UI will calculate the difference and display a message. + +[float] +== Data streams + +Spans are stored with transactions in the following data streams: + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[tag=traces-data-streams] + +See <> to learn more. + +[float] +== Example span document + +This example shows what span documents can look like when indexed in {es}. + +[%collapsible] +.Expand {es} document +==== +[source,json] +---- +include::{apm-server-root}/docs/data/elasticsearch/generated/spans.json[] +---- +==== + +[float] +[[apm-spans-span-compression]] +== Span compression In some cases, APM agents may collect large amounts of very similar or identical spans in a transaction. For example, this can happen if spans are captured inside of a loop, or in unoptimized SQL queries that use multiple queries instead of joins to fetch related data. diff --git a/docs/en/observability/apm/apm-distributed-tracing.asciidoc b/docs/en/observability/apm/data-model/distributed-tracing.asciidoc similarity index 84% rename from docs/en/observability/apm/apm-distributed-tracing.asciidoc rename to docs/en/observability/apm/data-model/distributed-tracing.asciidoc index 42c04a4e79..dbb1e6df76 100644 --- a/docs/en/observability/apm/apm-distributed-tracing.asciidoc +++ b/docs/en/observability/apm/data-model/distributed-tracing.asciidoc @@ -1,10 +1,19 @@ +[[apm-data-model-traces]] += Traces + +A trace is a group of <> and <> with a common root. +Each trace tracks the entirety of a single request. It describes the individual operations and their causality that +ensue from a single logical operation. + +[float] [[apm-distributed-tracing]] -=== Distributed tracing +== Distributed tracing + +When a trace travels through multiple services, as is common in a microservice architecture, +it is known as a *distributed trace*. A distributed trace comprises operations across multiple +distributed components, crossing process, network, and security boundaries. -A `trace` is a group of <> and <> with a common root. -Each `trace` tracks the entirety of a single request. -When a `trace` travels through multiple services, as is common in a microservice architecture, -it is known as a distributed trace. +image::images/distributed-traces.png[Diagram illustrating the relationship between spans, transactions, and distributed traces as described in the text on this page] [float] [[apm-why-distributed-tracing]] @@ -37,7 +46,7 @@ and continues to propagate the trace. [float] [[apm-trace-propagation]] -==== Trace propagation examples +=== Trace propagation examples In this example, Elastic's Ruby agent communicates with Elastic's Java agent. Both support the `traceparent` header, and trace data is successfully propagated. @@ -60,7 +69,7 @@ image::./images/dt-trace-ex3.png[How traceparent propagation works] [float] [[apm-w3c-tracecontext-spec]] -==== W3C Trace Context specification +=== W3C Trace Context specification All Elastic agents now support the official W3C Trace Context specification and `traceparent` header. See the table below for the minimum required agent version: diff --git a/docs/en/observability/apm/data-model/index.asciidoc b/docs/en/observability/apm/data-model/index.asciidoc new file mode 100644 index 0000000000..b3d0771787 --- /dev/null +++ b/docs/en/observability/apm/data-model/index.asciidoc @@ -0,0 +1,52 @@ +:span-name-type-sheet: https://docs.google.com/spreadsheets/d/1SmWeX5AeqUcayrArUauS_CxGgsjwRgMYH4ZY8yQsMhQ/edit#gid=644582948 +:span-spec: https://github.com/elastic/apm/blob/main/tests/agents/json-specs/span_types.json + +[[apm-data-model]] += Application data types + +++++ +Learn about data types +++++ + +Elastic APM agents capture different types of information from within their instrumented applications. +These are known as events, and can be spans, transactions, traces, errors, or metrics. + +//// +Explain how the different data types relate to each other at a high level +//// + +Elastic APM helps you see what happens from start to finish when a request is made to an application: + +* <>: A span contain information about the execution of a specific code path. + They are the building blocks of _transactions_ and _traces_. +* <>: A transaction describes an event captured by an Elastic + APM agent instrumenting a service. A transaction is technically a type of span that has additional + attributes associated with it and often contains multiple child _spans_. You can think of transactions + as the highest level of work you’re measuring within a service. +* <>: A trace is a group of _transactions_ and _spans_ with a common root. + Each trace tracks the entirety of a single request. When a trace travels through multiple services, + it is known as a _distributed trace_. + +image::images/spans-transactions-and-traces.png[Diagram illustrating the relationship between spans, transactions, and traces as described in the text on this page] + +In addition to the building blocks of traces, Elastic APM agents also capture: + +* <>: An error is created when something goes wrong with a request to an application. + This event contains information to help you determine where and why an error occurred, often including in which + _transaction_ the error occurred. +* <>: Metrics measure the state of a system by gathering information on a regular interval. + +Events can contain additional <> which further enriches your data. + +//// +Subsections +//// + +:leveloffset: +1 +include::{observability-docs-root}/docs/en/observability/apm/data-model/data-model-spans.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/data-model/transactions/index.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/data-model/distributed-tracing.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/data-model/data-model-errors.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/data-model/data-model-metrics.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/data-model/data-model-metadata.asciidoc[] +:!leveloffset: diff --git a/docs/en/observability/apm/data-model/transactions/index.asciidoc b/docs/en/observability/apm/data-model/transactions/index.asciidoc new file mode 100644 index 0000000000..3b4ade2936 --- /dev/null +++ b/docs/en/observability/apm/data-model/transactions/index.asciidoc @@ -0,0 +1,76 @@ +[[apm-data-model-transactions]] += Transactions + +*Transactions* are a special kind of <> that have additional attributes associated with them. +They describe an event captured by an Elastic {apm-agent} instrumenting a service. +You can think of transactions as the highest level of work you’re measuring within a service. +As an example, a transaction might be a: + +* Request to your server +* Batch job +* Background job +* Custom transaction type + +Agents decide whether to sample transactions or not, +and provide settings to control sampling behavior. +If sampled, the <> of a transaction are sent and stored as separate documents. +Within one transaction there can be 0, 1, or many spans captured. + +A transaction contains: + +* The timestamp of the event +* A unique id, type, and name +* Data about the environment in which the event is recorded: +** Service - environment, framework, language, etc. +** Host - architecture, hostname, IP, etc. +** Process - args, PID, PPID, etc. +** URL - full, domain, port, query, etc. +** <> - (if supplied) email, ID, username, etc. +* Other relevant information depending on the agent. Example: The JavaScript RUM agent captures transaction marks, +which are points in time relative to the start of the transaction with some label. + +In addition, agents provide options for users to capture custom <>. +Metadata can be indexed - <>, or not-indexed - <>. + +Transactions are grouped by their `type` and `name` in the APM UI's +<>. +If you're using a supported framework, APM agents will automatically handle the naming for you. +If you're not, or if you wish to override the default, +all agents have API methods to manually set the `type` and `name`. + +* `type` should be a keyword of specific relevance in the service's domain, +e.g. `request`, `backgroundjob`, etc. +* `name` should be a generic designation of a transaction in the scope of a single service, +e.g. `GET /users/:id`, `UsersController#show`, etc. + +TIP: Most agents limit keyword fields (e.g. `labels`) to 1024 characters, +non-keyword fields (e.g. `span.db.statement`) to 10,000 characters. + +[float] +== Data streams + +Transactions are stored with spans in the following data streams: + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[tag=traces-data-streams] + +See <> to learn more. + +[float] +== Example transaction document + +This example shows what transaction documents can look like when indexed in {es}. + +[%collapsible] +.Expand {es} document +==== +[source,json] +---- +include::{apm-server-root}/docs/data/elasticsearch/generated/transactions.json[] +---- +==== + +//// +Subsections +//// + +include::{observability-docs-root}/docs/en/observability/apm/data-model/transactions/sampling.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/sampling.asciidoc b/docs/en/observability/apm/data-model/transactions/sampling.asciidoc similarity index 93% rename from docs/en/observability/apm/sampling.asciidoc rename to docs/en/observability/apm/data-model/transactions/sampling.asciidoc index 33172f4dc9..af055d6093 100644 --- a/docs/en/observability/apm/sampling.asciidoc +++ b/docs/en/observability/apm/data-model/transactions/sampling.asciidoc @@ -1,5 +1,5 @@ [[apm-sampling]] -=== Transaction sampling += Transaction sampling Distributed tracing can generate a substantial amount of data. More data can mean higher costs and more noise. @@ -14,7 +14,7 @@ Elastic APM supports two types of sampling: [float] [[apm-head-based-sampling]] -==== Head-based sampling +== Head-based sampling In head-based sampling, the sampling decision for each trace is made when the trace is initiated. Each trace has a defined and equal probability of being sampled. @@ -31,7 +31,7 @@ See <> to get started. [float] [[distributed-tracing-examples]] -===== Distributed tracing +=== Distributed tracing In a distributed trace, the sampling decision is still made when the trace is initiated. Each subsequent service respects the initial service's sampling decision, regardless of its configured sample rate; @@ -52,7 +52,7 @@ be `1` (`100%`). image::./images/dt-sampling-example-2.png[Distributed tracing and head based sampling example two] [float] -===== Trace continuation strategies with distributed tracing +==== Trace continuation strategies with distributed tracing In addition to setting the sample rate, you can also specify which _trace continuation strategy_ to use. There are three trace continuation strategies: `continue`, `restart`, and `restart_external`. @@ -91,7 +91,7 @@ traces will be sampled as new traces in `Service C`. The end result will be five image::./images/dt-sampling-continuation-strategy-restart.png[Distributed tracing and head based sampling with restart continuation strategy] [float] -===== OpenTelemetry +=== OpenTelemetry Head-based sampling is implemented directly in the APM agents and SDKs. The sample rate must be propagated between services and the managed intake service in order to produce accurate metrics. @@ -113,7 +113,7 @@ Refer to the documentation of your favorite OpenTelemetry agent or SDK for more [float] [[apm-tail-based-sampling]] -==== Tail-based sampling +== Tail-based sampling In tail-based sampling, the sampling decision for each trace is made after the trace has completed. This means all traces will be analyzed against a set of rules, or policies, which will determine the rate at which they are sampled. @@ -129,7 +129,8 @@ So running APM Server close to your instrumented services can reduce any increas See <> to get started. -**Distributed tracing with tail-based sampling** +[float] +=== Distributed tracing with tail-based sampling With tail-based sampling, all traces are observed and a sampling decision is only made once a trace completes. @@ -140,7 +141,8 @@ the sampled traces would look something like this: image::./images/dt-sampling-example-3.png[Distributed tracing and tail based sampling example one] -**OpenTelemetry with tail-based sampling** +[float] +=== OpenTelemetry with tail-based sampling Tail-based sampling is implemented entirely in APM Server, and will work with traces sent by either Elastic APM agents or OpenTelemetry SDKs. @@ -148,7 +150,7 @@ and will work with traces sent by either Elastic APM agents or OpenTelemetry SDK Due to <> when using https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/tailsamplingprocessor[tailsamplingprocessor], we recommend using APM Server tail-based sampling instead. [float] -==== Sampled data and visualizations +== Sampled data and visualizations A sampled trace retains all data associated with it. A non-sampled trace drops all <> and <> data^1^. @@ -174,7 +176,7 @@ The {kib} apps that utilize RUM data depend on transaction events, so non-sampled RUM traces retain transaction data -- only span data is dropped. [float] -==== Sample rates +== Sample rates What's the best sampling rate? Unfortunately, there isn't one. Sampling is dependent on your data, the throughput of your application, data retention policies, and other factors. @@ -189,26 +191,27 @@ Here are some examples: Regardless of the above, cost conscious customers are likely to be fine with a lower sample rate. +[float] [[apm-configure-head-based-sampling]] -==== Configure head-based sampling +== Configure head-based sampling There are three ways to adjust the head-based sampling rate of your APM agents: [float] -===== Dynamic configuration +=== Dynamic configuration The transaction sample rate can be changed dynamically (no redeployment necessary) on a per-service and per-environment basis with <> in {kib}. [float] -===== {kib} API configuration +=== {kib} API configuration {apm-agent} configuration exposes an API that can be used to programmatically change your agents' sampling rate. An example is provided in the <>. [float] -===== {apm-agent} configuration +=== {apm-agent} configuration Each agent provides a configuration value used to set the transaction sample rate. See the relevant agent's documentation for more details: @@ -221,8 +224,9 @@ See the relevant agent's documentation for more details: * Python: {apm-py-ref-v}/configuration.html#config-transaction-sample-rate[`transaction_sample_rate`] * Ruby: {apm-ruby-ref-v}/configuration.html#config-transaction-sample-rate[`transaction_sample_rate`] +[float] [[apm-configure-tail-based-sampling]] -==== Configure tail-based sampling +== Configure tail-based sampling Enable tail-based sampling with <>. When enabled, trace events are mapped to sampling policies. @@ -241,7 +245,7 @@ but, due to how the limit is calculated and enforced the actual disk space may s over the limit. [float] -===== Example configuration +=== Example configuration This example defines three tail-based sampling polices: @@ -261,14 +265,14 @@ This example defines three tail-based sampling polices: or traces with any other name [float] -===== Configuration reference +=== Configuration reference -**Top-level tail-based sampling settings:** +[float] +==== Top-level tail-based sampling settings -:leveloffset: +4 -include::./configure/sampling.asciidoc[tag=tbs-top] +include::{observability-docs-root}/docs/en/observability/apm/configure/sampling.asciidoc[tag=tbs-top,leveloffset=+2] -**Policy settings:** +[float] +==== Policy settings -include::./configure/sampling.asciidoc[tag=tbs-policy] -:leveloffset: -4 +include::{observability-docs-root}/docs/en/observability/apm/configure/sampling.asciidoc[tag=tbs-policy,leveloffset=+2] diff --git a/docs/en/observability/apm/features.asciidoc b/docs/en/observability/apm/features.asciidoc deleted file mode 100644 index 6800ce61b6..0000000000 --- a/docs/en/observability/apm/features.asciidoc +++ /dev/null @@ -1,37 +0,0 @@ -[[apm-features]] -== Elastic APM features - -++++ -Features -++++ - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -include::./apm-k8s-attacher.asciidoc[leveloffset=+2] - -include::./cross-cluster-search.asciidoc[] - -include::./apm-data-security.asciidoc[] - -include::./apm-distributed-tracing.asciidoc[] - -include::./jaeger-integration.asciidoc[] - -include::./log-correlation.asciidoc[] - -include::./aws-lambda-extension.asciidoc[leveloffset=+2] - -include::./apm-rum.asciidoc[] - -include::./span-compression.asciidoc[] - -include::./sampling.asciidoc[] diff --git a/docs/en/observability/apm/getting-started-apm-server.asciidoc b/docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc similarity index 55% rename from docs/en/observability/apm/getting-started-apm-server.asciidoc rename to docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc index 9ccde19dbd..4087a8cc64 100644 --- a/docs/en/observability/apm/getting-started-apm-server.asciidoc +++ b/docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc @@ -1,153 +1,10 @@ -[[apm-getting-started-apm-server]] -== Self manage APM Server - -++++ -Self manage APM Server -++++ - -TIP: The easiest way to get started with Elastic APM is by using our -{ess-product}[hosted {es} Service] on {ecloud}. -The {es} Service is available on AWS, GCP, and Azure. -See <> to get started in minutes. - - -// TODO: MOVE THIS -IMPORTANT: Starting in version 8.0.0, {fleet} uses the APM integration to set up and manage APM index templates, -{ilm-init} policies, and ingest pipelines. APM Server will only send data to {es} _after_ the APM integration has been installed. - -The APM Server receives performance data from your APM agents, -validates and processes it, and then transforms the data into {es} documents. -If you're on this page, then you've chosen to self-manage the Elastic Stack, -and you now must decide how to run and configure the APM Server. -There are two options, and the components required are different for each: - -* **<>** -* **<>** -// * **<>** - -[float] -[[apm-setup-apm-server-binary]] -=== APM Server binary - -Install, configure, and run the APM Server binary wherever you need it. - -image::./images/bin-ov.png[APM Server binary overview] - -**Pros**: - -- Simplest self-managed option -- No addition component knowledge required -- YAML configuration simplifies automation - -**Supported outputs**: - -- {es} -- {ess} -- {ls} -- Kafka -- Redis -- File -- Console - -**Required components**: - -- APM agents -- APM Server -- {stack} - -**Configuration method**: YAML - -[float] -[[apm-setup-fleet-managed-apm]] -=== Fleet-managed APM Server - -Fleet is a web-based UI in {kib} that is used to centrally manage {agent}s. -In this deployment model, use {agent} to spin up APM Server instances that can be centrally-managed in a custom-curated user interface. - -NOTE: Fleet-managed APM Server does not have full feature parity with the APM Server binary method of running Elastic APM. - -image::./images/fm-ov.png[APM Server fleet overview] - -// (outputs, stable APIs) -// not the best option for a simple test setup or if only interested in centrally running APM Server - -**Pros**: - -- Conveniently manage one, some, or many different integrations from one central {fleet} UI. - -**Supported outputs**: - -- {es} -- {ess} - -**Required components**: - -- APM agents -- APM Server -- {agent} -- Fleet Server -- {stack} - -**Configuration method**: {kib} UI - -// [float] -// [[apm-setup-apm-server-ea]] -// === Standalone Elastic Agent-managed APM Server -// // I really don't know how to sell this option -// Instead of installing and configuring the APM Server binary, let {agent} orchestrate it for you. -// Install {agent} and manually configure the agent locally on the system where it's installed. -// You are responsible for managing and upgrading {agent}. This approach is recommended for advanced users only. - -// **Pros**: - -// - Easily add integrations for other data sources -// useful if EA already in place for other integrations, and customers want to customize setup rather than using Fleet for configuration -// // TODO: -// // maybe get some more hints on this one from the EA team to align with highlighting the same pros & cons. - -// **Available on Elastic Cloud**: ❌ - -// This supports all of the same outputs as binary -// see https://github.com/elastic/apm-server/issues/10467 -// **Supported outputs**: - -// **Configuration method**: YAML - -// image::./images/ea-ov.png[APM Server ea overview] - -// @simitt's notes for how to include EA-managed in the decision tree: -// **** -// If we generally describe Standalone Elastic Agent managed APM Server then we should also add it to this diagram: -// Do you want to use other integrations? -// -> yes: Would you like to use the comfort of Fleet UI based management? -> yes: Fleet managed APM Server; -> no: Standalone Elastic Agent managed APM Server -// -> no: What is your prefered way of configuration? -> yaml: APM Server binary; -> Kibana UI: Fleet managed APM Server -// **** - -// Components required: - -// [options="header"] -// |==== -// | Installation method | APM Server | Elastic Agent | Fleet Server -// | APM Server binary | ✔️ | | -// // | Standalone Elastic Agent-managed APM Server | ✔️ | ✔️ | -// | Fleet-managed APM Server | ✔️ | ✔️ | ✔️ -// |==== - -[float] -=== Help me decide - -Use the decision tree below to help determine which method of configuring and running the APM Server is best for your use case. - -[subs=attributes+] -include::{observability-docs-root}/docs/en/observability/apm/diagrams/apm-decision-tree.asciidoc[APM Server decision tree] - - -=== APM Server binary +[[get-started-with-apm-server-binary]] += APM Server binary This guide will explain how to set up and configure the APM Server binary. [float] -==== Prerequisites +== Prerequisites // tag::prereq[] First, see the https://www.elastic.co/support/matrix[Elastic Support Matrix] for information about supported operating systems and product compatibility. @@ -168,8 +25,9 @@ image::images/apm-architecture-diy.png[Install Elastic APM yourself] // STEP 1 // ******************************************************* +[float] [[apm-installing]] -==== Step 1: Install +== Step 1: Install NOTE: *Before you begin*: If you haven't installed the {stack}, do that now. See {stack-ref}/installing-elastic-stack.html[Learn how to install the @@ -303,8 +161,9 @@ See <> for deploying Docker containers // STEP 2 // ******************************************************* +[float] [[apm-server-configuration]] -==== Step 2: Set up and configure +== Step 2: Set up and configure // This content is reused in the upgrading guide // tag::why-apm-integration[] @@ -313,7 +172,7 @@ Starting in version 8.0.0, {fleet} uses the APM integration to set up and manage // end::why-apm-integration[] [float] -===== Install the APM integration +=== Install the APM integration // This content is reused in the upgrading guide // tag::install-apm-integration[] @@ -367,7 +226,7 @@ See {kibana-ref}/api.html[Kibana API] to learn more about how to use the Kibana // end::install-apm-integration[] [float] -===== Configure APM +=== Configure APM Configure APM by editing the `apm-server.yml` configuration file. The location of this file varies by platform--see the <> for help locating it. @@ -396,8 +255,9 @@ All available configuration options are outlined in // STEP 3 // ******************************************************* +[float] [[apm-server-starting]] -==== Step 3: Start +== Step 3: Start In a production environment, you would put APM Server on its own machines, similar to how you run {es}. @@ -426,7 +286,7 @@ You can change the defaults in `apm-server.yml` or by supplying a different addr [float] [[apm-running-deb-rpm]] -===== Debian Package / RPM +=== Debian Package / RPM For Debian package and RPM installations, we recommend the `apm-server` process runs as a non-root user. Therefore, these installation methods create an `apm-server` user which you can use to start the process. @@ -447,97 +307,32 @@ See the <> for a full directory la // STEP 4 // ******************************************************* +[float] [[apm-next-steps]] -==== Step 4: Next steps - -// Use a tagged region to pull APM Agent information from the APM Overview -If you haven't already, you can now install APM Agents in your services! - -* {apm-android-ref}/intro.html[Android agent] -* {apm-go-ref-v}/introduction.html[Go agent] -* {apm-ios-ref-v}/intro.html[iOS agent] -* {apm-java-ref-v}/intro.html[Java agent] -* {apm-dotnet-ref-v}/intro.html[.NET agent] -* {apm-node-ref-v}/intro.html[Node.js agent] -* {apm-php-ref-v}/intro.html[PHP agent] -* {apm-py-ref-v}/getting-started.html[Python agent] -* {apm-ruby-ref-v}/introduction.html[Ruby agent] -* {apm-rum-ref-v}/intro.html[JavaScript Real User Monitoring (RUM) agent] - -Once you have at least one {apm-agent} sending data to APM Server, -you can start visualizing your data in the <>. +== Step 4: Install APM agents -If you're migrating from Jaeger, see <>. - -// Shared APM & YUM -include::{observability-docs-root}/docs/en/observability/apm/repositories.asciidoc[] - -// Shared docker -include::{observability-docs-root}/docs/en/observability/apm/shared-docker.asciidoc[] - -[[get-started-with-fleet-apm-server]] -=== Fleet-managed APM Server +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/install-agents-widget.asciidoc[] -This guide will explain how to set up and configure a Fleet-managed APM Server. +// ******************************************************* +// STEP 5 +// ******************************************************* [float] -==== Prerequisites - -You need {es} for storing and searching your data, and {kib} for visualizing and managing it. -When setting these components up, you need: - -include::{ingest-docs-root}/docs/en/ingest-management/tab-widgets/prereq.asciidoc[tag=self-managed] - -==== Step 1: Set up Fleet +== Step 5: View your data -Use {fleet} in {kib} to get APM data into the {stack}. -The first time you use {fleet}, you'll need to set it up and add a -{fleet-server}: - -include::{ingest-docs-root}/docs/en/ingest-management/tab-widgets/add-fleet-server/content.asciidoc[tag=self-managed] - -For more information, refer to {fleet-guide}/fleet-server.html[{fleet-server}]. - -[[add-apm-integration]] -==== Step 2: Add and configure the APM integration - -include::{observability-docs-root}/docs/en/observability/tab-widgets/add-apm-integration/content.asciidoc[tag=self-managed] - -**** -An internet connection is required to install the APM integration via the Fleet UI in Kibana. - --- -include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm-server.asciidoc[tag=install-apm-integration-no-internet] --- -**** - -==== Step 3: Install APM agents - -APM agents are written in the same language as your service. -To monitor a new service, you must install the agent and configure it with a service name, -APM Server host, and Secret token. - -* **Service name**: The APM integration maps an instrumented service's name–defined in each {apm-agent}'s configuration– -to the index that its data is stored in {es}. -Service names are case-insensitive and must be unique. -For example, you cannot have a service named `Foo` and another named `foo`. -Special characters will be removed from service names and replaced with underscores (`_`). - -* **APM Server URL**: The host and port that APM Server listens for events on. -This should match the host and port defined when setting up the APM integration. - -* **Secret token**: Authentication method for {apm-agent} and APM Server communication. -This should match the secret token defined when setting up the APM integration. - -TIP: You can edit your APM integration settings if you need to change the APM Server URL -or secret token to match your APM agents. +Once you have at least one {apm-agent} sending data to APM Server, +you can start visualizing your data in the <>. -include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/install-agents-widget.asciidoc[] +[role="screenshot"] +image::./images/kibana-apm-sample-data.png[APM UI with data] -==== Step 4: View your data +// If you're migrating from Jaeger, see <>. -Back in {kib}, under {observability}, select APM. -You should see application performance monitoring data flowing into the {stack}! +//// +Subsections +//// -[role="screenshot"] -image::./images/kibana-apm-sample-data.png[APM UI with data] +// Shared APM & YUM +include::{observability-docs-root}/docs/en/observability/apm/repositories.asciidoc[leveloffset=+1] +// Shared docker +include::{observability-docs-root}/docs/en/observability/apm/shared-docker.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/getting-started-apm/get-started-with-fleet-apm-server.asciidoc b/docs/en/observability/apm/getting-started-apm/get-started-with-fleet-apm-server.asciidoc new file mode 100644 index 0000000000..261bf4617a --- /dev/null +++ b/docs/en/observability/apm/getting-started-apm/get-started-with-fleet-apm-server.asciidoc @@ -0,0 +1,70 @@ +[[get-started-with-fleet-apm-server]] += Fleet-managed APM Server + +This guide will explain how to set up and configure a Fleet-managed APM Server. + +[float] +== Prerequisites + +You need {es} for storing and searching your data, and {kib} for visualizing and managing it. +When setting these components up, you need: + +include::{ingest-docs-root}/docs/en/ingest-management/tab-widgets/prereq.asciidoc[tag=self-managed] + +[float] +== Step 1: Set up Fleet + +Use {fleet} in {kib} to get APM data into the {stack}. +The first time you use {fleet}, you'll need to set it up and add a +{fleet-server}: + +include::{ingest-docs-root}/docs/en/ingest-management/tab-widgets/add-fleet-server/content.asciidoc[tag=self-managed] + +For more information, refer to {fleet-guide}/fleet-server.html[{fleet-server}]. + +[float] +[[add-apm-integration]] +== Step 2: Add and configure the APM integration + +include::{observability-docs-root}/docs/en/observability/tab-widgets/add-apm-integration/content.asciidoc[tag=self-managed] + +**** +An internet connection is required to install the APM integration via the Fleet UI in Kibana. + +-- +include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc[leveloffset=+2,tag=install-apm-integration-no-internet] +-- +**** + +[float] +== Step 3: Install APM agents + +APM agents are written in the same language as your service. +To monitor a new service, you must install the agent and configure it with a service name, +APM Server host, and Secret token. + +* **Service name**: The APM integration maps an instrumented service's name–defined in each {apm-agent}'s configuration– +to the index that its data is stored in {es}. +Service names are case-insensitive and must be unique. +For example, you cannot have a service named `Foo` and another named `foo`. +Special characters will be removed from service names and replaced with underscores (`_`). + +* **APM Server URL**: The host and port that APM Server listens for events on. +This should match the host and port defined when setting up the APM integration. + +* **Secret token**: Authentication method for {apm-agent} and APM Server communication. +This should match the secret token defined when setting up the APM integration. + +TIP: You can edit your APM integration settings if you need to change the APM Server URL +or secret token to match your APM agents. + +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/install-agents-widget.asciidoc[] + +[float] +== Step 4: View your data + +Back in {kib}, under {observability}, select APM. +You should see application performance monitoring data flowing into the {stack}! + +[role="screenshot"] +image::./images/kibana-apm-sample-data.png[APM UI with data] diff --git a/docs/en/observability/apm/getting-started-apm/index.asciidoc b/docs/en/observability/apm/getting-started-apm/index.asciidoc new file mode 100644 index 0000000000..44dca348f9 --- /dev/null +++ b/docs/en/observability/apm/getting-started-apm/index.asciidoc @@ -0,0 +1,154 @@ +[[apm-getting-started-apm-server]] += Get started with APM + +++++ +Get started +++++ + +**** +The easiest way to get started with Elastic APM is by using our +{ess-product}[hosted {es} Service] on {ecloud}. +The {es} Service is available on AWS, GCP, and Azure. +*To get started in minutes, follow the steps in <>.* +**** + +// TODO: MOVE THIS +IMPORTANT: Starting in version 8.0.0, {fleet} uses the APM integration to set up and manage APM index templates, +{ilm-init} policies, and ingest pipelines. APM Server will only send data to {es} _after_ the APM integration has been installed. + +The APM Server receives performance data from your APM agents, +validates and processes it, and then transforms the data into {es} documents. +If you're on this page, then you've chosen to self-manage the Elastic Stack, +and you now must decide how to run and configure the APM Server. +There are two options, and the components required are different for each: + +* **<>** +* **<>** +// * **<>** + +[float] +[[apm-setup-fleet-managed-apm]] +== Fleet-managed APM Server + +Fleet is a web-based UI in {kib} that is used to centrally manage {agent}s. +In this deployment model, use {agent} to spin up APM Server instances that can be centrally-managed in a custom-curated user interface. + +NOTE: Fleet-managed APM Server does not have full feature parity with the APM Server binary method of running Elastic APM. + +image::./images/fm-ov.png[APM Server fleet overview] + +// (outputs, stable APIs) +// not the best option for a simple test setup or if only interested in centrally running APM Server + +[cols="1,3"] +|=== +| *Pros* +a| Conveniently manage one, some, or many different +integrations from one central {fleet} UI. + +| *Supported outputs* +a| * {es} +* {ess} + +| *Required{nbsp}components* +a| * APM agents +* APM Server +* {agent} +* Fleet Server +* {stack} + +| *Configuration method* +| {kib} UI +|=== + +[float] +[[apm-setup-apm-server-binary]] +== APM Server binary + +Install, configure, and run the APM Server binary wherever you need it. + +image::./images/bin-ov.png[APM Server binary overview] + +[cols="1,3"] +|=== +| *Pros* +a| * Simplest self-managed option +* No addition component knowledge required +* YAML configuration simplifies automation + +| *Supported outputs* +a| * {es} +* {ess} +* {ls} +* Kafka +* Redis +* File +* Console + +| *Required components* +a| * APM agents +* APM Server +* {stack} + +| *Configuration method* +a| YAML +|=== + +// [float] +// [[apm-setup-apm-server-ea]] +// === Standalone Elastic Agent-managed APM Server +// // I really don't know how to sell this option +// Instead of installing and configuring the APM Server binary, let {agent} orchestrate it for you. +// Install {agent} and manually configure the agent locally on the system where it's installed. +// You are responsible for managing and upgrading {agent}. This approach is recommended for advanced users only. + +// **Pros**: + +// - Easily add integrations for other data sources +// useful if EA already in place for other integrations, and customers want to customize setup rather than using Fleet for configuration +// // TODO: +// // maybe get some more hints on this one from the EA team to align with highlighting the same pros & cons. + +// **Available on Elastic Cloud**: ❌ + +// This supports all of the same outputs as binary +// see https://github.com/elastic/apm-server/issues/10467 +// **Supported outputs**: + +// **Configuration method**: YAML + +// image::./images/ea-ov.png[APM Server ea overview] + +// @simitt's notes for how to include EA-managed in the decision tree: +// **** +// If we generally describe Standalone Elastic Agent managed APM Server then we should also add it to this diagram: +// Do you want to use other integrations? +// -> yes: Would you like to use the comfort of Fleet UI based management? -> yes: Fleet managed APM Server; -> no: Standalone Elastic Agent managed APM Server +// -> no: What is your prefered way of configuration? -> yaml: APM Server binary; -> Kibana UI: Fleet managed APM Server +// **** + +// Components required: + +// [options="header"] +// |==== +// | Installation method | APM Server | Elastic Agent | Fleet Server +// | APM Server binary | ✔️ | | +// // | Standalone Elastic Agent-managed APM Server | ✔️ | ✔️ | +// | Fleet-managed APM Server | ✔️ | ✔️ | ✔️ +// |==== + +[float] +== Help me decide + +Use the decision tree below to help determine which method of configuring and running the APM Server is best for your use case. + +[subs=attributes+] +include::{observability-docs-root}/docs/en/observability/apm/diagrams/apm-decision-tree.asciidoc[APM Server decision tree] + +//// +Subsections +//// +:leveloffset: +1 +include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm/get-started-with-fleet-apm-server.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc[] +:leveloffset!: diff --git a/docs/en/observability/apm/how-to.asciidoc b/docs/en/observability/apm/how-to.asciidoc deleted file mode 100644 index 266c611ffd..0000000000 --- a/docs/en/observability/apm/how-to.asciidoc +++ /dev/null @@ -1,47 +0,0 @@ -[[apm-how-to-guides]] -== Perform common tasks in the APM UI - -Learn how to perform common tasks in the APM UI: - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -include::../apm-ui/agent-configuration.asciidoc[] - -include::../apm-ui/apm-spaces.asciidoc[] - -include::../apm-ui/apm-alerts.asciidoc[] - -include::./source-map-how-to.asciidoc[] - -include::../apm-ui/custom-links.asciidoc[] - -include::../apm-ui/filters.asciidoc[] - -include::../apm-ui/correlations.asciidoc[] - -include::../apm-ui/agent-explorer.asciidoc[] - -include::../apm-ui/machine-learning.asciidoc[] - -include::../apm-ui/mobile-session-explorer.asciidoc[] - -include::../apm-ui/lambda.asciidoc[] - -include::../apm-ui/advanced-queries.asciidoc[] - -include::../apm-ui/storage-explorer.asciidoc[] - -include::../apm-ui/deployment-annotations.asciidoc[] diff --git a/docs/en/observability/apm-ui/images/active-alert-service.png b/docs/en/observability/apm/images/active-alert-service.png similarity index 100% rename from docs/en/observability/apm-ui/images/active-alert-service.png rename to docs/en/observability/apm/images/active-alert-service.png diff --git a/docs/en/observability/apm-ui/images/add-variable.png b/docs/en/observability/apm/images/add-variable.png similarity index 100% rename from docs/en/observability/apm-ui/images/add-variable.png rename to docs/en/observability/apm/images/add-variable.png diff --git a/docs/en/observability/apm-ui/images/advanced-discover.png b/docs/en/observability/apm/images/advanced-discover.png similarity index 100% rename from docs/en/observability/apm-ui/images/advanced-discover.png rename to docs/en/observability/apm/images/advanced-discover.png diff --git a/docs/en/observability/apm-ui/images/all-instances.png b/docs/en/observability/apm/images/all-instances.png similarity index 100% rename from docs/en/observability/apm-ui/images/all-instances.png rename to docs/en/observability/apm/images/all-instances.png diff --git a/docs/en/observability/apm-ui/images/apm-agent-configuration.png b/docs/en/observability/apm/images/apm-agent-configuration.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-agent-configuration.png rename to docs/en/observability/apm/images/apm-agent-configuration.png diff --git a/docs/en/observability/apm-ui/images/apm-agent-explorer-flyout.png b/docs/en/observability/apm/images/apm-agent-explorer-flyout.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-agent-explorer-flyout.png rename to docs/en/observability/apm/images/apm-agent-explorer-flyout.png diff --git a/docs/en/observability/apm-ui/images/apm-agent-explorer.png b/docs/en/observability/apm/images/apm-agent-explorer.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-agent-explorer.png rename to docs/en/observability/apm/images/apm-agent-explorer.png diff --git a/docs/en/observability/apm-ui/images/apm-alert.png b/docs/en/observability/apm/images/apm-alert.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-alert.png rename to docs/en/observability/apm/images/apm-alert.png diff --git a/docs/en/observability/apm-ui/images/apm-anomaly-alert.png b/docs/en/observability/apm/images/apm-anomaly-alert.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-anomaly-alert.png rename to docs/en/observability/apm/images/apm-anomaly-alert.png diff --git a/docs/en/observability/apm-ui/images/apm-distributed-tracing.png b/docs/en/observability/apm/images/apm-distributed-tracing-apm-ui.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-distributed-tracing.png rename to docs/en/observability/apm/images/apm-distributed-tracing-apm-ui.png diff --git a/docs/en/observability/apm-ui/images/apm-error-group.png b/docs/en/observability/apm/images/apm-error-group.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-error-group.png rename to docs/en/observability/apm/images/apm-error-group.png diff --git a/docs/en/observability/apm-ui/images/apm-errors-overview.png b/docs/en/observability/apm/images/apm-errors-overview.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-errors-overview.png rename to docs/en/observability/apm/images/apm-errors-overview.png diff --git a/docs/en/observability/apm-ui/images/apm-errors-watcher-assistant.png b/docs/en/observability/apm/images/apm-errors-watcher-assistant.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-errors-watcher-assistant.png rename to docs/en/observability/apm/images/apm-errors-watcher-assistant.png diff --git a/docs/en/observability/apm-ui/images/apm-geo-ui.png b/docs/en/observability/apm/images/apm-geo-ui.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-geo-ui.png rename to docs/en/observability/apm/images/apm-geo-ui.png diff --git a/docs/en/observability/apm-ui/images/apm-index-pattern.png b/docs/en/observability/apm/images/apm-index-pattern.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-index-pattern.png rename to docs/en/observability/apm/images/apm-index-pattern.png diff --git a/docs/en/observability/apm-ui/images/apm-integration-config.png b/docs/en/observability/apm/images/apm-integration-config.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-integration-config.png rename to docs/en/observability/apm/images/apm-integration-config.png diff --git a/docs/en/observability/apm-ui/images/apm-logs-tab.png b/docs/en/observability/apm/images/apm-logs-tab.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-logs-tab.png rename to docs/en/observability/apm/images/apm-logs-tab.png diff --git a/docs/en/observability/apm-ui/images/apm-metrics.png b/docs/en/observability/apm/images/apm-metrics.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-metrics.png rename to docs/en/observability/apm/images/apm-metrics.png diff --git a/docs/en/observability/apm-ui/images/apm-ml-integration.png b/docs/en/observability/apm/images/apm-ml-integration.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-ml-integration.png rename to docs/en/observability/apm/images/apm-ml-integration.png diff --git a/docs/en/observability/apm-ui/images/apm-query-bar.png b/docs/en/observability/apm/images/apm-query-bar.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-query-bar.png rename to docs/en/observability/apm/images/apm-query-bar.png diff --git a/docs/en/observability/apm-ui/images/apm-roles-config.png b/docs/en/observability/apm/images/apm-roles-config.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-roles-config.png rename to docs/en/observability/apm/images/apm-roles-config.png diff --git a/docs/en/observability/apm-ui/images/apm-service-group.png b/docs/en/observability/apm/images/apm-service-group.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-service-group.png rename to docs/en/observability/apm/images/apm-service-group.png diff --git a/docs/en/observability/apm-ui/images/apm-service-map-anomaly.png b/docs/en/observability/apm/images/apm-service-map-anomaly.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-service-map-anomaly.png rename to docs/en/observability/apm/images/apm-service-map-anomaly.png diff --git a/docs/en/observability/apm-ui/images/apm-services-overview.png b/docs/en/observability/apm/images/apm-services-overview.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-services-overview.png rename to docs/en/observability/apm/images/apm-services-overview.png diff --git a/docs/en/observability/apm-ui/images/apm-services-trace.png b/docs/en/observability/apm/images/apm-services-trace.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-services-trace.png rename to docs/en/observability/apm/images/apm-services-trace.png diff --git a/docs/en/observability/apm-ui/images/apm-settings.png b/docs/en/observability/apm/images/apm-settings.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-settings.png rename to docs/en/observability/apm/images/apm-settings.png diff --git a/docs/en/observability/apm-ui/images/apm-setup.png b/docs/en/observability/apm/images/apm-setup.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-setup.png rename to docs/en/observability/apm/images/apm-setup.png diff --git a/docs/en/observability/apm-ui/images/apm-span-detail.png b/docs/en/observability/apm/images/apm-span-detail.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-span-detail.png rename to docs/en/observability/apm/images/apm-span-detail.png diff --git a/docs/en/observability/apm-ui/images/apm-traces.png b/docs/en/observability/apm/images/apm-traces.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-traces.png rename to docs/en/observability/apm/images/apm-traces.png diff --git a/docs/en/observability/apm-ui/images/apm-transaction-annotation.png b/docs/en/observability/apm/images/apm-transaction-annotation.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-transaction-annotation.png rename to docs/en/observability/apm/images/apm-transaction-annotation.png diff --git a/docs/en/observability/apm-ui/images/apm-transaction-duration-dist.png b/docs/en/observability/apm/images/apm-transaction-duration-dist.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-transaction-duration-dist.png rename to docs/en/observability/apm/images/apm-transaction-duration-dist.png diff --git a/docs/en/observability/apm-ui/images/apm-transaction-response-dist.png b/docs/en/observability/apm/images/apm-transaction-response-dist.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-transaction-response-dist.png rename to docs/en/observability/apm/images/apm-transaction-response-dist.png diff --git a/docs/en/observability/apm-ui/images/apm-transaction-sample.png b/docs/en/observability/apm/images/apm-transaction-sample.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-transaction-sample.png rename to docs/en/observability/apm/images/apm-transaction-sample.png diff --git a/docs/en/observability/apm-ui/images/apm-transactions-overview.png b/docs/en/observability/apm/images/apm-transactions-overview.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-transactions-overview.png rename to docs/en/observability/apm/images/apm-transactions-overview.png diff --git a/docs/en/observability/apm-ui/images/apm-transactions-table.png b/docs/en/observability/apm/images/apm-transactions-table.png similarity index 100% rename from docs/en/observability/apm-ui/images/apm-transactions-table.png rename to docs/en/observability/apm/images/apm-transactions-table.png diff --git a/docs/en/observability/apm-ui/images/correlations-failed-transactions.png b/docs/en/observability/apm/images/correlations-failed-transactions.png similarity index 100% rename from docs/en/observability/apm-ui/images/correlations-failed-transactions.png rename to docs/en/observability/apm/images/correlations-failed-transactions.png diff --git a/docs/en/observability/apm-ui/images/correlations-hover.png b/docs/en/observability/apm/images/correlations-hover.png similarity index 100% rename from docs/en/observability/apm-ui/images/correlations-hover.png rename to docs/en/observability/apm/images/correlations-hover.png diff --git a/docs/en/observability/apm-ui/images/create-github-issue.png b/docs/en/observability/apm/images/create-github-issue.png similarity index 100% rename from docs/en/observability/apm-ui/images/create-github-issue.png rename to docs/en/observability/apm/images/create-github-issue.png diff --git a/docs/en/observability/apm-ui/images/create-jira-issue.png b/docs/en/observability/apm/images/create-jira-issue.png similarity index 100% rename from docs/en/observability/apm-ui/images/create-jira-issue.png rename to docs/en/observability/apm/images/create-jira-issue.png diff --git a/docs/en/observability/apm-ui/images/dependencies-drilldown.png b/docs/en/observability/apm/images/dependencies-drilldown.png similarity index 100% rename from docs/en/observability/apm-ui/images/dependencies-drilldown.png rename to docs/en/observability/apm/images/dependencies-drilldown.png diff --git a/docs/en/observability/apm-ui/images/dependencies.png b/docs/en/observability/apm/images/dependencies.png similarity index 100% rename from docs/en/observability/apm-ui/images/dependencies.png rename to docs/en/observability/apm/images/dependencies.png diff --git a/docs/en/observability/apm/images/diagram-of-a-trace.png b/docs/en/observability/apm/images/diagram-of-a-trace.png new file mode 100644 index 0000000000000000000000000000000000000000..a80dd9d0fb9098d1dbacdabfc16ae761411bf3a8 GIT binary patch literal 80569 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 literal 0 HcmV?d00001 diff --git a/docs/en/observability/apm/images/distributed-traces.png b/docs/en/observability/apm/images/distributed-traces.png new file mode 100644 index 0000000000000000000000000000000000000000..14c32a7e008e0594e9dc7ad40911d2c9da93d8ab GIT binary patch literal 114882 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 literal 0 HcmV?d00001 diff --git a/docs/en/observability/apm-ui/images/dynamic-config.svg b/docs/en/observability/apm/images/dynamic-config.svg similarity index 100% rename from docs/en/observability/apm-ui/images/dynamic-config.svg rename to docs/en/observability/apm/images/dynamic-config.svg diff --git a/docs/en/observability/apm-ui/images/error-rate.png b/docs/en/observability/apm/images/error-rate.png similarity index 100% rename from docs/en/observability/apm-ui/images/error-rate.png rename to docs/en/observability/apm/images/error-rate.png diff --git a/docs/en/observability/apm-ui/images/example-metadata.png b/docs/en/observability/apm/images/example-metadata.png similarity index 100% rename from docs/en/observability/apm-ui/images/example-metadata.png rename to docs/en/observability/apm/images/example-metadata.png diff --git a/docs/en/observability/apm-ui/images/global-filters.png b/docs/en/observability/apm/images/global-filters.png similarity index 100% rename from docs/en/observability/apm-ui/images/global-filters.png rename to docs/en/observability/apm/images/global-filters.png diff --git a/docs/en/observability/apm-ui/images/green-service.png b/docs/en/observability/apm/images/green-service.png similarity index 100% rename from docs/en/observability/apm-ui/images/green-service.png rename to docs/en/observability/apm/images/green-service.png diff --git a/docs/en/observability/apm-ui/images/infra.png b/docs/en/observability/apm/images/infra.png similarity index 100% rename from docs/en/observability/apm-ui/images/infra.png rename to docs/en/observability/apm/images/infra.png diff --git a/docs/en/observability/apm-ui/images/jvm-metrics-overview.png b/docs/en/observability/apm/images/jvm-metrics-overview.png similarity index 100% rename from docs/en/observability/apm-ui/images/jvm-metrics-overview.png rename to docs/en/observability/apm/images/jvm-metrics-overview.png diff --git a/docs/en/observability/apm-ui/images/jvm-metrics.png b/docs/en/observability/apm/images/jvm-metrics.png similarity index 100% rename from docs/en/observability/apm-ui/images/jvm-metrics.png rename to docs/en/observability/apm/images/jvm-metrics.png diff --git a/docs/en/observability/apm-ui/images/lambda-cold-start-trace.png b/docs/en/observability/apm/images/lambda-cold-start-trace.png similarity index 100% rename from docs/en/observability/apm-ui/images/lambda-cold-start-trace.png rename to docs/en/observability/apm/images/lambda-cold-start-trace.png diff --git a/docs/en/observability/apm-ui/images/lambda-correlations.png b/docs/en/observability/apm/images/lambda-correlations.png similarity index 100% rename from docs/en/observability/apm-ui/images/lambda-correlations.png rename to docs/en/observability/apm/images/lambda-correlations.png diff --git a/docs/en/observability/apm-ui/images/lambda-overview.png b/docs/en/observability/apm/images/lambda-overview.png similarity index 100% rename from docs/en/observability/apm-ui/images/lambda-overview.png rename to docs/en/observability/apm/images/lambda-overview.png diff --git a/docs/en/observability/apm-ui/images/latency.png b/docs/en/observability/apm/images/latency.png similarity index 100% rename from docs/en/observability/apm-ui/images/latency.png rename to docs/en/observability/apm/images/latency.png diff --git a/docs/en/observability/apm-ui/images/local-filter.png b/docs/en/observability/apm/images/local-filter.png similarity index 100% rename from docs/en/observability/apm-ui/images/local-filter.png rename to docs/en/observability/apm/images/local-filter.png diff --git a/docs/en/observability/apm-ui/images/logs.png b/docs/en/observability/apm/images/logs.png similarity index 100% rename from docs/en/observability/apm-ui/images/logs.png rename to docs/en/observability/apm/images/logs.png diff --git a/docs/en/observability/apm-ui/images/metadata-icons.png b/docs/en/observability/apm/images/metadata-icons.png similarity index 100% rename from docs/en/observability/apm-ui/images/metadata-icons.png rename to docs/en/observability/apm/images/metadata-icons.png diff --git a/docs/en/observability/apm-ui/images/mobile-location.png b/docs/en/observability/apm/images/mobile-location.png similarity index 100% rename from docs/en/observability/apm-ui/images/mobile-location.png rename to docs/en/observability/apm/images/mobile-location.png diff --git a/docs/en/observability/apm-ui/images/mobile-most-used.png b/docs/en/observability/apm/images/mobile-most-used.png similarity index 100% rename from docs/en/observability/apm-ui/images/mobile-most-used.png rename to docs/en/observability/apm/images/mobile-most-used.png diff --git a/docs/en/observability/apm-ui/images/mobile-session-error-details.png b/docs/en/observability/apm/images/mobile-session-error-details.png similarity index 100% rename from docs/en/observability/apm-ui/images/mobile-session-error-details.png rename to docs/en/observability/apm/images/mobile-session-error-details.png diff --git a/docs/en/observability/apm-ui/images/mobile-session-explorer-apm.png b/docs/en/observability/apm/images/mobile-session-explorer-apm.png similarity index 100% rename from docs/en/observability/apm-ui/images/mobile-session-explorer-apm.png rename to docs/en/observability/apm/images/mobile-session-explorer-apm.png diff --git a/docs/en/observability/apm-ui/images/mobile-session-explorer-nav.png b/docs/en/observability/apm/images/mobile-session-explorer-nav.png similarity index 100% rename from docs/en/observability/apm-ui/images/mobile-session-explorer-nav.png rename to docs/en/observability/apm/images/mobile-session-explorer-nav.png diff --git a/docs/en/observability/apm-ui/images/mobile-session-filter-discover.png b/docs/en/observability/apm/images/mobile-session-filter-discover.png similarity index 100% rename from docs/en/observability/apm-ui/images/mobile-session-filter-discover.png rename to docs/en/observability/apm/images/mobile-session-filter-discover.png diff --git a/docs/en/observability/apm-ui/images/mobile-tp.png b/docs/en/observability/apm/images/mobile-tp.png similarity index 100% rename from docs/en/observability/apm-ui/images/mobile-tp.png rename to docs/en/observability/apm/images/mobile-tp.png diff --git a/docs/en/observability/apm-ui/images/operations-detail.png b/docs/en/observability/apm/images/operations-detail.png similarity index 100% rename from docs/en/observability/apm-ui/images/operations-detail.png rename to docs/en/observability/apm/images/operations-detail.png diff --git a/docs/en/observability/apm-ui/images/operations.png b/docs/en/observability/apm/images/operations.png similarity index 100% rename from docs/en/observability/apm-ui/images/operations.png rename to docs/en/observability/apm/images/operations.png diff --git a/docs/en/observability/apm-ui/images/red-service.png b/docs/en/observability/apm/images/red-service.png similarity index 100% rename from docs/en/observability/apm-ui/images/red-service.png rename to docs/en/observability/apm/images/red-service.png diff --git a/docs/en/observability/apm-ui/images/service-maps-java.png b/docs/en/observability/apm/images/service-maps-java.png similarity index 100% rename from docs/en/observability/apm-ui/images/service-maps-java.png rename to docs/en/observability/apm/images/service-maps-java.png diff --git a/docs/en/observability/apm-ui/images/service-maps.png b/docs/en/observability/apm/images/service-maps.png similarity index 100% rename from docs/en/observability/apm-ui/images/service-maps.png rename to docs/en/observability/apm/images/service-maps.png diff --git a/docs/en/observability/apm-ui/images/service-quick-health.png b/docs/en/observability/apm/images/service-quick-health.png similarity index 100% rename from docs/en/observability/apm-ui/images/service-quick-health.png rename to docs/en/observability/apm/images/service-quick-health.png diff --git a/docs/en/observability/apm-ui/images/spans-dependencies.png b/docs/en/observability/apm/images/spans-dependencies.png similarity index 100% rename from docs/en/observability/apm-ui/images/spans-dependencies.png rename to docs/en/observability/apm/images/spans-dependencies.png diff --git a/docs/en/observability/apm/images/spans-transactions-and-traces.png b/docs/en/observability/apm/images/spans-transactions-and-traces.png new file mode 100644 index 0000000000000000000000000000000000000000..06badc4454ae7fa04f6dff9425970354aab9856e GIT binary patch literal 91061 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�+aD8rA2SvyK{kp@vw|#< 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 guide to get started. \ No newline at end of file diff --git a/docs/en/observability/apm/manage-storage.asciidoc b/docs/en/observability/apm/manage-storage.asciidoc deleted file mode 100644 index f2817b1732..0000000000 --- a/docs/en/observability/apm/manage-storage.asciidoc +++ /dev/null @@ -1,216 +0,0 @@ -[[apm-manage-storage]] -== Manage storage - -{agent} uses <> to store time series data across multiple indices. -<> are used to configure the backing indices of data streams as they are created. -Each data stream ships with a customizable <> that automates data retention as your indices grow and age. -Use <> to process and enrich APM documents before indexing them. - -The <> attempts to define a "typical" storage reference for Elastic APM, -and there are additional settings you can tweak to <>, -or to <>. - -In addition, the APM UI makes it easy to visualize your APM data usage with -<>. -Storage explorer allows you to analyze the storage footprint of each of your services to see -which are producing large amounts of data--so you can better reduce the data you're collecting -or forecast and prepare for future storage needs. - -include::./data-streams.asciidoc[] - -include::./ilm-how-to.asciidoc[] - -include::./custom-index-template.asciidoc[] - -include::./ingest-pipelines.asciidoc[] - -[[apm-storage-guide]] -=== Storage and sizing guide - -APM processing and storage costs are largely dominated by transactions, spans, and stack frames. - -* <> describe an event captured by an Elastic {apm-agent} instrumenting a service. -They are the highest level of work being measuring within a service. -* <> belong to transactions. They measure from the start to end of an activity, -and contain information about a specific code path that has been executed. -* *Stack frames* belong to spans. Stack frames represent a function call on the call stack, -and include attributes like function name, file name and path, line number, etc. -Stack frames can heavily influence the size of a span. - -[float] -==== Typical transactions - -Due to the high variability of APM data, it's difficult to classify a transaction as typical. -Regardless, this guide will attempt to classify Transactions as _Small_, _Medium_, or _Large_, -and make recommendations based on those classifications. - -The size of a transaction depends on the language, agent settings, and what services the agent instruments. -For instance, an agent auto-instrumenting a service with a popular tech stack -(web framework, database, caching library, etc.) is more likely to generate bigger transactions. - -In addition, all agents support manual instrumentation. -How little or much you use these APIs will also impact what a typical transaction looks like. - -If your sampling rate is very small, transactions will be the dominate storage cost. - -Here's a speculative reference: - -[options="header"] -|======================================================================= -|Transaction size |Number of Spans |Number of stack frames -|_Small_ |5-10 |5-10 -|_Medium_ |15-20 |15-20 -|_Large_ |30-40 |30-40 -|======================================================================= - -There will always be transaction outliers with hundreds of spans or stack frames, but those are very rare. -Small transactions are the most common. - -[float] -==== Typical storage - -Consider the following typical storage reference. -These numbers do not account for {es} compression. - -* 1 unsampled transaction is **~1 KB** -* 1 span with 10 stack frames is **~4 KB** -* 1 span with 50 stack frames is **~20 KB** -* 1 transaction with 10 spans, each with 10 stack frames is **~50 KB** -* 1 transaction with 25 spans, each with 25 spans is **250-300 KB** -* 100 transactions with 10 spans, each with 10 stack frames, sampled at 90% is **600 KB** - -APM data compresses quite well, so the storage cost in {es} will be considerably less: - -* Indexing 100 unsampled transactions per second for 1 hour results in 360,000 documents. These documents use around **50 MB** of disk space. -* Indexing 10 transactions per second for 1 hour, each transaction with 10 spans, each span with 10 stack frames, results in 396,000 documents. These documents use around **200 MB** of disk space. -* Indexing 25 transactions per second for 1 hour, each transaction with 25 spans, each span with 25 stack frames, results in 2,340,000 documents. These documents use around **1.2 GB** of disk space. - -NOTE: These examples were indexing the same data over and over with minimal variation. Because of that, the compression ratios observed of 80-90% are somewhat optimistic. - -[[apm-reduce-apm-storage]] -=== Reduce storage - -The amount of storage for APM data depends on several factors: -the number of services you are instrumenting, how much traffic the services see, agent and server settings, -and the length of time you store your data. - -Here are some ways you can reduce either the amount of APM data you're ingesting -or the amount of data you're retaining. - -[float] -[[apm-reduce-sample-rate]] -==== Reduce the sample rate - -Distributed tracing can generate a substantial amount of data. -More data can mean higher costs and more noise. -Sampling aims to lower the amount of data ingested and the effort required to analyze that data. - -See <> to learn more. - -[float] -==== Enable span compression - -In some cases, APM agents may collect large amounts of very similar or identical spans in a transaction. -These repeated, similar spans often don't provide added benefit, especially if they are of very short duration. -Span compression takes these similar spans and compresses them into a single span-- -retaining important information but reducing processing and storage overhead. - -See <> to learn more. - -[float] -[[apm-reduce-stacktrace]] -==== Reduce collected stack trace information - -Elastic APM agents collect `stacktrace` information under certain circumstances. -This can be very helpful in identifying issues in your code, -but it also comes with an overhead at collection time and increases the storage usage. - -Stack trace collection settings are managed in each agent. - -[float] -==== Delete data - -You might want to only keep data for a defined time period. -This might mean deleting old documents periodically, -deleting data collected for specific services or customers, -or deleting specific indices. - -Depending on your use case, you can delete data: - -* periodically with <> -* <> -* with the <> - -If you want to delete data for security or privacy reasons, see <>. - -[float] -[[apm-delete-data-with-ilm]] -===== Delete data with {ilm} ({ilm-init}) - -Index lifecycle management enables you to automate how you want to manage your indices over time. -You can base actions on factors such as shard size and performance requirements. -See <> to learn more. - -[float] -[[apm-delete-data-query]] -===== Delete data matching a query - -You can delete all APM documents matching a specific query with the {ref}/docs-delete-by-query.html[Delete By Query API]. -For example, to delete all documents with a given `service.name`, use the following request: - -["source","console"] ----- -POST /.ds-*-apm*/_delete_by_query -{ - "query": { - "term": { - "service.name": { - "value": "old-service-name" - } - } - } -} ----- - -[float] -[[apm-delete-data-in-kibana]] -===== Delete data with {kib} Index Management - -{kib}'s {ref}/index-mgmt.html[Index Management] allows you to manage your cluster's -indices, data streams, index templates, and much more. - -In {kib}, navigate to **Stack Management** > **Index Management** > **Data Streams**. -Select the data streams you want to delete, and click **Delete data streams**. - -[float] -[[apm-update-data]] -==== Update existing data - -You might want to update documents that are already indexed. -For example, if you your service name was set incorrectly. - -To do this, you can use the {ref}/docs-update-by-query.html[Update By Query API]. -To rename a service, send the following request: - -["source","sh"] ------------------------------------------------------------- -POST /.ds-*-apm*/_update_by_query?expand_wildcards=all -{ - "query": { - "term": { - "service.name": { - "value": "current-service-name" - } - } - }, - "script": { - "source": "ctx._source.service.name = 'new-service-name'", - "lang": "painless" - } -} ------------------------------------------------------------- -// CONSOLE - -TIP: Remember to also change the service name in the {apm-agents-ref}/index.html[{apm-agent} configuration]. - -include::{observability-docs-root}/docs/en/observability/apm/exploring-es-data.asciidoc[leveloffset=+2] diff --git a/docs/en/observability/apm/custom-index-template.asciidoc b/docs/en/observability/apm/manage-storage/custom-index-template.asciidoc similarity index 96% rename from docs/en/observability/apm/custom-index-template.asciidoc rename to docs/en/observability/apm/manage-storage/custom-index-template.asciidoc index ff83ae2e3e..51e47e3e93 100644 --- a/docs/en/observability/apm/custom-index-template.asciidoc +++ b/docs/en/observability/apm/manage-storage/custom-index-template.asciidoc @@ -5,7 +5,7 @@ ////////////////////////////////////////////////////////////////////////// [[apm-custom-index-template]] -=== View the {es} index template += View the {es} index template :append-legacy: // tag::index-template-integration[] @@ -20,7 +20,7 @@ Select any of the APM index templates to view their relevant component templates [discrete] [id="index-template-view{append-legacy}"] -=== Edit the {es} index template +== Edit the {es} index template WARNING: Custom index mappings may conflict with the mappings defined by the {es} apm-data plugin and may break the APM integration and APM UI in {kib}. @@ -42,7 +42,7 @@ Add any custom metadata, index settings, or mappings. [discrete] [[apm-custom-index-template-index-settings]] -==== Index settings +=== Index settings In the **Index settings** step, you can specify custom {ref}/index-modules.html#index-modules-settings[index settings]. For example, you could: @@ -76,7 +76,7 @@ Specify the number of replica shards: [discrete] [[apm-custom-index-template-mappings]] -==== Mappings +=== Mappings {ref}/mapping.html[Mapping] is the process of defining how a document, and the fields it contains, are stored and indexed. In the *Mappings* step, you can add custom field mappings. @@ -95,7 +95,7 @@ image::images/custom-index-template-runtime-fields.png[Editing a component templ [discrete] [[apm-custom-index-template-rollover]] -=== Roll over the data stream +== Roll over the data stream Changes to component templates are not applied retroactively to existing indices. For changes to take effect, you must create a new write index for the data stream. diff --git a/docs/en/observability/apm/data-streams.asciidoc b/docs/en/observability/apm/manage-storage/data-streams.asciidoc similarity index 97% rename from docs/en/observability/apm/data-streams.asciidoc rename to docs/en/observability/apm/manage-storage/data-streams.asciidoc index c5389aa4a8..682da3c402 100644 --- a/docs/en/observability/apm/data-streams.asciidoc +++ b/docs/en/observability/apm/manage-storage/data-streams.asciidoc @@ -1,5 +1,5 @@ [[apm-data-streams]] -=== Data streams += Data streams **** {agent} uses data streams to store append-only time series data across multiple indices. @@ -16,7 +16,7 @@ See the {fleet-guide}/data-streams.html[{fleet} and {agent} Guide] to learn more [discrete] [[apm-data-streams-naming-scheme]] -=== Data stream naming scheme +== Data stream naming scheme // tag::data-streams[] APM data follows the `--` naming scheme. @@ -30,7 +30,7 @@ Or, you might create namespaces that correspond to strategic business units with [discrete] [[apm-data-streams-list]] -=== APM data streams +== APM data streams By type, the APM data streams are: @@ -87,7 +87,7 @@ Logs are stored in the following data streams: [discrete] [[apm-data-stream-rerouting]] -=== APM data stream rerouting +== APM data stream rerouting APM supports rerouting APM data to user-defined APM data stream names other than the defaults. This can be achieved by using a {ref}/reroute-processor.html[`reroute` processor] in ingest pipelines to set the data stream dataset or namespace. @@ -116,7 +116,7 @@ For more custom APM ingest pipeline guides, see <> to learn how to create your own data retention policies. diff --git a/docs/en/observability/apm/exploring-es-data.asciidoc b/docs/en/observability/apm/manage-storage/exploring-es-data.asciidoc similarity index 100% rename from docs/en/observability/apm/exploring-es-data.asciidoc rename to docs/en/observability/apm/manage-storage/exploring-es-data.asciidoc diff --git a/docs/en/observability/apm/ilm-how-to.asciidoc b/docs/en/observability/apm/manage-storage/ilm-how-to.asciidoc similarity index 95% rename from docs/en/observability/apm/ilm-how-to.asciidoc rename to docs/en/observability/apm/manage-storage/ilm-how-to.asciidoc index 59d57bcbff..12d54c67d1 100644 --- a/docs/en/observability/apm/ilm-how-to.asciidoc +++ b/docs/en/observability/apm/manage-storage/ilm-how-to.asciidoc @@ -3,7 +3,7 @@ ////////////////////////////////////////////////////////////////////////// [[apm-ilm-how-to]] -=== {ilm-cap} += {ilm-cap} :append-legacy: // tag::ilm-integration[] @@ -17,7 +17,7 @@ See {ref}/index-lifecycle-management.html[{ilm-init}: Manage the index lifecycle [discrete] [id="index-lifecycle-policies-default{append-legacy}"] -=== Default policies +== Default policies The table below describes the default index lifecycle policy applied to each APM data stream. Each policy includes a rollover and delete definition: @@ -132,7 +132,7 @@ This is not considered a breaking change as index management should continually [discrete] [id="apm-data-streams-custom-policy{append-legacy}"] -=== Configure a custom index lifecycle policy +== Configure a custom index lifecycle policy When the APM integration is installed, {fleet} creates a default `*@custom` component template for each data stream. The easiest way to configure a custom index lifecycle policy per data stream is to edit this template. @@ -141,7 +141,7 @@ This tutorial explains how to apply a custom index lifecycle policy to the `trac [discrete] [id="apm-data-streams-custom-one{append-legacy}"] -=== Step 1: View data streams +== Step 1: View data streams The **Data Streams** view in {kib} shows you the data streams, index templates, and index lifecycle policies associated with a given integration. @@ -156,7 +156,7 @@ image::images/data-stream-overview.png[Data streams info] [discrete] [id="apm-data-streams-custom-two{append-legacy}"] -=== Step 2: Create an index lifecycle policy +== Step 2: Create an index lifecycle policy . Navigate to **{stack-manage-app}** > **Index Lifecycle Policies**. . Click **Create policy**. @@ -166,7 +166,7 @@ Customize the policy to your liking, and when you're done, click **Save policy** [discrete] [id="apm-data-streams-custom-three{append-legacy}"] -=== Step 3: Apply the index lifecycle policy +== Step 3: Apply the index lifecycle policy To apply your new index lifecycle policy to the `traces-apm-*` data stream, edit the `@custom` component template. @@ -191,7 +191,7 @@ image::images/create-component-template.png[Create component template] [discrete] [id="apm-data-streams-custom-four{append-legacy}"] -=== Step 4: Roll over the data stream (optional) +== Step 4: Roll over the data stream (optional) To confirm that the data stream is now using the new index template and {ilm-init} policy, you can either repeat <>, or navigate to **{dev-tools-app}** and run the following: @@ -231,7 +231,7 @@ POST /traces-apm-default/_rollover/ [discrete] [id="apm-data-streams-custom-policy-namespace{append-legacy}"] -=== Namespace-level index lifecycle policies +== Namespace-level index lifecycle policies It is also possible to create more granular index lifecycle policies that apply to individual namespaces. This process is similar to the above tutorial, but includes cloning and modify the existing index template to use diff --git a/docs/en/observability/apm/manage-storage/index.asciidoc b/docs/en/observability/apm/manage-storage/index.asciidoc new file mode 100644 index 0000000000..aa73b774d8 --- /dev/null +++ b/docs/en/observability/apm/manage-storage/index.asciidoc @@ -0,0 +1,37 @@ +[[apm-manage-storage]] += Manage storage + +{agent} uses <> to store time series data across multiple indices. +<> are used to configure the backing indices of data streams as they are created. +Each data stream ships with a customizable <> that automates data retention as your indices grow and age. +Use <> to process and enrich APM documents before indexing them. + +The <> attempts to define a "typical" storage reference for Elastic APM, +and there are additional settings you can tweak to <>, +or to <>. + +In addition, the APM UI makes it easy to visualize your APM data usage with +<>. +Storage explorer allows you to analyze the storage footprint of each of your services to see +which are producing large amounts of data--so you can better reduce the data you're collecting +or forecast and prepare for future storage needs. + +:leveloffset: +1 + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/storage-explorer.asciidoc[] + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[] + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/ilm-how-to.asciidoc[] + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/custom-index-template.asciidoc[] + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/ingest-pipelines.asciidoc[] + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/storage-and-sizing.asciidoc[] + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/reduce-apm-storage.asciidoc[] + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/exploring-es-data.asciidoc[] + +:!leveloffset: diff --git a/docs/en/observability/apm/ingest-pipelines.asciidoc b/docs/en/observability/apm/manage-storage/ingest-pipelines.asciidoc similarity index 85% rename from docs/en/observability/apm/ingest-pipelines.asciidoc rename to docs/en/observability/apm/manage-storage/ingest-pipelines.asciidoc index 01353e8258..fdbf6d7b74 100644 --- a/docs/en/observability/apm/ingest-pipelines.asciidoc +++ b/docs/en/observability/apm/manage-storage/ingest-pipelines.asciidoc @@ -3,7 +3,7 @@ ////////////////////////////////////////////////////////////////////////// [[apm-ingest-pipelines]] -=== Parse data using ingest pipelines += Parse data using ingest pipelines :append-legacy: // tag::ingest-pipelines[] @@ -17,7 +17,7 @@ The default APM pipelines are defined in {es} apm-data plugin index templates. [discrete] [id="custom-ingest-pipelines{append-legacy}"] -=== Custom ingest pipelines +== Custom ingest pipelines The Elastic APM integration supports custom ingest pipelines. A custom pipeline allows you to transform data to better match your specific use case. @@ -33,15 +33,15 @@ Sending other APM data to alternate data streams, like traces (`traces-apm.*`), [discrete] [id="custom-ingest-pipeline-naming{append-legacy}"] -=== `@custom` ingest pipeline naming convention +== `@custom` ingest pipeline naming convention // tag::ingest-pipeline-naming[] `@custom` pipelines are specific to each data stream and follow a similar naming convention: `-@custom`. As a reminder, the default APM data streams are: -include::./data-streams.asciidoc[tag=traces-data-streams] -include::./data-streams.asciidoc[tag=metrics-data-streams] -include::./data-streams.asciidoc[tag=logs-data-streams] +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[tag=traces-data-streams] +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[tag=metrics-data-streams] +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/data-streams.asciidoc[tag=logs-data-streams] To match a custom ingest pipeline with a data stream, follow the `-@custom` template, or replace `-namespace` with `@custom` in the table above. @@ -54,7 +54,7 @@ The `@custom` pipeline will persist across all version upgrades. [discrete] [id="custom-ingest-pipeline-create{append-legacy}"] -=== Create a `@custom` ingest pipeline +== Create a `@custom` ingest pipeline The process for creating a custom ingest pipeline is as follows: diff --git a/docs/en/observability/apm/manage-storage/reduce-apm-storage.asciidoc b/docs/en/observability/apm/manage-storage/reduce-apm-storage.asciidoc new file mode 100644 index 0000000000..7b58dd4d14 --- /dev/null +++ b/docs/en/observability/apm/manage-storage/reduce-apm-storage.asciidoc @@ -0,0 +1,125 @@ +[[apm-reduce-apm-storage]] += Reduce storage + +The amount of storage for APM data depends on several factors: +the number of services you are instrumenting, how much traffic the services see, agent and server settings, +and the length of time you store your data. + +Here are some ways you can reduce either the amount of APM data you're ingesting +or the amount of data you're retaining. + +[float] +[[apm-reduce-sample-rate]] +== Reduce the sample rate + +Distributed tracing can generate a substantial amount of data. +More data can mean higher costs and more noise. +Sampling aims to lower the amount of data ingested and the effort required to analyze that data. + +See <> to learn more. + +[float] +== Enable span compression + +In some cases, APM agents may collect large amounts of very similar or identical spans in a transaction. +These repeated, similar spans often don't provide added benefit, especially if they are of very short duration. +Span compression takes these similar spans and compresses them into a single span-- +retaining important information but reducing processing and storage overhead. + +See <> to learn more. + +[float] +[[apm-reduce-stacktrace]] +== Reduce collected stack trace information + +Elastic APM agents collect `stacktrace` information under certain circumstances. +This can be very helpful in identifying issues in your code, +but it also comes with an overhead at collection time and increases the storage usage. + +Stack trace collection settings are managed in each agent. + +[float] +== Delete data + +You might want to only keep data for a defined time period. +This might mean deleting old documents periodically, +deleting data collected for specific services or customers, +or deleting specific indices. + +Depending on your use case, you can delete data: + +* periodically with <> +* <> +* with the <> + +If you want to delete data for security or privacy reasons, see <>. + +[float] +[[apm-delete-data-with-ilm]] +=== Delete data with {ilm} ({ilm-init}) + +Index lifecycle management enables you to automate how you want to manage your indices over time. +You can base actions on factors such as shard size and performance requirements. +See <> to learn more. + +[float] +[[apm-delete-data-query]] +=== Delete data matching a query + +You can delete all APM documents matching a specific query with the {ref}/docs-delete-by-query.html[Delete By Query API]. +For example, to delete all documents with a given `service.name`, use the following request: + +["source","console"] +---- +POST /.ds-*-apm*/_delete_by_query +{ + "query": { + "term": { + "service.name": { + "value": "old-service-name" + } + } + } +} +---- + +[float] +[[apm-delete-data-in-kibana]] +=== Delete data with {kib} Index Management + +{kib}'s {ref}/index-mgmt.html[Index Management] allows you to manage your cluster's +indices, data streams, index templates, and much more. + +In {kib}, navigate to **Stack Management** > **Index Management** > **Data Streams**. +Select the data streams you want to delete, and click **Delete data streams**. + +[float] +[[apm-update-data]] +== Update existing data + +You might want to update documents that are already indexed. +For example, if you your service name was set incorrectly. + +To do this, you can use the {ref}/docs-update-by-query.html[Update By Query API]. +To rename a service, send the following request: + +["source","sh"] +------------------------------------------------------------ +POST /.ds-*-apm*/_update_by_query?expand_wildcards=all +{ + "query": { + "term": { + "service.name": { + "value": "current-service-name" + } + } + }, + "script": { + "source": "ctx._source.service.name = 'new-service-name'", + "lang": "painless" + } +} +------------------------------------------------------------ +// CONSOLE + +TIP: Remember to also change the service name in the {apm-agents-ref}/index.html[{apm-agent} configuration]. diff --git a/docs/en/observability/apm/manage-storage/storage-and-sizing.asciidoc b/docs/en/observability/apm/manage-storage/storage-and-sizing.asciidoc new file mode 100644 index 0000000000..2c550d9b26 --- /dev/null +++ b/docs/en/observability/apm/manage-storage/storage-and-sizing.asciidoc @@ -0,0 +1,62 @@ +[[apm-storage-guide]] += Storage and sizing guide + +APM processing and storage costs are largely dominated by transactions, spans, and stack frames. + +* <> describe an event captured by an Elastic {apm-agent} instrumenting a service. +They are the highest level of work being measuring within a service. +* <> belong to transactions. They measure from the start to end of an activity, +and contain information about a specific code path that has been executed. +* *Stack frames* belong to spans. Stack frames represent a function call on the call stack, +and include attributes like function name, file name and path, line number, etc. +Stack frames can heavily influence the size of a span. + +[float] +== Typical transactions + +Due to the high variability of APM data, it's difficult to classify a transaction as typical. +Regardless, this guide will attempt to classify Transactions as _Small_, _Medium_, or _Large_, +and make recommendations based on those classifications. + +The size of a transaction depends on the language, agent settings, and what services the agent instruments. +For instance, an agent auto-instrumenting a service with a popular tech stack +(web framework, database, caching library, etc.) is more likely to generate bigger transactions. + +In addition, all agents support manual instrumentation. +How little or much you use these APIs will also impact what a typical transaction looks like. + +If your sampling rate is very small, transactions will be the dominate storage cost. + +Here's a speculative reference: + +[options="header"] +|======================================================================= +|Transaction size |Number of Spans |Number of stack frames +|_Small_ |5-10 |5-10 +|_Medium_ |15-20 |15-20 +|_Large_ |30-40 |30-40 +|======================================================================= + +There will always be transaction outliers with hundreds of spans or stack frames, but those are very rare. +Small transactions are the most common. + +[float] +== Typical storage + +Consider the following typical storage reference. +These numbers do not account for {es} compression. + +* 1 unsampled transaction is **~1 KB** +* 1 span with 10 stack frames is **~4 KB** +* 1 span with 50 stack frames is **~20 KB** +* 1 transaction with 10 spans, each with 10 stack frames is **~50 KB** +* 1 transaction with 25 spans, each with 25 spans is **250-300 KB** +* 100 transactions with 10 spans, each with 10 stack frames, sampled at 90% is **600 KB** + +APM data compresses quite well, so the storage cost in {es} will be considerably less: + +* Indexing 100 unsampled transactions per second for 1 hour results in 360,000 documents. These documents use around **50 MB** of disk space. +* Indexing 10 transactions per second for 1 hour, each transaction with 10 spans, each span with 10 stack frames, results in 396,000 documents. These documents use around **200 MB** of disk space. +* Indexing 25 transactions per second for 1 hour, each transaction with 25 spans, each span with 25 stack frames, results in 2,340,000 documents. These documents use around **1.2 GB** of disk space. + +NOTE: These examples were indexing the same data over and over with minimal variation. Because of that, the compression ratios observed of 80-90% are somewhat optimistic. diff --git a/docs/en/observability/apm-ui/storage-explorer.asciidoc b/docs/en/observability/apm/manage-storage/storage-explorer.asciidoc similarity index 93% rename from docs/en/observability/apm-ui/storage-explorer.asciidoc rename to docs/en/observability/apm/manage-storage/storage-explorer.asciidoc index c43af9f37f..3f4aee8649 100644 --- a/docs/en/observability/apm-ui/storage-explorer.asciidoc +++ b/docs/en/observability/apm/manage-storage/storage-explorer.asciidoc @@ -1,5 +1,5 @@ [[apm-storage-explorer]] -=== Storage Explorer += Storage Explorer Analyze your APM data and manage costs with **storage explorer**. For example, analyze the storage footprint of each of your services to see which are producing @@ -11,7 +11,7 @@ and prepare for future storage needs. image::./images/storage-explorer-overview.png[APM Storage Explorer] [float] -==== Index lifecycle phases +== Index lifecycle phases A default {apm-guide-ref}/ilm-how-to.html[index lifecycle policy] is applied to each APM data stream, but can be customized depending on your business needs. @@ -27,13 +27,13 @@ See {apm-guide-ref}/ilm-how-to.html[Index lifecycle management] to learn more ab the default APM index lifecycle policies. [float] -==== Service size chart +== Service size chart The service size chart displays the estimated size of each service over time. Expand the time filter to visualize data trends and estimate daily data generation. [float] -==== Service statistics table +== Service statistics table The service statistics table provides detailed information on each service: @@ -54,19 +54,19 @@ As you explore your service statistics, you might want to take action to reduce documents and therefore storage size of a particular service. [float] -===== Reduce the number of transactions +=== Reduce the number of transactions To reduce the number of transactions a service generates, configure a more aggressive {apm-guide-ref}/sampling.html[transaction sampling policy]. Transaction sampling lowers the amount of data ingested without negatively impacting the usefulness of your data. [float] -===== Reduce the number of spans +=== Reduce the number of spans To reduce the number of spans a service generates, enable {apm-guide-ref}/span-compression.html[span compression]. Span compression saves on data and transfer costs by compressing multiple, similar spans into a single span. [float] -===== Reduce the number of metrics +=== Reduce the number of metrics To reduce the number of system, runtime, and application metrics, tune the APM agent or agents that are collecting the data. You can disable the collection of specific metrics with the **disable metrics** configuration. @@ -75,17 +75,17 @@ Most APM agents support both options. See the relevant {apm-agents-ref}[APM agent configuration options] for more details. [float] -===== Reduce the number of errors +=== Reduce the number of errors To reduce the number of errors a service generate, work with your developers to change how exceptions are handled in your code. [float] -==== Privileges +== Privileges Storage Explorer requires expanded privileges to view. See <> for more information. [float] -==== Limitations +== Limitations Multi-cluster deployments are not supported. diff --git a/docs/en/observability/apm-ui/mobile-errors.asciidoc b/docs/en/observability/apm/mobile-errors.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/mobile-errors.asciidoc rename to docs/en/observability/apm/mobile-errors.asciidoc diff --git a/docs/en/observability/apm/monitor-apm-server.asciidoc b/docs/en/observability/apm/monitor-apm-server/index.asciidoc similarity index 79% rename from docs/en/observability/apm/monitor-apm-server.asciidoc rename to docs/en/observability/apm/monitor-apm-server/index.asciidoc index c882045b81..96072311da 100644 --- a/docs/en/observability/apm/monitor-apm-server.asciidoc +++ b/docs/en/observability/apm/monitor-apm-server/index.asciidoc @@ -1,9 +1,5 @@ [[apm-monitor-apm]] -== Monitor APM Server - -++++ -Monitor -++++ += Monitor APM Server Use the {stack} {monitor-features} to gain insight into the real-time health and performance of APM Server. Stack monitoring exposes key metrics, like intake response count, intake error rate, output event rate, @@ -17,7 +13,7 @@ Select your deployment method to get started: [float] [[apm-monitor-apm-cloud]] -=== {ecloud} +== {ecloud} {ecloud} manages the installation and configuration of a monitoring agent for you -- so all you have to do is flip a switch and watch the data pour in. @@ -25,7 +21,13 @@ all you have to do is flip a switch and watch the data pour in. * **{ess}** user? See {cloud}/ec-enable-logging-and-monitoring.html[ESS: Enable logging and monitoring]. * **{ece}** user? See {ece-ref}/ece-enable-logging-and-monitoring.html[ECE: Enable logging and monitoring]. +//// +Subsections +//// + +:leveloffset: +1 -include::./monitor.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/monitor-apm-server/monitor.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/monitor-apm-server/monitoring-beats.asciidoc[] -include::{observability-docs-root}/docs/en/observability/apm/monitoring/monitoring-beats.asciidoc[leveloffset=+2] +:!leveloffset: diff --git a/docs/en/observability/apm/monitor.asciidoc b/docs/en/observability/apm/monitor-apm-server/monitor.asciidoc similarity index 97% rename from docs/en/observability/apm/monitor.asciidoc rename to docs/en/observability/apm/monitor-apm-server/monitor.asciidoc index 291378d40c..1fb279d92d 100644 --- a/docs/en/observability/apm/monitor.asciidoc +++ b/docs/en/observability/apm/monitor-apm-server/monitor.asciidoc @@ -1,5 +1,5 @@ [[apm-monitor-apm-self-install]] -=== Monitor a Fleet-managed APM Server += Monitor a Fleet-managed APM Server ++++ Fleet-managed @@ -15,7 +15,7 @@ To collect and ship monitoring data: [float] [[apm-configure-ea-monitoring-data]] -==== Configure {agent} to send monitoring data +== Configure {agent} to send monitoring data **** Before you can monitor APM, @@ -52,7 +52,7 @@ See the {fleet-guide}/elastic-agent-cmd-options.html[{agent} command reference] [float] [[apm-install-config-metricbeat]] -==== Install and configure {metricbeat} to collect monitoring data +== Install and configure {metricbeat} to collect monitoring data . Install {metricbeat} on the same server as {agent}. To learn how, see {metricbeat-ref}/metricbeat-installation-configuration.html[Get started with {metricbeat}]. diff --git a/docs/en/observability/apm/monitoring/monitoring-beats.asciidoc b/docs/en/observability/apm/monitor-apm-server/monitoring-beats.asciidoc similarity index 94% rename from docs/en/observability/apm/monitoring/monitoring-beats.asciidoc rename to docs/en/observability/apm/monitor-apm-server/monitoring-beats.asciidoc index 75a021290b..7c91c3da17 100644 --- a/docs/en/observability/apm/monitoring/monitoring-beats.asciidoc +++ b/docs/en/observability/apm/monitor-apm-server/monitoring-beats.asciidoc @@ -20,9 +20,14 @@ select monitoring data directly to the standard indices of your monitoring cluster. endif::[] +//// +Subsections +//// + +:leveloffset: +1 + include::monitoring-internal-collection.asciidoc[] +include::monitoring-metricbeat.asciidoc[] include::monitoring-local-collection.asciidoc[] -ifndef::serverless[] -include::monitoring-metricbeat.asciidoc[] -endif::[] \ No newline at end of file +:!leveloffset: diff --git a/docs/en/observability/apm/monitoring/monitoring-internal-collection.asciidoc b/docs/en/observability/apm/monitor-apm-server/monitoring-internal-collection.asciidoc similarity index 98% rename from docs/en/observability/apm/monitoring/monitoring-internal-collection.asciidoc rename to docs/en/observability/apm/monitor-apm-server/monitoring-internal-collection.asciidoc index dc2d3dc156..3506339740 100644 --- a/docs/en/observability/apm/monitoring/monitoring-internal-collection.asciidoc +++ b/docs/en/observability/apm/monitor-apm-server/monitoring-internal-collection.asciidoc @@ -1,5 +1,5 @@ [[apm-monitoring-internal-collection]] -== Use internal collection to send monitoring data += Use internal collection to send monitoring data ++++ Use internal collection ++++ diff --git a/docs/en/observability/apm/monitoring/monitoring-local-collection.asciidoc b/docs/en/observability/apm/monitor-apm-server/monitoring-local-collection.asciidoc similarity index 99% rename from docs/en/observability/apm/monitoring/monitoring-local-collection.asciidoc rename to docs/en/observability/apm/monitor-apm-server/monitoring-local-collection.asciidoc index e6522f3bc7..572ef23afb 100644 --- a/docs/en/observability/apm/monitoring/monitoring-local-collection.asciidoc +++ b/docs/en/observability/apm/monitor-apm-server/monitoring-local-collection.asciidoc @@ -1,5 +1,6 @@ [[apm-monitoring-local-collection]] = Use the select metrics emitted directly to your monitoring cluster + ++++ Use local collection ++++ diff --git a/docs/en/observability/apm/monitoring/monitoring-metricbeat.asciidoc b/docs/en/observability/apm/monitor-apm-server/monitoring-metricbeat.asciidoc similarity index 98% rename from docs/en/observability/apm/monitoring/monitoring-metricbeat.asciidoc rename to docs/en/observability/apm/monitor-apm-server/monitoring-metricbeat.asciidoc index 60a666dc6a..d976c8e725 100644 --- a/docs/en/observability/apm/monitoring/monitoring-metricbeat.asciidoc +++ b/docs/en/observability/apm/monitor-apm-server/monitoring-metricbeat.asciidoc @@ -1,5 +1,6 @@ [[apm-monitoring-metricbeat-collection]] -== Use {metricbeat} to send monitoring data += Use {metricbeat} to send monitoring data + [subs="attributes"] ++++ Use {metricbeat} collection @@ -25,7 +26,7 @@ To collect and ship monitoring data: [float] [[apm-configure-shipper]] -=== Configure the shipper you want to monitor +== Configure the shipper you want to monitor . Enable the HTTP endpoint to allow external collection of monitoring data: + @@ -99,7 +100,7 @@ endif::[] [float] [[apm-configure-metricbeat]] -=== Install and configure {metricbeat} to collect monitoring data +== Install and configure {metricbeat} to collect monitoring data . Install {metricbeat} on the same server as APM Server. To learn how, see {metricbeat-ref}/metricbeat-installation-configuration.html[Get started with {metricbeat}]. diff --git a/docs/en/observability/apm/monitoring/shared-monitor-config.asciidoc b/docs/en/observability/apm/monitor-apm-server/shared-monitor-config.asciidoc similarity index 100% rename from docs/en/observability/apm/monitoring/shared-monitor-config.asciidoc rename to docs/en/observability/apm/monitor-apm-server/shared-monitor-config.asciidoc diff --git a/docs/en/observability/apm/repositories.asciidoc b/docs/en/observability/apm/repositories.asciidoc index 56b61a6331..3cc4c4c556 100644 --- a/docs/en/observability/apm/repositories.asciidoc +++ b/docs/en/observability/apm/repositories.asciidoc @@ -1,5 +1,6 @@ +[float] [[apm-setup-repositories]] -==== Repositories for APT and YUM += Repositories for APT and YUM We have repositories available for APT and YUM-based distributions. Note that we provide binary packages, but no source packages. @@ -12,7 +13,7 @@ We use the PGP key https://pgp.mit.edu/pks/lookup?op=vindex&search=0xD27D666CD88 to sign all our packages. It is available from https://pgp.mit.edu. [float] -===== APT +== APT ifeval::["{release-state}"=="unreleased"] @@ -92,7 +93,7 @@ sudo systemctl enable apm-server endif::[] [float] -===== YUM +== YUM ifeval::["{release-state}"=="unreleased"] diff --git a/docs/en/observability/apm/secure-comms.asciidoc b/docs/en/observability/apm/secure-comms.asciidoc deleted file mode 100644 index 65b03d9543..0000000000 --- a/docs/en/observability/apm/secure-comms.asciidoc +++ /dev/null @@ -1,23 +0,0 @@ -[[apm-securing-apm-server]] -== Secure communication with the {stack} - -++++ -Secure communication -++++ - -The following topics provide information about securing the APM Server -process and connecting securely to APM agents and the {stack}. - -* <> -* <> -* <> - -:leveloffset: +1 -include::secure-agent-communication.asciidoc[] - -// APM privileges -include::{observability-docs-root}/docs/en/observability/apm/feature-roles.asciidoc[] - -// APM API keys -include::{observability-docs-root}/docs/en/observability/apm/access-api-keys.asciidoc[] -:leveloffset: -1 \ No newline at end of file diff --git a/docs/en/observability/apm/anonymous-auth.asciidoc b/docs/en/observability/apm/security/apm-agents/anonymous-auth.asciidoc similarity index 93% rename from docs/en/observability/apm/anonymous-auth.asciidoc rename to docs/en/observability/apm/security/apm-agents/anonymous-auth.asciidoc index 59fb8a9007..903514ffe8 100644 --- a/docs/en/observability/apm/anonymous-auth.asciidoc +++ b/docs/en/observability/apm/security/apm-agents/anonymous-auth.asciidoc @@ -1,5 +1,5 @@ [[apm-anonymous-auth]] -=== Anonymous authentication += Anonymous authentication Elastic APM agents can send unauthenticated (anonymous) events to the APM Server. An event is considered to be anonymous if no authentication token can be extracted from the incoming request. @@ -22,7 +22,7 @@ ingestion of unauthenticated client-side APM data while still requiring authenti [float] [[apm-anonymous-auth-config]] -=== Configuring anonymous auth for client-side services +== Configuring anonymous auth for client-side services [NOTE] ==== @@ -34,7 +34,7 @@ include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/anonymo [float] [[apm-derive-client-ip]] -=== Deriving an incoming request's `client.ip` address +== Deriving an incoming request's `client.ip` address The remote IP address of an incoming request might be different from the end-user's actual IP address, for example, because of a proxy. For this reason, @@ -49,7 +49,7 @@ If none of these headers are present, the remote address for the incoming reques [float] [[apm-derive-client-ip-concerns]] -==== Using a reverse proxy or load balancer +=== Using a reverse proxy or load balancer HTTP headers are easily modified; it's possible for anyone to spoof the derived `client.ip` value by changing or setting, diff --git a/docs/en/observability/apm/api-keys.asciidoc b/docs/en/observability/apm/security/apm-agents/api-keys.asciidoc similarity index 95% rename from docs/en/observability/apm/api-keys.asciidoc rename to docs/en/observability/apm/security/apm-agents/api-keys.asciidoc index 937f2c1179..035cd0c4c7 100644 --- a/docs/en/observability/apm/api-keys.asciidoc +++ b/docs/en/observability/apm/security/apm-agents/api-keys.asciidoc @@ -1,5 +1,5 @@ [[apm-api-key]] -=== API keys += API keys IMPORTANT: API keys are sent as plain-text, so they only provide security when used in combination with <>. @@ -22,15 +22,15 @@ make sure <> is enabled, then complete these steps: . <> . <> -[[apm-enable-api-key]] [float] -=== Enable API keys +[[apm-enable-api-key]] +== Enable API keys include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/api-key-widget.asciidoc[] -[[apm-create-api-key-user]] [float] -=== Create an API key user in {kib} +[[apm-create-api-key-user]] +== Create an API key user in {kib} API keys can only have the same or lower access rights than the user that creates them. Instead of using a superuser account to create API keys, you can create a role with the minimum required @@ -70,9 +70,9 @@ POST /_security/role/apm_agent_key_role Assign the newly created `apm_agent_key_role` role to any user that wishes to create {apm-agent} API keys. -[[apm-create-an-api-key]] [float] -=== Create an API key in the APM UI +[[apm-create-an-api-key]] +== Create an API key in the APM UI The APM UI has a built-in workflow that you can use to easily create and view {apm-agent} API keys. Only API keys created in the APM UI will show up here. @@ -91,9 +91,9 @@ You will need this for the next step, and you will not be able to view it again. [role="screenshot"] image::images/apm-ui-api-key.png[APM UI API key] -[[apm-agent-api-key]] [float] -=== Set the API key in your APM agents +[[apm-agent-api-key]] +== Set the API key in your APM agents You can now apply your newly created API keys in the configuration of each of your APM agents. See the relevant agent documentation for additional information: @@ -109,18 +109,18 @@ See the relevant agent documentation for additional information: * *Python agent*: {apm-py-ref}/configuration.html#config-api-key[`api_key`] * *Ruby agent*: {apm-ruby-ref}/configuration.html#config-api-key[`api_key`] -[[apm-configure-api-key-alternative]] [float] -=== Alternate API key creation methods +[[apm-configure-api-key-alternative]] +== Alternate API key creation methods API keys can also be created and validated outside of {kib}: * <> * <> -[[apm-create-api-key-workflow-apm-server]] [float] -==== APM Server API key workflow +[[apm-create-api-key-workflow-apm-server]] +=== APM Server API key workflow This API creation method only works with the APM Server binary. @@ -129,15 +129,15 @@ deprecated::[8.6.0, Users should create API Keys through {kib} or the {es} REST APM Server provides a command line interface for creating, retrieving, invalidating, and verifying API keys. Keys created using this method can only be used for communication with APM Server. -[[apm-create-api-key-subcommands]] [float] -===== `apikey` subcommands +[[apm-create-api-key-subcommands]] +==== `apikey` subcommands -include::{observability-docs-root}/docs/en/observability/apm/command-reference.asciidoc[tag=apikey-subcommands] +include::{observability-docs-root}/docs/en/observability/apm/configure/advanced-setup/command-reference.asciidoc[tag=apikey-subcommands] -[[apm-create-api-key-privileges]] [float] -===== Privileges +[[apm-create-api-key-privileges]] +==== Privileges If privileges are not specified at creation time, the created key will have all privileges. @@ -145,9 +145,9 @@ If privileges are not specified at creation time, the created key will have all * `--ingest` grants the `event:write` privilege * `--sourcemap` grants the `sourcemap:write` privilege -[[apm-create-api-key-workflow]] [float] -===== Create an API key +[[apm-create-api-key-workflow]] +==== Create an API key Create an API key with the `create` subcommand. @@ -208,9 +208,9 @@ Error count ........ 0 A full list of `apikey` subcommands and flags is available in the <>. -[[apm-create-api-key-workflow-es]] [float] -==== {es} API key workflow +[[apm-create-api-key-workflow-es]] +=== {es} API key workflow It is also possible to create API keys using the {es} {ref}/security-api-create-api-key.html[create API key API]. diff --git a/docs/en/observability/apm/secure-agent-communication.asciidoc b/docs/en/observability/apm/security/apm-agents/index.asciidoc similarity index 90% rename from docs/en/observability/apm/secure-agent-communication.asciidoc rename to docs/en/observability/apm/security/apm-agents/index.asciidoc index 2e34ab600b..c47dfd5e17 100644 --- a/docs/en/observability/apm/secure-agent-communication.asciidoc +++ b/docs/en/observability/apm/security/apm-agents/index.asciidoc @@ -1,9 +1,5 @@ [[apm-secure-agent-communication]] -== Secure communication with APM agents - -++++ -With APM agents -++++ += Secure communication with APM agents Communication between APM agents and {agent} can be both encrypted and authenticated. It is strongly recommended to use both TLS encryption and authentication as secrets are sent as plain text. @@ -19,10 +15,11 @@ If both API keys and a secret token are enabled, APM agents can choose whichever In some use-cases, like when an {apm-agent} is running on the client side, authentication is not possible. See <> for more information. -include::./tls-comms.asciidoc[] +:leveloffset: +1 +include::./tls-comms.asciidoc[] include::./api-keys.asciidoc[] - include::./secret-token.asciidoc[] - include::./anonymous-auth.asciidoc[] + +:!leveloffset: diff --git a/docs/en/observability/apm/secret-token.asciidoc b/docs/en/observability/apm/security/apm-agents/secret-token.asciidoc similarity index 96% rename from docs/en/observability/apm/secret-token.asciidoc rename to docs/en/observability/apm/security/apm-agents/secret-token.asciidoc index 1ac8993a1e..62fd4a5c41 100644 --- a/docs/en/observability/apm/secret-token.asciidoc +++ b/docs/en/observability/apm/security/apm-agents/secret-token.asciidoc @@ -1,5 +1,5 @@ [[apm-secret-token]] -=== Secret token += Secret token IMPORTANT: Secret tokens are sent as plain-text, so they only provide security when used in combination with <>. @@ -18,7 +18,7 @@ as there is no way to prevent them from being publicly exposed. [float] [[apm-create-secret-token]] -=== Create a secret token +== Create a secret token // lint ignore fleet NOTE: {ess} and {ece} deployments provision a secret token when the deployment is created. @@ -28,7 +28,7 @@ include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/secret- [[apm-configure-secret-token]] [float] -=== Configure the secret token in your APM agents +== Configure the secret token in your APM agents Each Elastic {apm-agent} has a configuration option to set the value of the secret token: diff --git a/docs/en/observability/apm/tls-comms.asciidoc b/docs/en/observability/apm/security/apm-agents/tls-comms.asciidoc similarity index 93% rename from docs/en/observability/apm/tls-comms.asciidoc rename to docs/en/observability/apm/security/apm-agents/tls-comms.asciidoc index fbcbd16e51..16c111695b 100644 --- a/docs/en/observability/apm/tls-comms.asciidoc +++ b/docs/en/observability/apm/security/apm-agents/tls-comms.asciidoc @@ -1,5 +1,5 @@ [[apm-agent-tls]] -=== {apm-agent} TLS communication += {apm-agent} TLS communication TLS is disabled by default. When TLS is enabled for APM Server inbound communication, agents will verify the identity @@ -11,11 +11,11 @@ or be <>. [float] [[apm-agent-self-sign]] -=== Use a self-signed certificate +== Use a self-signed certificate [float] [[apm-agent-self-sign-1]] -==== Step 1: Create a self-signed certificate +=== Step 1: Create a self-signed certificate The {es} distribution offers the `certutil` tool for the creation of self-signed certificates: @@ -28,7 +28,7 @@ location of the output zip archive containing the certificate and the private ke [float] [[apm-agent-self-sign-2]] -==== Step 2: Configure the APM Server +=== Step 2: Configure the APM Server Enable TLS and configure the APM Server to point to the extracted certificate and key: @@ -36,7 +36,7 @@ include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/tls-wid [float] [[apm-agent-self-sign-3]] -==== Step 3: Configure APM agents +=== Step 3: Configure APM agents When the APM server uses a certificate that is not chained to a publicly-trusted certificate (e.g. self-signed), additional configuration is required in the {apm-agent}: @@ -61,7 +61,7 @@ We do not recommend disabling {apm-agent} verification of the server's certifica [float] [[apm-agent-client-cert]] -=== Client certificate authentication +== Client certificate authentication APM Server does not require agents to provide a certificate for authentication, and there is no dedicated support for SSL/TLS client certificate authentication in Elastic’s backend agents. \ No newline at end of file diff --git a/docs/en/observability/apm-ui/apm-spaces.asciidoc b/docs/en/observability/apm/security/data-security/apm-spaces.asciidoc similarity index 97% rename from docs/en/observability/apm-ui/apm-spaces.asciidoc rename to docs/en/observability/apm/security/data-security/apm-spaces.asciidoc index 8d97f3069f..5c4257e3f9 100644 --- a/docs/en/observability/apm-ui/apm-spaces.asciidoc +++ b/docs/en/observability/apm/security/data-security/apm-spaces.asciidoc @@ -1,5 +1,5 @@ [[apm-spaces]] -=== Control access to APM data += Control access to APM data Starting in version 8.2.0, the APM UI is {kibana-ref}/xpack-spaces.html[Kibana space] aware. This allows you to separate your data--and access to that data--by team, use case, service environment, @@ -15,7 +15,7 @@ is by creating filtered aliases. See the guide below for more information. [float] [[apm-spaces-example]] -=== Guide: Separate staging and production data +== Guide: Separate staging and production data This guide will explain how to separate your staging and production data. This can be helpful to either remove noise when troubleshooting a production issue, @@ -30,7 +30,7 @@ You should have documents where `service.environment: production` and `service.e If this field is empty, see <> to learn how to set this value. [float] -==== Step 1: Create filtered aliases +=== Step 1: Create filtered aliases The APM UI uses index patterns to query your APM data. An index pattern can match data streams, indices, and/or aliases. The default values are: @@ -244,7 +244,7 @@ POST /_aliases?pretty ==== [float] -==== Step 2: Create {kib} spaces +=== Step 2: Create {kib} spaces Next, you'll need to create a {Kib} space for each service environment. To create these spaces, navigate to **Stack Management** > **Spaces** > **Create a space**. @@ -253,7 +253,7 @@ For this guide, we've created two Kibana spaces, one named `production` and one See {kibana-ref}/xpack-spaces.html[Kibana spaces] for more information on creating a space. [float] -==== Step 3: Update APM index settings in each space +=== Step 3: Update APM index settings in each space Now we can change the default data views that the APM UI queries in each space. @@ -271,7 +271,7 @@ The values in each column match the names of the filtered aliases we created in |==== [float] -==== Step 4: Create {kib} access roles +=== Step 4: Create {kib} access roles In {kib}, navigate to **Stack Management** > **Roles** and click **Create role**. @@ -362,7 +362,7 @@ POST /_security/role/staging_apm_viewer ==== [float] -==== Step 5: Assign users to roles +=== Step 5: Assign users to roles The last thing to do is assign users to the newly created roles above. Users will only have access to the data within the spaces that they are granted. @@ -406,6 +406,6 @@ POST /_security/user/staging-apm-user <1> Assigns the previously created `staging_apm_viewer` role. [float] -==== Step 6: Marvel +=== Step 6: Marvel That's it! Head back to the APM UI and marvel at your space-specific data. diff --git a/docs/en/observability/apm/security/data-security/custom-filter.asciidoc b/docs/en/observability/apm/security/data-security/custom-filter.asciidoc new file mode 100644 index 0000000000..32566c4828 --- /dev/null +++ b/docs/en/observability/apm/security/data-security/custom-filter.asciidoc @@ -0,0 +1,300 @@ +[[apm-custom-filter]] += Custom filters + +include::{observability-docs-root}/docs/en/observability/apm/security/data-security/index.asciidoc[tag=custom-filters] + +[discrete] +[[apm-filters-ingest-pipeline]] +== Create an ingest pipeline filter + +Ingest node pipelines specify a series of processors that transform data in a specific way. +Transformation happens prior to indexing--inflicting no performance overhead on the monitored application. +Pipelines are a flexible and easy way to filter or obfuscate Elastic APM data. + +[discrete] +[[apm-filters-ingest-pipeline-tutorial]] +=== Tutorial: redact sensitive information + +Say you decide to <> +but quickly notice that sensitive information is being collected in the +`http.request.body.original` field: + +[source,json] +---- +{ + "email": "test@abc.com", + "password": "hunter2" +} +---- + +**Create a pipeline** + +To obfuscate the passwords stored in the request body, +you can use a series of {ref}/processors.html[ingest processors]. +To start, create a pipeline with a simple description and an empty array of processors: + +[source,json] +---- +{ + "pipeline": { + "description": "redact http.request.body.original.password", + "processors": [] <1> + } +} +---- +<1> The processors defined below will go in this array + +**Add a JSON processor** + +Add your first processor to the processors array. +Because the agent captures the request body as a string, use the +{ref}/json-processor.html[JSON processor] to convert the original field value into a structured JSON object. +Save this JSON object in a new field: + +[source,json] +---- +{ + "json": { + "field": "http.request.body.original", + "target_field": "http.request.body.original_json", + "ignore_failure": true + } +} +---- + +**Add a set processor** + +If `body.original_json` is not `null`, i.e., it exists, we'll redact the `password` with the {ref}/set-processor.html[set processor], +by setting the value of `body.original_json.password` to `"redacted"`: + +[source,json] +---- +{ + "set": { + "field": "http.request.body.original_json.password", + "value": "redacted", + "if": "ctx?.http?.request?.body?.original_json != null" + } +} +---- + +**Add a convert processor** + +Use the {ref}/convert-processor.html[convert processor] to convert the JSON value of `body.original_json` to a string and set it as the `body.original` value: + +[source,json] +---- +{ + "convert": { + "field": "http.request.body.original_json", + "target_field": "http.request.body.original", + "type": "string", + "if": "ctx?.http?.request?.body?.original_json != null", + "ignore_failure": true + } +} +---- + +**Add a remove processor** + +Finally, use the {ref}/remove-processor.html[remove processor] to remove the `body.original_json` field: + +[source,json] +---- +{ + "remove": { + "field": "http.request.body.original", + "if": "ctx?.http?.request?.body?.original_json != null", + "ignore_failure": true + } +} +---- + +**Register the pipeline** + +Now we'll put it all together. +Use the {ref}/put-pipeline-api.html[create or update pipeline API] to register the new pipeline in {es}. +Name the pipeline `apm_redacted_body_password`: + +[source,console] +---- +PUT _ingest/pipeline/apm_redacted_body_password +{ + "description": "redact http.request.body.original.password", + "processors": [ + { + "json": { + "field": "http.request.body.original", + "target_field": "http.request.body.original_json", + "ignore_failure": true + } + }, + { + "set": { + "field": "http.request.body.original_json.password", + "value": "redacted", + "if": "ctx?.http?.request?.body?.original_json != null" + } + }, + { + "convert": { + "field": "http.request.body.original_json", + "target_field": "http.request.body.original", + "type": "string", + "if": "ctx?.http?.request?.body?.original_json != null", + "ignore_failure": true + } + }, + { + "remove": { + "field": "http.request.body.original_json", + "if": "ctx?.http?.request?.body?.original_json != null", + "ignore_failure": true + } + } + ] +} +---- + +**Test the pipeline** + +Prior to enabling this new pipeline, you can test it with the {ref}/simulate-pipeline-api.html[simulate pipeline API]. +This API allows you to run multiple documents through a pipeline to ensure it is working correctly. + +The request below simulates running three different documents through the pipeline: + +[source,console] +---- +POST _ingest/pipeline/apm_redacted_body_password/_simulate +{ + "docs": [ + { + "_source": { <1> + "http": { + "request": { + "body": { + "original": """{"email": "test@abc.com", "password": "hunter2"}""" + } + } + } + } + }, + { + "_source": { <2> + "some-other-field": true + } + }, + { + "_source": { <3> + "http": { + "request": { + "body": { + "original": """["invalid json" """ + } + } + } + } + } + ] +} +---- +<1> This document features the same sensitive data from the original example above +<2> This document only contains an unrelated field +<3> This document contains invalid JSON + +The API response should be similar to this: + +[source,json] +---- +{ + "docs" : [ + { + "doc" : { + "_source" : { + "http" : { + "request" : { + "body" : { + "original" : { + "password" : "redacted", + "email" : "test@abc.com" + } + } + } + } + } + } + }, + { + "doc" : { + "_source" : { + "nobody" : true + } + } + }, + { + "doc" : { + "_source" : { + "http" : { + "request" : { + "body" : { + "original" : """["invalid json" """ + } + } + } + } + } + } + ] +} +---- + +As expected, only the first simulated document has a redacted password field. +All other documents are unaffected. + +**Create an `@custom` pipeline** + +The final step in this process is to call the newly created `apm_redacted_body_password` pipeline +from the `@custom` pipeline of the data stream you wish to edit. + +include::{observability-docs-root}/docs/en/observability/apm/manage-storage/ingest-pipelines.asciidoc[tag=ingest-pipeline-naming] + +Use the {ref}/put-pipeline-api.html[create or update pipeline API] to register the new pipeline in {es}. +Name the pipeline `traces-apm@custom`: + +[source,console] +---- +PUT _ingest/pipeline/traces-apm@custom +{ + "processors": [ + { + "pipeline": { + "name": "apm_redacted_body_password" <1> + } + } + ] +} +---- +<1> The name of the pipeline we previously created + +TIP: If you prefer using a GUI, you can instead open {kib} and navigate to +**Stack Management** -> **Ingest Pipelines** -> **Create pipeline**. +Use the same naming convention explained previously to ensure your new pipeline matches the correct APM data stream. + +That's it! Passwords will now be redacted from your APM HTTP body data. + +To learn more about ingest pipelines, see <>. + +[discrete] +[[apm-filters-in-agent]] +== APM agent filters + +Some APM agents offer a way to manipulate or drop APM events _before_ they are sent to the APM Server. +Please see the relevant agent's documentation for more information and examples: + +// * Go: {apm-go-ref-v}/[] +// * Java: {apm-java-ref-v}/[] +* .NET: {apm-dotnet-ref-v}/public-api.html#filter-api[Filter API]. +* Node.js: {apm-node-ref-v}/agent-api.html#apm-add-filter[`addFilter()`]. +// * PHP: {apm-php-ref-v}[] +* Python: {apm-py-ref-v}/sanitizing-data.html[custom processors]. +* Ruby: {apm-ruby-ref-v}/api.html#api-agent-add-filter[`add_filter()`]. diff --git a/docs/en/observability/apm/security/data-security/delete.asciidoc b/docs/en/observability/apm/security/data-security/delete.asciidoc new file mode 100644 index 0000000000..712bf3bfe0 --- /dev/null +++ b/docs/en/observability/apm/security/data-security/delete.asciidoc @@ -0,0 +1,90 @@ +[[apm-data-security-delete]] += Delete sensitive data + +If you accidentally ingest sensitive data, follow these steps to remove or redact the offending data: + +. Stop collecting the sensitive data. +Use the *remedy* column of the <> table to determine how to stop collecting +the offending data. + +. Delete or redact the ingested data. With data collection fixed, you can now delete or redact the offending data: ++ +* <> +* <> + +[float] +[[apm-redact-field-data]] +== Redact specific fields + +To redact sensitive data in a specific field, use the {ref}/docs-update-by-query.html[update by query API]. + +For example, the following query removes the `client.ip` address +from APM documents in the `logs-apm.error-default` data stream: + +[source, console] +---- +POST /logs-apm.error-default/_update_by_query +{ + "query": { + "exists": { + "field": "client.ip" + } + } + "script": { + "source": "ctx._source.client.ip = params.redacted", + "params": { + "redacted": "[redacted]" + } + } +} +---- + +Or, perhaps you only want to redact IP addresses from European users: + +[source, console] +---- +POST /logs-apm.error-default/_update_by_query +{ + "query": { + "term": { + "client.geo.continent_name": { + "value": "Europe" + } + } + }, + "script": { + "source": "ctx._source.client.ip = params.redacted", + "params": { + "redacted": "[redacted]" + } + } +} +---- + +See {ref}/docs-update-by-query.html[update by query API] for more information and examples. + +[float] +[[apm-delete-doc-data]] +== Delete {es} documents + +WARNING: This will permanently delete your data. +You should test your queries with the {ref}/search-search.html[search API] prior to deleting data. + +To delete an {es} document, +you can use the {ref}/docs-delete-by-query.html[delete by query API]. + +For example, to delete all documents in the `apm-traces-*` data stream with a `user.email` value, run the following query: + +[source, console] +---- +POST /apm-traces-*/_delete_by_query +{ + "query": { + "exists": { + "field": "user.email" + } + } +} +---- + +See {ref}/docs-delete-by-query.html[delete by query API] for more information and examples. diff --git a/docs/en/observability/apm/security/data-security/filtering.asciidoc b/docs/en/observability/apm/security/data-security/filtering.asciidoc new file mode 100644 index 0000000000..b2297b6ca3 --- /dev/null +++ b/docs/en/observability/apm/security/data-security/filtering.asciidoc @@ -0,0 +1,122 @@ +[[apm-filtering]] += Built-in data filters + +include::{observability-docs-root}/docs/en/observability/apm/security/data-security/index.asciidoc[tag=data-filters] + +[discrete] +[[apm-filters-http-header]] +== HTTP headers + +By default, APM agents capture HTTP request and response headers (including cookies). +Most Elastic APM agents provide the ability to sanitize HTTP header fields, +including cookies and `application/x-www-form-urlencoded` data (POST form fields). +Query string and captured request bodies, like `application/json` data, are not sanitized. + +The default list of sanitized fields attempts to target common field names for data relating to +passwords, credit card numbers, authorization, etc., but can be customized to fit your data. +This sensitive data never leaves the instrumented service. + +This setting supports <>, +which means the list of sanitized fields can be updated without needing to redeploy your services: + +* Go: {apm-go-ref-v}/configuration.html#config-sanitize-field-names[`ELASTIC_APM_SANITIZE_FIELD_NAMES`] +* Java: {apm-java-ref-v}/config-core.html#config-sanitize-field-names[`sanitize_field_names`] +* .NET: {apm-dotnet-ref-v}/config-core.html#config-sanitize-field-names[`sanitizeFieldNames`] +* Node.js: {apm-node-ref-v}/configuration.html#sanitize-field-names[`sanitizeFieldNames`] +// * PHP: {apm-php-ref-v}[``] +* Python: {apm-py-ref-v}/configuration.html#config-sanitize-field-names[`sanitize_field_names`] +* Ruby: {apm-ruby-ref-v}/configuration.html#config-sanitize-field-names[`sanitize_field_names`] + +Alternatively, you can completely disable the capturing of HTTP headers. +This setting also supports <>: + +* Go: {apm-go-ref-v}/configuration.html#config-capture-headers[`ELASTIC_APM_CAPTURE_HEADERS`] +* Java: {apm-java-ref-v}/config-core.html#config-capture-headers[`capture_headers`] +* .NET: {apm-dotnet-ref-v}/config-http.html#config-capture-headers[`CaptureHeaders`] +* Node.js: {apm-node-ref-v}/configuration.html#capture-headers[`captureHeaders`] +// * PHP: {apm-php-ref-v}[``] +* Python: {apm-py-ref-v}/configuration.html#config-capture-headers[`capture_headers`] +* Ruby: {apm-ruby-ref-v}/configuration.html#config-capture-headers[`capture_headers`] + +[discrete] +[[apm-filters-http-body]] +== HTTP bodies + +By default, the body of HTTP requests is not recorded. +Request bodies often contain sensitive data like passwords or credit card numbers, +so use care when enabling this feature. + +This setting supports <>, +which means the list of sanitized fields can be updated without needing to redeploy your services: + +* Go: {apm-go-ref-v}/configuration.html#config-capture-body[`ELASTIC_APM_CAPTURE_BODY`] +* Java: {apm-java-ref-v}/config-core.html#config-capture-body[`capture_body`] +* .NET: {apm-dotnet-ref-v}/config-http.html#config-capture-body[`CaptureBody`] +* Node.js: {apm-node-ref-v}/configuration.html#capture-body[`captureBody`] +// * PHP: {apm-php-ref-v}[``] +* Python: {apm-py-ref-v}/configuration.html#config-capture-body[`capture_body`] +* Ruby: {apm-ruby-ref-v}/configuration.html#config-capture-body[`capture_body`] + +[discrete] +[[apm-filters-personal-data]] +== Personal data + +By default, the APM Server captures some personal data associated with trace events: + +* `client.ip`: The client's IP address. Typically derived from the HTTP headers of incoming requests. +`client.ip` is also used in conjunction with the {ref}/geoip-processor.html[`geoip` processor] to assign +geographical information to trace events. To learn more about how `client.ip` is derived, +see <>. +* `user_agent`: User agent data, including the client operating system, device name, vendor, and version. + +The capturing of this data can be turned off by setting +**Capture personal data** to `false`. + +[discrete] +[[apm-filters-real-user-data]] +== Real user monitoring data + +Protecting user data is important. +For that reason, individual RUM instrumentations can be disabled in the RUM agent with the +{apm-rum-ref-v}/configuration.html#disable-instrumentations[`disableInstrumentations`] configuration variable. +Disabled instrumentations produce no spans or transactions. + +[options="header"] +|==== +|Disable |Configuration value +|HTTP requests |`fetch` and `xmlhttprequest` +|Page load metrics including static resources |`page-load` +|JavaScript errors on the browser |`error` +|User click events including URLs visited, mouse clicks, and navigation events |`eventtarget` +|Single page application route changes |`history` +|==== + +[discrete] +[[apm-filters-database-statements]] +== Database statements + +For SQL databases, APM agents do not capture the parameters of prepared statements. +Note that Elastic APM currently does not make an effort to strip parameters of regular statements. +Not using prepared statements makes your code vulnerable to SQL injection attacks, +so be sure to use prepared statements. + +For non-SQL data stores, such as {es} or MongoDB, +Elastic APM captures the full statement for queries. +For inserts or updates, the full document is not stored. +To filter or obfuscate data in non-SQL database statements, +or to remove the statement entirely, +you can set up an ingest node pipeline. + +[discrete] +[[apm-filters-agent-specific]] +== Agent-specific options + +Certain agents offer additional filtering and obfuscating options: + +**Agent configuration options** + +* (Node.js) Remove errors raised by the server-side process: +disable with {apm-node-ref-v}/configuration.html#capture-exceptions[captureExceptions]. + +* (Java) Remove process arguments from transactions: +disabled by default with {apm-java-ref-v}/config-reporter.html#config-include-process-args[`include_process_args`]. diff --git a/docs/en/observability/apm/security/data-security/index.asciidoc b/docs/en/observability/apm/security/data-security/index.asciidoc new file mode 100644 index 0000000000..0b041e6c6e --- /dev/null +++ b/docs/en/observability/apm/security/data-security/index.asciidoc @@ -0,0 +1,92 @@ +[[apm-data-security]] += Application data security + +++++ +Secure data +++++ + +When setting up Elastic APM, it's essential to review all captured data carefully to ensure +it doesn't contain sensitive information like passwords, credit card numbers, or health data. +In addition, you may wish to filter out other identifiable information, like IP addresses, user agent information, +or form field data. + +Depending on the type of data, we offer several different ways to filter, manipulate, +or obfuscate sensitive information during or before ingestion: + +* <> +* <> + +In addition to utilizing filters, you should regularly review the <> table to ensure +sensitive data is not being ingested. If it is, it's possible to remove or redact it. +See <> for more information. + +[float] +[[apm-built-in-data-filters]] +== Built-in data filters + +// tag::data-filters[] +Built-in data filters allow you to filter or turn off ingestion of the following types of data: + +[options="header"] +|==== +|Data type |Common sensitive data +|<> |Passwords, credit card numbers, authorization, etc. +|<> |Passwords, credit card numbers, etc. +|<> |Client IP address and user agent. +|<> |URLs visited, click events, user browser errors, resources used, etc. +|<> |Sensitive user or business information +|==== +// end::data-filters[] + +[float] +[[apm-custom-data-filters]] +== Custom filters + +// tag::custom-filters[] +Custom filters allow you to filter or redact other types of APM data on ingestion: + +|==== +|<> | Applied at ingestion time. +All agents and fields are supported. Data leaves the instrumented service. +There are no performance overhead implications on the instrumented service. + +|<> | Not supported by all agents. +Data is sanitized before leaving the instrumented service. +Potential overhead implications on the instrumented service +|==== +// end::custom-filters[] + +[float] +[[apm-sensitive-fields]] +== Sensitive fields + +You should review the following fields regularly to ensure sensitive data is not being captured: + +[options="header"] +|==== +| Field | Description | Remedy +| `client.ip` | The client IP address, as forwarded by proxy. | <> +| `http.request.body.original` | The body of the monitored HTTP request. | <> +| `http.request.headers` | The canonical headers of the monitored HTTP request. | <> +| `http.request.socket.remote_address` | The address of the last proxy or end-user (if no proxy). | <> +| `http.response.headers` | The canonical headers of the monitored HTTP response. | <> +| `process.args` | Process arguments. | <> +| `span.db.statement` | Database statement. | <> +| `stacktrace.vars` | A flat mapping of local variables captured in the stack frame | <> +| `url.query` | The query string of the request, e.g. `?pass=hunter2`. | <> +| `user.*` | Logged-in user information. | <> +| `user_agent.*` | Device and version making the network request. | <> +|==== + +//// +Subsections +//// + +:leveloffset: +1 + +include::{observability-docs-root}/docs/en/observability/apm/security/data-security/apm-spaces.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/security/data-security/filtering.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/security/data-security/custom-filter.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/security/data-security/delete.asciidoc[] + +:!leveloffset: diff --git a/docs/en/observability/apm/access-api-keys.asciidoc b/docs/en/observability/apm/security/elastic-stack/access-api-keys.asciidoc similarity index 96% rename from docs/en/observability/apm/access-api-keys.asciidoc rename to docs/en/observability/apm/security/elastic-stack/access-api-keys.asciidoc index f6fdf10eb3..3a8862fd6f 100644 --- a/docs/en/observability/apm/access-api-keys.asciidoc +++ b/docs/en/observability/apm/security/elastic-stack/access-api-keys.asciidoc @@ -1,5 +1,5 @@ [[apm-beats-api-keys]] -=== Grant access using API keys += Grant access using API keys Instead of using usernames and passwords, you can use API keys to grant access to {es} resources. You can set API keys to expire at a certain time, @@ -15,7 +15,7 @@ You can create as many API keys per user as necessary. [float] [[apm-beats-api-key-publish]] -==== Create an API key for writing events +== Create an API key for writing events In {kib}, navigate to **{stack-manage-app}** > **API keys** and click **Create API key**. @@ -76,7 +76,7 @@ output.elasticsearch: [float] [[apm-beats-api-key-monitor]] -==== Create an API key for monitoring +== Create an API key for monitoring In {kib}, navigate to **{stack-manage-app}** > **API keys** and click **Create API key**. @@ -120,7 +120,7 @@ monitoring.elasticsearch: [float] [[apm-beats-api-key-es]] -==== Create an API key with {es} APIs +== Create an API key with {es} APIs You can also use {es}'s {ref}/security-api-create-api-key.html[Create API key API] to create a new API key. For example: @@ -165,9 +165,9 @@ POST /_security/api_key See the {ref}/security-api-create-api-key.html[Create API key] reference for more information. -[[apm-learn-more-api-keys]] [float] -==== Learn more about API keys +[[apm-learn-more-api-keys]] +== Learn more about API keys See the {es} API key documentation for more information: diff --git a/docs/en/observability/apm/feature-roles.asciidoc b/docs/en/observability/apm/security/elastic-stack/index.asciidoc similarity index 92% rename from docs/en/observability/apm/feature-roles.asciidoc rename to docs/en/observability/apm/security/elastic-stack/index.asciidoc index d1acdac6bc..6e67bfc0a2 100644 --- a/docs/en/observability/apm/feature-roles.asciidoc +++ b/docs/en/observability/apm/security/elastic-stack/index.asciidoc @@ -1,16 +1,12 @@ [[apm-secure-comms-stack]] -== Secure communication with the {stack} - -++++ -With the {stack} -++++ += Secure communication with the {stack} NOTE: This documentation only applies to the APM Server binary. Use role-based access control or API keys to grant APM Server users access to secured resources. * <> -* <>. +* <> After privileged users have been created, use authentication to connect to a secured Elastic cluster. @@ -23,7 +19,7 @@ A reference of all available <Create a _writer_ user @@ -72,7 +68,7 @@ In general, there are three types of privileges you'll work with: APM users that publish events to {es} need privileges to write to APM data streams. [float] -==== General writer role +=== General writer role To grant an APM user the required privileges for writing events to {es}: @@ -102,7 +98,7 @@ that has the following privileges: //// [[apm-privileges-to-publish-monitoring]] -=== Grant privileges and roles needed for monitoring +== Grant privileges and roles needed for monitoring ++++ Create a _monitoring_ user @@ -119,7 +115,7 @@ depend on the method used to collect that data. [float] [[apm-privileges-to-publish-monitoring-write]] -==== Publish monitoring data +=== Publish monitoring data [IMPORTANT] ==== @@ -130,7 +126,7 @@ Monitoring on {ecloud} is enabled by clicking the *Enable* button in the *Monito [float] [[apm-privileges-to-publish-monitoring-internal]] -===== Internal collection +==== Internal collection If you're using <> to collect metrics about APM Server, {security-features} provides @@ -168,7 +164,7 @@ If you don't use the +apm_system+ user: [float] [[apm-privileges-to-publish-monitoring-metricbeat]] -===== {metricbeat} collection +==== {metricbeat} collection NOTE: When using {metricbeat} to collect metrics, no roles or users need to be created with APM Server. @@ -206,7 +202,7 @@ information. Assign the following roles to the *monitoring user*: [float] [[apm-privileges-to-publish-monitoring-view]] -==== View monitoring data +=== View monitoring data To grant users the required privileges for viewing monitoring data: @@ -243,7 +239,7 @@ need to view monitoring data for APM Server: //// [[apm-privileges-api-key]] -=== Grant privileges and roles needed for API key management +== Grant privileges and roles needed for API key management ++++ Create an _API key_ user @@ -275,7 +271,7 @@ Users with this role can only create API keys that have the same or lower access [float] [[apm-privileges-api-key-example]] -=== Example API key role +== Example API key role The following example assigns the required cluster privileges, and the ingest agent data `apm` API key application privileges to a role named `apm_api_key`: @@ -311,7 +307,7 @@ PUT _security/role/apm_api_key <1> //// [[apm-privileges-agent-central-config]] -=== Grant privileges and roles needed for APM Agent central configuration +== Grant privileges and roles needed for APM Agent central configuration ++++ Create a _central config_ user @@ -319,7 +315,7 @@ PUT _security/role/apm_api_key <1> [float] [[apm-privileges-agent-central-config-server]] -==== APM Server agent central configuration management +=== APM Server agent central configuration management APM Server acts as a proxy between your APM agents and the APM UI. The APM UI communicates any changed settings to APM Server so that your agents only need to poll the Server @@ -355,7 +351,7 @@ TIP: Looking for privileges and roles needed to use central configuration from t See <>. [[apm-privileges-rum-source-map]] -=== Grant privileges and roles needed for reading source maps +== Grant privileges and roles needed for reading source maps ++++ Create a _source map_ user @@ -363,7 +359,7 @@ See <>. [float] [[apm-privileges-rum-source-mapping]] -==== APM Server RUM source mapping +=== APM Server RUM source mapping If <> is enabled, additional privileges are required to read source maps. @@ -390,11 +386,4 @@ See <> for more details. *********************************** *********************************** //// -// [[apm-privileges-create-api-keys]] -// === Grant privileges and roles needed to create APM Server API keys - -// ++++ -// Create an _APM API key_ user -// ++++ - -// CONTENT \ No newline at end of file +include::{observability-docs-root}/docs/en/observability/apm/security/elastic-stack/access-api-keys.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/security/index.asciidoc b/docs/en/observability/apm/security/index.asciidoc new file mode 100644 index 0000000000..02ab702328 --- /dev/null +++ b/docs/en/observability/apm/security/index.asciidoc @@ -0,0 +1,45 @@ +//// +TO DO: +Does this framing make sense? +//// +[[apm-securing-apm-server]] += Use APM securely + +When setting up Elastic APM, it's critical to ensure that application data is secure from start to finish. +You should approach securing your application data from different perspectives: + +[cols="1,1"] +|=== +| *What kind of data is collected?* +| Ensure that data doesn’t contain sensitive information like passwords, + credit card numbers, health data, or other identifiable information. + + Read more in <>. + +| *How do APM agents and {agent} communicate?* +| Ensure that any communication between APM agents and {agent} + are both encrypted and authenticated. + + Read more in <>. + +| *How do APM Server and the {stack} communicate?* +| Use role-based access control to grant APM Server users access + to secured resources. The roles that you set up depend on your organization's security requirements and the + minimum privileges required to use specific features. + + Read more in <>. + +| *Who can use the APM UI?* +| Use role-based access control to grant users access to features of the APM UI. + + Read more in <>. +|=== + +//// +Subsections +//// + +include::{observability-docs-root}/docs/en/observability/apm/security/data-security/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/security/apm-agents/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/security/elastic-stack/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/security/user-access/index.asciidoc[leveloffset=+1] \ No newline at end of file diff --git a/docs/en/observability/apm/security/user-access/annotation.asciidoc b/docs/en/observability/apm/security/user-access/annotation.asciidoc new file mode 100644 index 0000000000..888759bd98 --- /dev/null +++ b/docs/en/observability/apm/security/user-access/annotation.asciidoc @@ -0,0 +1,44 @@ +[[apm-app-annotation-user-create]] += APM UI annotation user + +++++ +Create an annotation user +++++ + +NOTE: By default, the `viewer` and `editor` built-in roles provide read access to Observability annotations. +You only need to create an annotation user to write to the annotations index +({kibana-ref}/apm-settings-kb.html[`xpack.observability.annotations.index`]). + +[float] +[[apm-app-annotation-user]] +== Annotation user + +View deployment annotations in the APM UI. + +. Create a new role, named something like `annotation_user`, +and assign the following privileges: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +|Index +|`read` on +\{ANNOTATION_INDEX\}+^1^ +|Read-only access to the observability annotation index + +|Index +|`view_index_metadata` on +\{ANNOTATION_INDEX\}+^1^ +|Read-only access to observability annotation index metadata +|==== ++ +^1^ +\{ANNOTATION_INDEX\}+ should be the index name you've defined in +{kibana-ref}/apm-settings-kb.html[`xpack.observability.annotations.index`]. + +. Assign the `annotation_user` created previously, and the roles and privileges necessary to create +a <> or <> APM reader to any users that need to view annotations in the APM UI + +[float] +[[apm-app-annotation-api]] +== Annotation API + +See <>. \ No newline at end of file diff --git a/docs/en/observability/apm/security/user-access/api-ui.asciidoc b/docs/en/observability/apm/security/user-access/api-ui.asciidoc new file mode 100644 index 0000000000..7322aa39e4 --- /dev/null +++ b/docs/en/observability/apm/security/user-access/api-ui.asciidoc @@ -0,0 +1,82 @@ +[[apm-app-api-user]] += APM UI API user + +++++ +Create an API user +++++ + +[float] +[[apm-app-api-config-manager]] +== Central configuration API + +Users can list, search, create, update, and delete central configurations via the APM UI API. + +. Assign the following Kibana feature privileges: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +| Kibana +|`all` on the APM and User Experience feature +|Allow all access to the APM and User Experience apps +|==== + +[float] +[[apm-app-api-config-reader]] +== Central configuration API reader + +Sometimes a user only needs to list and search central configurations via the APM UI API. + +. Assign the following Kibana feature privileges: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +| Kibana +|`read` on the APM and User Experience feature +|Allow read access to the APM and User Experience apps +|==== + +[float] +[[apm-app-api-annotation-manager]] +== Annotation API + +Users can use the annotation API to create annotations on their APM data. + +. Create a new role, named something like `annotation_role`, +and assign the following privileges: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +|Index +|`manage` on +observability-annotations+ index +|Check if the +observability-annotations+ index exists + +|Index +|`read` on +observability-annotations+ index +|Read the +observability-annotations+ index + +|Index +|`create_index` on +observability-annotations+ index +|Create the +observability-annotations+ index + +|Index +|`create_doc` on +observability-annotations+ index +|Create new annotations in the +observability-annotations+ index +|==== + +. Assign the `annotation_role` created previously, +and the following Kibana feature privileges to any annotation API users: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +| Kibana +|`all` on the APM and User Experience feature +|Allow all access to the APM and User Experience apps +|==== \ No newline at end of file diff --git a/docs/en/observability/apm/security/user-access/central-config.asciidoc b/docs/en/observability/apm/security/user-access/central-config.asciidoc new file mode 100644 index 0000000000..59e189901a --- /dev/null +++ b/docs/en/observability/apm/security/user-access/central-config.asciidoc @@ -0,0 +1,67 @@ +[[apm-app-central-config-user]] += APM UI central config user + +++++ +Create a central config user +++++ + +[float] +[[apm-app-central-config-manager]] +== Central configuration manager + +Central configuration users need to be able to view, create, update, and delete APM agent configurations. + +. Create a new role, named something like `central-config-manager`, and assign the following privileges: ++ +-- +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/central-config-users/widget.asciidoc[] +-- ++ +TIP: Using the deprecated APM Server binaries? +Add the privileges under the **Classic APM indices** tab above. + +. Assign the `central-config-manager` role created in the previous step, +and the following Kibana feature privileges to anyone who needs to manage central configurations: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +| Kibana +|`All` on the APM and User Experience feature +|Allow full use of the APM and User Experience apps +|==== + +[float] +[[apm-app-central-config-reader]] +== Central configuration reader + +In some instances, you may wish to create a user that can only read central configurations, +but not create, update, or delete them. + +. Create a new role, named something like `central-config-reader`, and assign the following privileges: ++ +-- +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/central-config-users/widget.asciidoc[] +-- ++ +TIP: Using the deprecated APM Server binaries? +Add the privileges under the **Classic APM indices** tab above. + +. Assign the `central-config-reader` role created in the previous step, +and the following Kibana feature privileges to anyone who needs to read central configurations: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +| Kibana +|`read` on the APM and User Experience feature +|Allow read access to the APM and User Experience apps +|==== + +[float] +[[apm-app-central-config-api]] +== Central configuration API + +See <>. \ No newline at end of file diff --git a/docs/en/observability/apm/security/user-access/index.asciidoc b/docs/en/observability/apm/security/user-access/index.asciidoc new file mode 100644 index 0000000000..4011f17066 --- /dev/null +++ b/docs/en/observability/apm/security/user-access/index.asciidoc @@ -0,0 +1,37 @@ +[[apm-app-users]] += Secure access to the APM UI + +:beat_default_index_prefix: apm +:annotation_index: observability-annotations + +++++ +Secure access to the APM UI +++++ + +Use role-based access control to grant users access to secured +resources. The roles that you set up depend on your organization's security +requirements and the minimum privileges required to use specific features. + +{es-security-features} provides {ref}/built-in-roles.html[built-in roles] that grant a +subset of the privileges needed by APM users. +When possible, assign users the built-in roles to minimize the affect of future changes on your security strategy. +If no built-in role is available, you can assign users the privileges needed to accomplish a specific task. +In general, there are three types of privileges you'll work with: + +* **Elasticsearch cluster privileges**: Manage the actions a user can perform against your cluster. +* **Elasticsearch index privileges**: Control access to the data in specific indices your cluster. +* **Kibana feature privileges**: Grant users write or read access to features and apps within Kibana. + +Select your use-case to get started: + +* <> +* <> +* <> +* <> +* <> + +include::{observability-docs-root}/docs/en/observability/apm/security/user-access/reader.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/security/user-access/annotation.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/security/user-access/api-ui.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/security/user-access/central-config.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/security/user-access/storage-explorer.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm/security/user-access/reader.asciidoc b/docs/en/observability/apm/security/user-access/reader.asciidoc new file mode 100644 index 0000000000..f342e277eb --- /dev/null +++ b/docs/en/observability/apm/security/user-access/reader.asciidoc @@ -0,0 +1,77 @@ +[[apm-app-reader]] += APM reader user + +++++ +Create an APM reader user +++++ + +APM reader users typically need to view the APM UI and dashboards and visualizations that use APM data. +These users might also need to create and edit dashboards, visualizations, and machine learning jobs. + +[float] +[[apm-app-reader-full]] +== APM reader + +To create an APM reader user: + +. Create a new role, named something like `read-apm`, and assign the following privileges: ++ +-- +:apm-read-view: +:apm-monitor: +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/apm-app-reader/widget.asciidoc[] +:!apm-read-view: +:!apm-monitor: +-- + +. Assign the `read-apm` role created in the previous step, and the following built-in roles to +any APM reader users: ++ +[options="header"] +|==== +|Role | Purpose + +|`kibana_admin` +|Grants access to all features in Kibana. + +|`machine_learning_admin` +|Grants the privileges required to create, update, and view machine learning jobs +|==== + +[float] +[[apm-app-reader-partial]] +== Partial APM reader + +In some instances, you may wish to restrict certain Kibana apps that a user has access to. + +. Create a new role, named something like `read-apm-partial`, and assign the following privileges: ++ +-- +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/apm-app-reader/widget.asciidoc[] +-- + +. Assign feature privileges to any Kibana feature that the user needs access to. +Here are two examples: ++ +[options="header"] +|==== +|Type | Privilege | Purpose + +| Kibana +| `Read` or `All` on the APM and User Experience feature +| Allow the use of the the APM and User Experience apps + +| Kibana +| `Read` or `All` on Dashboards and Discover +| Allow the user to view, edit, and create dashboards, as well as browse data. +|==== + +. Finally, assign the following role if a user needs to enable and edit machine learning features: ++ +[options="header"] +|==== +|Role | Purpose + +|`machine_learning_admin` +|Grants the privileges required to create, update, and view machine learning jobs +|==== diff --git a/docs/en/observability/apm/security/user-access/storage-explorer.asciidoc b/docs/en/observability/apm/security/user-access/storage-explorer.asciidoc new file mode 100644 index 0000000000..429fb7fe78 --- /dev/null +++ b/docs/en/observability/apm/security/user-access/storage-explorer.asciidoc @@ -0,0 +1,22 @@ +[[apm-app-storage-explorer-user-create]] += APM UI storage explorer user + +++++ +Create a storage explorer user +++++ + +[float] +[[apm-app-storage-explorer-user]] +== Storage Explorer user + +View the **Storage Explorer** in the APM UI. + +. Create a new role, named something like `storage-explorer_user`, +and assign the following privileges: ++ +-- +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/storage-explorer-user/widget.asciidoc[] +-- + +. Assign the `storage-explorer_user` created previously, and the roles and privileges necessary to create +a <> or <> APM reader to any users that need to view **Storage Explorer** in the APM UI. \ No newline at end of file diff --git a/docs/en/observability/apm/setting-up-and-running.asciidoc b/docs/en/observability/apm/setting-up-and-running.asciidoc deleted file mode 100644 index a9a065f614..0000000000 --- a/docs/en/observability/apm/setting-up-and-running.asciidoc +++ /dev/null @@ -1,31 +0,0 @@ - -[[apm-setting-up-and-running]] -== APM Server advanced setup - -++++ -Advanced setup -++++ - -Before reading this section, see the <> -for basic installation and running instructions. - -This section includes additional information on how to set up and run APM Server, including: - -* <> -* <> -* <> -* <> -* <> -* <> - -include::{observability-docs-root}/docs/en/observability/apm/shared-directory-layout.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/keystore.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/command-reference.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/data-ingestion.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/high-availability.asciidoc[] - -include::{observability-docs-root}/docs/en/observability/apm/shared-systemd.asciidoc[] diff --git a/docs/en/observability/apm/shared-docker.asciidoc b/docs/en/observability/apm/shared-docker.asciidoc index 335e3d68f3..90f8af1547 100644 --- a/docs/en/observability/apm/shared-docker.asciidoc +++ b/docs/en/observability/apm/shared-docker.asciidoc @@ -1,5 +1,6 @@ +[float] [[apm-running-on-docker]] -==== Run APM Server on Docker += Run APM Server on Docker Docker images for APM Server are available from the Elastic Docker registry. The base image is https://hub.docker.com/_/ubuntu[ubuntu:22.04]. @@ -15,7 +16,7 @@ https://www.elastic.co/subscriptions[Subscriptions] page for information about Elastic license levels. [float] -===== Pull the image +== Pull the image Obtaining APM Server for Docker is as simple as issuing a +docker pull+ command against the Elastic Docker registry and then, optionally, verifying the image. @@ -58,7 +59,7 @@ The following checks were performed on each of these signatures: endif::[] [float] -===== Configure APM Server on Docker +== Configure APM Server on Docker The Docker image provides several methods for configuring APM Server. The conventional approach is to provide a configuration file via a volume mount, but @@ -66,7 +67,7 @@ it's also possible to create a custom image with your configuration included. [float] -====== Example configuration file +=== Example configuration file Download this example configuration file as a starting point: @@ -76,7 +77,7 @@ curl -L -O https://raw.githubusercontent.com/elastic/apm-server/{branch}/apm-ser ------------------------------------------------ [float] -====== Volume-mounted configuration +=== Volume-mounted configuration One way to configure APM Server on Docker is to provide +apm-server.docker.yml+ via a volume mount. With +docker run+, the volume mount can be specified like this. @@ -99,7 +100,7 @@ the `-E output.elasticsearch.hosts` line with the Cloud ID and elastic password using the syntax shown earlier. [float] -====== Customize your configuration +=== Customize your configuration ifdef::has_docker_label_ex[] The +apm-server.docker.yml+ file you downloaded earlier is configured to deploy {beats} modules based on the Docker labels applied to your containers. See <> for more details. Add labels to your application Docker containers, and they will be picked up by the {beats} autodiscover feature when they are deployed. Here is an example command for an Apache HTTP Server container with labels to configure the {filebeat} and {metricbeat} modules for the Apache HTTP Server: @@ -125,7 +126,7 @@ The +apm-server.docker.yml+ downloaded earlier should be customized for your env endif::[] [float] -====== Custom image configuration +=== Custom image configuration It's possible to embed your APM Server configuration in a custom image. Here is an example Dockerfile to achieve this: diff --git a/docs/en/observability/apm-ui/tab-widgets/apm-app-reader/content.asciidoc b/docs/en/observability/apm/tab-widgets/apm-app-reader/content.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/tab-widgets/apm-app-reader/content.asciidoc rename to docs/en/observability/apm/tab-widgets/apm-app-reader/content.asciidoc diff --git a/docs/en/observability/apm-ui/tab-widgets/apm-app-reader/widget.asciidoc b/docs/en/observability/apm/tab-widgets/apm-app-reader/widget.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/tab-widgets/apm-app-reader/widget.asciidoc rename to docs/en/observability/apm/tab-widgets/apm-app-reader/widget.asciidoc diff --git a/docs/en/observability/apm-ui/tab-widgets/central-config-users/content.asciidoc b/docs/en/observability/apm/tab-widgets/central-config-users/content.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/tab-widgets/central-config-users/content.asciidoc rename to docs/en/observability/apm/tab-widgets/central-config-users/content.asciidoc diff --git a/docs/en/observability/apm-ui/tab-widgets/central-config-users/widget.asciidoc b/docs/en/observability/apm/tab-widgets/central-config-users/widget.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/tab-widgets/central-config-users/widget.asciidoc rename to docs/en/observability/apm/tab-widgets/central-config-users/widget.asciidoc diff --git a/docs/en/observability/apm/tab-widgets/install-agents-widget.asciidoc b/docs/en/observability/apm/tab-widgets/install-agents-widget.asciidoc index 84ddaa7c5d..4979d12366 100644 --- a/docs/en/observability/apm/tab-widgets/install-agents-widget.asciidoc +++ b/docs/en/observability/apm/tab-widgets/install-agents-widget.asciidoc @@ -196,7 +196,7 @@ include::install-agents.asciidoc[tag=rum] hidden=""> ++++ -include::../open-telemetry.asciidoc[tag=otel-get-started] +include::../collect-application-data/open-telemetry/index.asciidoc[tag=otel-get-started] ++++ diff --git a/docs/en/observability/apm-ui/tab-widgets/storage-explorer-user/content.asciidoc b/docs/en/observability/apm/tab-widgets/storage-explorer-user/content.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/tab-widgets/storage-explorer-user/content.asciidoc rename to docs/en/observability/apm/tab-widgets/storage-explorer-user/content.asciidoc diff --git a/docs/en/observability/apm-ui/tab-widgets/storage-explorer-user/widget.asciidoc b/docs/en/observability/apm/tab-widgets/storage-explorer-user/widget.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/tab-widgets/storage-explorer-user/widget.asciidoc rename to docs/en/observability/apm/tab-widgets/storage-explorer-user/widget.asciidoc diff --git a/docs/en/observability/apm/apm-performance-diagnostic.asciidoc b/docs/en/observability/apm/troubleshooting/apm-performance-diagnostic.asciidoc similarity index 97% rename from docs/en/observability/apm/apm-performance-diagnostic.asciidoc rename to docs/en/observability/apm/troubleshooting/apm-performance-diagnostic.asciidoc index daa4d6f12a..e7f5e28f71 100644 --- a/docs/en/observability/apm/apm-performance-diagnostic.asciidoc +++ b/docs/en/observability/apm/troubleshooting/apm-performance-diagnostic.asciidoc @@ -1,13 +1,13 @@ [[apm-performance-diagnostic]] -=== APM Server performance diagnostic += APM Server performance diagnostic [[apm-es-backpressure]] [float] -==== Diagnosing backpressure from {es} +== Diagnosing backpressure from {es} When {es} is under excessive load or indexing pressure, APM Server could experience the downstream backpressure when indexing new documents into {es}. Most commonly, backpressure from {es} will manifest itself in the form of higher indexing latency and/or rejected requests, which in return could lead APM Server to deny incoming requests. -As a result, APM agents connected to the affected APM Server will suffer from throttling and/or request timeout when shipping APM events. +As a result, APM agents connected to the affected APM Server will suffer from throttling and/or request timeout when shipping APM events. To quickly identify possible issues try looking for similar error logs lines in APM Server logs: diff --git a/docs/en/observability/apm/apm-response-codes.asciidoc b/docs/en/observability/apm/troubleshooting/apm-response-codes.asciidoc similarity index 86% rename from docs/en/observability/apm/apm-response-codes.asciidoc rename to docs/en/observability/apm/troubleshooting/apm-response-codes.asciidoc index d6d1dc1f01..468a14650e 100644 --- a/docs/en/observability/apm/apm-response-codes.asciidoc +++ b/docs/en/observability/apm/troubleshooting/apm-response-codes.asciidoc @@ -1,30 +1,30 @@ [[apm-common-response-codes]] -=== APM Server response codes += APM Server response codes [[apm-bad-request]] [float] -==== HTTP 400: Data decoding error / Data validation error +== HTTP 400: Data decoding error / Data validation error The most likely cause for this error is using incompatible versions of {apm-agent} and APM Server. See the <> to verify compatibility. [[apm-event-too-large]] [float] -==== HTTP 400: Event too large +== HTTP 400: Event too large APM agents communicate with the APM server by sending events in an HTTP request. Each event is sent as its own line in the HTTP request body. If events are too large, you should consider increasing the <> setting in the APM integration, and adjusting relevant settings in the agent. [[apm-unauthorized]] [float] -==== HTTP 401: Invalid token +== HTTP 401: Invalid token Either the <> in the request header doesn't match the secret token configured in the APM integration, or the <> is invalid. [[apm-forbidden]] [float] -==== HTTP 403: Forbidden request +== HTTP 403: Forbidden request Either you are sending requests to a <> endpoint without RUM enabled, or a request is coming from an origin not specified in the APM integration settings. @@ -32,7 +32,7 @@ See the <> setting for more information. [[apm-request-timed-out]] [float] -==== HTTP 503: Request timed out waiting to be processed +== HTTP 503: Request timed out waiting to be processed This happens when APM Server exceeds the maximum number of requests that it can process concurrently. To alleviate this problem, you can try to: reduce the sample rate and/or reduce the collected stack trace information. diff --git a/docs/en/observability/apm/apm-server-down.asciidoc b/docs/en/observability/apm/troubleshooting/apm-server-down.asciidoc similarity index 96% rename from docs/en/observability/apm/apm-server-down.asciidoc rename to docs/en/observability/apm/troubleshooting/apm-server-down.asciidoc index f9e3d00378..599277aca3 100644 --- a/docs/en/observability/apm/apm-server-down.asciidoc +++ b/docs/en/observability/apm/troubleshooting/apm-server-down.asciidoc @@ -1,5 +1,5 @@ [[apm-server-es-down]] -=== What happens when APM Server or {es} is down? += What happens when APM Server or {es} is down? *If {es} is down* diff --git a/docs/en/observability/apm-ui/troubleshooting.asciidoc b/docs/en/observability/apm/troubleshooting/common-problems.asciidoc similarity index 52% rename from docs/en/observability/apm-ui/troubleshooting.asciidoc rename to docs/en/observability/apm/troubleshooting/common-problems.asciidoc index 2dced7c1c2..d3451c3554 100644 --- a/docs/en/observability/apm-ui/troubleshooting.asciidoc +++ b/docs/en/observability/apm/troubleshooting/common-problems.asciidoc @@ -1,29 +1,17 @@ -[[apm-app-troubleshooting]] -== Troubleshoot - -++++ -Troubleshoot -++++ - -This section describes common problems you might encounter with the APM UI. -If your issue is potentially related to other components of the APM ecosystem, -don't forget to check our other troubleshooting guides or discussion forum: - -* {apm-guide-ref}/troubleshoot-apm.html[APM Server troubleshooting] -* {apm-dotnet-ref}/troubleshooting.html[.NET agent troubleshooting] -* {apm-go-ref}/troubleshooting.html[Go agent troubleshooting] -* {apm-ios-ref}/troubleshooting.html[iOS agent troubleshooting] -* {apm-java-ref}/trouble-shooting.html[Java agent troubleshooting] -* {apm-node-ref}/troubleshooting.html[Node.js agent troubleshooting] -* {apm-php-ref}/troubleshooting.html[PHP agent troubleshooting] -* {apm-py-ref}/troubleshooting.html[Python agent troubleshooting] -* {apm-ruby-ref}/debugging.html[Ruby agent troubleshooting] -* {apm-rum-ref}/troubleshooting.html[RUM troubleshooting] -* https://discuss.elastic.co/c/apm[APM discussion forum]. - -[discrete] -[[troubleshooting-apm-app]] -== Troubleshoot common APM UI problems +[[apm-common-problems]] += Common problems + +This section describes common problems you might encounter when using APM Server and the APM UI in {kib}. + +*APM Server*: + +* <> +* <> +* <> +* <> +* <> + +*APM UI*: * <> * <> @@ -31,9 +19,148 @@ don't forget to check our other troubleshooting guides or discussion forum: * <> * <> +[float] +[[apm-no-data-indexed]] +== No data is indexed + +If no data shows up in {es}, first make sure that your APM components are properly connected. + +include::{observability-docs-root}/docs/en/observability/apm/tab-widgets/no-data-indexed-widget.asciidoc[] + + +[float] +[[apm-common-ssl-problems]] +== Common SSL-related problems + +* <> +* <> +* <> +* <> +* <> + + +[float] +[[apm-ssl-client-fails]] +=== SSL client fails to connect + +The target host might be unreachable or the certificate may not be valid. +To fix this problem: + +. Make sure that the APM Server process on the target host is running and you can connect to it. +Try to ping the target host to verify that you can reach it from the host running APM Server. +Then use either `nc` or `telnet` to make sure that the port is available. For example: ++ +[source,shell] +---- +ping +telnet 5044 +---- + +. Verify that the certificate is valid and that the hostname and IP match. +. Use OpenSSL to test connectivity to the target server and diagnose problems. +See the https://www.openssl.org/docs/manmaster/man1/openssl-s_client.html[OpenSSL documentation] for more info. + +[float] +[[apm-cannot-validate-certificate]] +=== x509: cannot validate certificate for because it doesn't contain any IP SANs + +This happens because your certificate is only valid for the hostname present in the Subject field. +To resolve this problem, try one of these solutions: + +* Create a DNS entry for the hostname, mapping it to the server's IP. +* Create an entry in `/etc/hosts` for the hostname. Or, on Windows, add an entry to +`C:\Windows\System32\drivers\etc\hosts`. +* Re-create the server certificate and add a Subject Alternative Name (SAN) for the IP address of the server. This makes the +server's certificate valid for both the hostname and the IP address. + +[float] +[[apm-getsockopt-no-route-to-host]] +=== getsockopt: no route to host + +This is not an SSL problem. It's a networking problem. Make sure the two hosts can communicate. + +[float] +[[apm-getsockopt-connection-refused]] +=== getsockopt: connection refused + +This is not an SSL problem. Make sure that {ls} is running and that there is no firewall blocking the traffic. + +[float] +[[apm-target-machine-refused-connection]] +=== No connection could be made because the target machine actively refused it + +A firewall is refusing the connection. Check if a firewall is blocking the traffic on the client, the network, or the +destination host. + +[[apm-io-timeout]] +[float] +== I/O Timeout + +I/O Timeouts can occur when your timeout settings across the stack are not configured correctly, +especially when using a load balancer. + +You may see an error like the one below in the {apm-agent} logs, and/or a similar error on the APM Server side: + +[source,logs] +---- +[ElasticAPM] APM Server responded with an error: +"read tcp 123.34.22.313:8200->123.34.22.40:41602: i/o timeout" +---- + +To fix this, ensure timeouts are incrementing from the {apm-agent}, +through your load balancer, to the APM Server. + +By default, the agent timeouts are set at 10 seconds, and the server timeout is set at 3600 seconds. +Your load balancer should be set somewhere between these numbers. + +For example: + +[source,txt] +---- +APM agent --> Load Balancer --> APM Server + 10s 15s 3600s +---- + +The APM Server timeout can be configured by updating the +<>. + +[[apm-field-limit-exceeded]] +[float] +== Field limit exceeded + +When adding too many distinct tag keys on a transaction or span, +you risk creating a link:{ref}/mapping.html#mapping-limit-settings[mapping explosion]. + +For example, you should avoid that user-specified data, +like URL parameters, is used as a tag key. +Likewise, using the current timestamp or a user ID as a tag key is not a good idea. +However, tag *values* with a high cardinality are not a problem. +Just try to keep the number of distinct tag keys at a minimum. + +The symptom of a mapping explosion is that transactions and spans are not indexed anymore after a certain time. Usually, on the next day, +the spans and transactions will be indexed again because a new index is created each day. +But as soon as the field limit is reached, indexing stops again. + +In the agent logs, you won't see a sign of failures as the APM server asynchronously sends the data it received from the agents to {es}. However, the APM server and {es} log a warning like this: + +[source,logs] +---- +{\"type\":\"illegal_argument_exception\",\"reason\":\"Limit of total fields [1000] in [INDEX_NAME] has been exceeded\"} +---- + +[[apm-tail-based-sampling-memory-disk-io]] +[float] +== Tail-based sampling causing high system memory usage and high disk IO + +Tail-based sampling requires minimal memory to run, and there should not be a noticeable increase in RSS memory usage. +However, since tail-based sampling writes data to disk, +it is possible to see a significant increase in OS page cache memory usage due to disk IO. +If you see a drop in throughput and excessive disk activity after enabling tail-based sampling, +please ensure that there is enough memory headroom in the system for OS page cache to perform disk IO efficiently. + [float] [[no-apm-data-found]] -=== No APM data found +== Data doesn't appear in the APM UI This section can help with any of the following: @@ -45,15 +172,64 @@ This section can help with any of the following: These problems are likely to be caused by a missing index template or ingest pipeline. By default, {fleet} sets up these and other APM assets when the APM integration is installed. Try reinstalling the APM integration by navigating to -**Integrations** > **Elastic APM** > **Manage in Fleet** > **Settings** > **Reinstall Elastic APM**. +**Integrations** → **Elastic APM** → **Manage in Fleet** → **Settings** → **Reinstall Elastic APM**. Because assets cannot be applied to indices retroactively, after reinstalling the APM integration you must either wait for the index to rollover or force a rollover. To force a rollover, use the {ref}/indices-rollover-index.html[rollover API] to target the relevant {apm-guide-ref}/apm-data-streams.html[APM data streams]. +[float] +[[apm-data-indexed-no-apm]] +=== Data is indexed but doesn't appear in the APM UI + +The APM UI relies on index mappings to query and display data. +If your APM data isn't showing up in the APM UI, but is elsewhere in {kib}, like the Discover app, +you may have a missing index mapping. + +You can determine if a field was mapped correctly with the `_mapping` API. +For example, run the following command in the {kib} {kibana-ref}/console-kibana.html[console]. +This will display the field data type of the `service.name` field. + +[source,curl] +---- +GET *apm*/_mapping/field/service.name +---- + +If the `mapping.name.type` is `"text"`, your APM indices were not set up correctly. + +[source,yml] +---- +".ds-metrics-apm.transaction.1m-default-2023.04.12-000038": { + "mappings": { + "service.name": { + "full_name": "service.name", + "mapping": { + "name": { + "type": "text" <1> + } + } + } + } +} +---- +<1> The `service.name` `mapping.name.type` would be `"keyword"` if this field had been set up correctly. + +To fix this problem, install the APM integration by following these steps: + +include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc[leveloffset=+2,tag=install-apm-integration] + +This will reinstall the APM index templates and trigger a data stream index rollover. + +You can verify the correct index templates were installed by running the following command in the {kib} console: + +[source,curl] +---- +GET /_index_template/traces-apm +---- + [float] [[troubleshooting-too-many-transactions]] -=== Too many unique transaction names +== Too many unique transaction names Transaction names are defined in each APM agent; when an APM agent supports a framework, it includes logic for naming the transactions that the framework creates. @@ -118,7 +294,7 @@ See the relevant {apm-agents-ref}[Agent API documentation] to adjust how you're [float] [[troubleshooting-unknown-route]] -=== Unknown route +== Unknown route The <> will only display helpful information when the transactions in your services are named correctly. @@ -139,7 +315,7 @@ You can also use the agent's public API to manually set a name for the transacti [float] [[troubleshooting-fields-unsearchable]] -=== Fields are not searchable +== Fields are not searchable In Elasticsearch, index templates are used to define settings and mappings that determine how fields should be analyzed. The recommended index templates for APM are installed by {fleet} when the Elastic APM integration is installed. @@ -173,7 +349,7 @@ These are dynamic by default, which means they will be indexed and become search [float] [[service-map-rum-connections]] -=== Service Maps: no connection between client and server +== Service Maps: no connection between client and server If the service map is not showing an expected connection between the client and server, it's likely because you haven't configured diff --git a/docs/en/observability/apm/debugging.asciidoc b/docs/en/observability/apm/troubleshooting/debugging.asciidoc similarity index 97% rename from docs/en/observability/apm/debugging.asciidoc rename to docs/en/observability/apm/troubleshooting/debugging.asciidoc index 15bd1f613c..680fc8746a 100644 --- a/docs/en/observability/apm/debugging.asciidoc +++ b/docs/en/observability/apm/troubleshooting/debugging.asciidoc @@ -1,5 +1,5 @@ [[apm-enable-apm-server-debugging]] -=== Enable APM Server binary debugging += Enable APM Server binary debugging ++++ APM Server binary debugging diff --git a/docs/en/observability/apm/troubleshoot-apm.asciidoc b/docs/en/observability/apm/troubleshooting/index.asciidoc similarity index 66% rename from docs/en/observability/apm/troubleshoot-apm.asciidoc rename to docs/en/observability/apm/troubleshooting/index.asciidoc index 5823d9c248..089d18859d 100644 --- a/docs/en/observability/apm/troubleshoot-apm.asciidoc +++ b/docs/en/observability/apm/troubleshooting/index.asciidoc @@ -1,5 +1,9 @@ [[apm-troubleshoot-apm]] -== Troubleshoot += Troubleshooting APM + +++++ +Troubleshooting +++++ This section provides solutions to common questions and problems, and processing and performance guidance. @@ -15,12 +19,11 @@ For additional help with other APM components, see the links below. [float] [[apm-troubleshooting-docs]] -=== Troubleshooting documentation +== Troubleshooting documentation {agent}, the APM UI, and each {apm-agent} has its own troubleshooting guide: * {fleet-guide}/troubleshooting-intro.html[*{fleet} and {agent}* troubleshooting] -* <> * {apm-android-ref}/faq.html[*Android agent* FAQ] * {apm-dotnet-ref-v}/troubleshooting.html[*.NET agent* troubleshooting] * {apm-go-ref-v}/troubleshooting.html[*Go agent* troubleshooting] @@ -34,7 +37,7 @@ For additional help with other APM components, see the links below. [float] [[apm-elastic-support]] -=== Elastic Support +== Elastic Support We offer a support experience unlike any other. Our team of professionals 'speak human and code' and love making your day. @@ -42,19 +45,18 @@ https://www.elastic.co/subscriptions[Learn more about subscriptions]. [float] [[apm-discussion-forum]] -=== Discussion forum +== Discussion forum For additional questions and feature requests, visit our https://discuss.elastic.co/c/apm[discussion forum]. -include::common-problems.asciidoc[] - -include::apm-server-down.asciidoc[] - -include::apm-response-codes.asciidoc[] - -include::processing-performance.asciidoc[] +:leveloffset: +1 -include::{observability-docs-root}/docs/en/observability/apm/debugging.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/troubleshooting/common-problems.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/troubleshooting/apm-server-down.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/troubleshooting/apm-response-codes.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/troubleshooting/processing-performance.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/troubleshooting/debugging.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/troubleshooting/apm-performance-diagnostic.asciidoc[] -include::apm-performance-diagnostic.asciidoc[] \ No newline at end of file +:!leveloffset: diff --git a/docs/en/observability/apm/processing-performance.asciidoc b/docs/en/observability/apm/troubleshooting/processing-performance.asciidoc similarity index 98% rename from docs/en/observability/apm/processing-performance.asciidoc rename to docs/en/observability/apm/troubleshooting/processing-performance.asciidoc index 6e98bbba0f..9db4040411 100644 --- a/docs/en/observability/apm/processing-performance.asciidoc +++ b/docs/en/observability/apm/troubleshooting/processing-performance.asciidoc @@ -1,5 +1,5 @@ [[apm-processing-and-performance]] -=== Processing and performance += Processing and performance APM Server performance depends on a number of factors: memory and CPU available, network latency, transaction sizes, workload patterns, diff --git a/docs/en/observability/apm/upgrading-to-8.x.asciidoc b/docs/en/observability/apm/upgrading-to-8.x.asciidoc index 35bd9536ff..5279a463dc 100644 --- a/docs/en/observability/apm/upgrading-to-8.x.asciidoc +++ b/docs/en/observability/apm/upgrading-to-8.x.asciidoc @@ -80,10 +80,10 @@ See the {stack-ref}/upgrading-elastic-stack.html[{stack} Installation and Upgrad . **Install the APM integration via the {fleet} UI** + -include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm-server.asciidoc[tag=why-apm-integration] +include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc[leveloffset=+2,tag=why-apm-integration] + -- -include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm-server.asciidoc[tag=install-apm-integration] +include::{observability-docs-root}/docs/en/observability/apm/getting-started-apm/get-started-with-apm-server-binary.asciidoc[leveloffset=+2,tag=install-apm-integration] -- . **Install the {version} APM Server release** diff --git a/docs/en/observability/apm-ui/agent-explorer.asciidoc b/docs/en/observability/apm/view-and-analyze/agent-explorer.asciidoc similarity index 95% rename from docs/en/observability/apm-ui/agent-explorer.asciidoc rename to docs/en/observability/apm/view-and-analyze/agent-explorer.asciidoc index 1197b7538e..925c5f62c3 100644 --- a/docs/en/observability/apm-ui/agent-explorer.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/agent-explorer.asciidoc @@ -1,5 +1,5 @@ [[apm-agent-explorer]] -=== APM Agent explorer += APM Agent explorer ++++ Identify deployment details for APM agents diff --git a/docs/en/observability/apm-ui/errors.asciidoc b/docs/en/observability/apm/view-and-analyze/drill-down/errors.asciidoc similarity index 99% rename from docs/en/observability/apm-ui/errors.asciidoc rename to docs/en/observability/apm/view-and-analyze/drill-down/errors.asciidoc index cf6ed775c3..32627e40af 100644 --- a/docs/en/observability/apm-ui/errors.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/drill-down/errors.asciidoc @@ -1,5 +1,5 @@ [[apm-errors]] -=== Errors += Errors TIP: {apm-guide-ref}/data-model-errors.html[Errors] are groups of exceptions with a similar exception or log message. diff --git a/docs/en/observability/apm/view-and-analyze/drill-down/index.asciidoc b/docs/en/observability/apm/view-and-analyze/drill-down/index.asciidoc new file mode 100644 index 0000000000..27ee8cb860 --- /dev/null +++ b/docs/en/observability/apm/view-and-analyze/drill-down/index.asciidoc @@ -0,0 +1,26 @@ +[[apm-ui-drill-down]] += Drill down into application data + +++++ +Drill down into data +++++ + +Notice something awry? Select a service or trace and dive deeper with: + +* <> +* <> +* <> +* <> +* <> +* <> + +:leveloffset: +1 + +include::transactions.asciidoc[] +include::spans.asciidoc[] +include::errors.asciidoc[] +include::metrics.asciidoc[] +include::infrastructure.asciidoc[] +include::logs.asciidoc[] + +:!leveloffset: diff --git a/docs/en/observability/apm-ui/infrastructure.asciidoc b/docs/en/observability/apm/view-and-analyze/drill-down/infrastructure.asciidoc similarity index 97% rename from docs/en/observability/apm-ui/infrastructure.asciidoc rename to docs/en/observability/apm/view-and-analyze/drill-down/infrastructure.asciidoc index 41648d2178..5ab523e232 100644 --- a/docs/en/observability/apm-ui/infrastructure.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/drill-down/infrastructure.asciidoc @@ -1,5 +1,5 @@ [[apm-infrastructure]] -=== Infrastructure += Infrastructure beta::[] diff --git a/docs/en/observability/apm-ui/logs.asciidoc b/docs/en/observability/apm/view-and-analyze/drill-down/logs.asciidoc similarity index 63% rename from docs/en/observability/apm-ui/logs.asciidoc rename to docs/en/observability/apm/view-and-analyze/drill-down/logs.asciidoc index 879ba8fa0e..d65da83508 100644 --- a/docs/en/observability/apm-ui/logs.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/drill-down/logs.asciidoc @@ -1,5 +1,5 @@ [[apm-logs]] -=== Logs += Logs The *Logs* tab shows contextual logs for the selected service. @@ -16,3 +16,15 @@ see {observability-guide}/application-logs.html[log correlation] image::./images/logs.png[Example view of the Logs tab in APM UI in Kibana] TIP: Logs displayed on this page are filtered on `service.name` + +[[apm-logs-correlation]] +== Integrate with logging frameworks + +Elastic APM integrates with popular logging frameworks, making it easy to correlate your logs and traces. +This enables you to: + +* View the context of a log and the parameters provided by a user +* View all logs belonging to a particular trace +* Easily move between logs and traces when debugging application issues + +See the <> guide to get started. diff --git a/docs/en/observability/apm-ui/metrics.asciidoc b/docs/en/observability/apm/view-and-analyze/drill-down/metrics.asciidoc similarity index 98% rename from docs/en/observability/apm-ui/metrics.asciidoc rename to docs/en/observability/apm/view-and-analyze/drill-down/metrics.asciidoc index 987581c9d0..72e30e4c95 100644 --- a/docs/en/observability/apm-ui/metrics.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/drill-down/metrics.asciidoc @@ -1,5 +1,5 @@ [[apm-metrics]] -=== Metrics += Metrics The *Metrics* overview provides APM agent-specific metrics, which lets you perform more in-depth root cause analysis investigations within the APM UI. diff --git a/docs/en/observability/apm-ui/spans.asciidoc b/docs/en/observability/apm/view-and-analyze/drill-down/spans.asciidoc similarity index 98% rename from docs/en/observability/apm-ui/spans.asciidoc rename to docs/en/observability/apm/view-and-analyze/drill-down/spans.asciidoc index 495cb5c3f9..2759849a21 100644 --- a/docs/en/observability/apm-ui/spans.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/drill-down/spans.asciidoc @@ -1,5 +1,5 @@ [[apm-spans]] -=== Trace sample timeline += Trace sample timeline The trace sample timeline visualization is a bird's-eye view of what your application was doing while it was trying to respond to a request. This makes it useful for visualizing where a selected transaction spent most of its time. @@ -24,7 +24,7 @@ image::./images/apm-span-detail.png[Example view of a span detail in the APM UI [float] [[trace-sample-investigate]] -==== Investigate +== Investigate The trace sample timeline features an **Investigate** button which provides a quick way to jump to other areas of the Elastic Observability UI while maintaining the context of the currently selected trace sample. @@ -40,7 +40,7 @@ For example, quickly view: [float] [[distributed-tracing]] -==== Distributed tracing +== Distributed tracing When a trace travels through multiple services it is known as a _distributed trace_. In APM, the colors in a distributed trace represent different services and diff --git a/docs/en/observability/apm-ui/transactions.asciidoc b/docs/en/observability/apm/view-and-analyze/drill-down/transactions.asciidoc similarity index 98% rename from docs/en/observability/apm-ui/transactions.asciidoc rename to docs/en/observability/apm/view-and-analyze/drill-down/transactions.asciidoc index 9a4a7c436b..eae2e0e4ee 100644 --- a/docs/en/observability/apm-ui/transactions.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/drill-down/transactions.asciidoc @@ -1,5 +1,5 @@ [[apm-transactions]] -=== Transactions += Transactions TIP: A {apm-guide-ref}/data-model-transactions.html[transaction] describes an event captured by an Elastic APM agent instrumenting a service. APM agents automatically collect performance metrics on HTTP requests, database queries, and much more. @@ -53,7 +53,7 @@ See <> for more information. [discrete] [[transactions-table]] -=== Transactions table +== Transactions table The *Transactions* table displays a list of _transaction groups_ for the selected service. In other words, this view groups all transactions of the same name together, @@ -78,7 +78,7 @@ refer to the documentation for each {apm-agents-ref}[APM Agent] you've implement [discrete] [[rum-transaction-overview]] -=== RUM Transaction overview +== RUM Transaction overview The transaction overview page is customized for the JavaScript RUM agent. Specifically, the page highlights *page load times* for your service: @@ -93,7 +93,7 @@ are available in the Observability User Experience tab. [discrete] [[transaction-details]] -=== Transaction details +== Transaction details Selecting a transaction group will bring you to the *transaction* details. This page is visually similar to the transaction overview, but it shows data from all transactions within @@ -104,7 +104,7 @@ image::./images/apm-transactions-overview.png[Example view of response time dist [discrete] [[transaction-duration-distribution]] -==== Latency distribution +=== Latency distribution The latency distribution shows a plot of all transaction durations for the given time period. The following screenshot shows a typical distribution @@ -118,7 +118,7 @@ Click and drag to select a latency duration _bucket_ to display up to 500 trace [discrete] [[transaction-trace-sample]] -==== Trace samples +=== Trace samples Trace samples are based on the _bucket_ selection in the *Latency distribution* chart; update the samples by selecting a new _bucket_. @@ -170,7 +170,7 @@ image::./images/apm-logs-tab.png[APM logs tab] [discrete] [[transaction-latency-correlations]] -==== Correlations +=== Correlations Correlations surface attributes of your data that are potentially correlated with high-latency or erroneous transactions. To learn more, see <>. diff --git a/docs/en/observability/apm-ui/advanced-queries.asciidoc b/docs/en/observability/apm/view-and-analyze/filter-and-search/advanced-queries.asciidoc similarity index 95% rename from docs/en/observability/apm-ui/advanced-queries.asciidoc rename to docs/en/observability/apm/view-and-analyze/filter-and-search/advanced-queries.asciidoc index 6b5f20dd27..a37d7cf7d3 100644 --- a/docs/en/observability/apm-ui/advanced-queries.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/filter-and-search/advanced-queries.asciidoc @@ -1,5 +1,9 @@ [[apm-advanced-queries]] -=== Query your data += Use advanced queries on your application data + +++++ +Advanced queries +++++ Querying your APM data is an essential tool that can make finding bottlenecks in your code even more straightforward. @@ -11,7 +15,7 @@ You can select the query bar and hit the down arrow on your keyboard to begin sc [float] [[apm-app-advanced-queries]] -=== Querying in the APM UI +== Querying in the APM UI When querying in the APM UI, you’re merely searching and selecting data from fields in {es} documents. Queries entered into the query bar are also added as parameters to the URL, so it’s easy to share a specific query or view with others. @@ -28,7 +32,7 @@ To learn more about the {kib} query language capabilities, see the {kibana-ref}/ [float] [[apm-app-queries]] -==== APM UI queries +=== APM UI queries APM queries can be handy for removing noise from your data in the <>, <>, <>, <>, and <> views. @@ -46,7 +50,7 @@ Or filter the list by including the service version and the Kubernetes pod it's [float] [[discover-advanced-queries]] -=== Querying in Discover +== Querying in Discover Alternatively, you can query your APM documents in {kibana-ref}/discover.html[*Discover*]. Querying documents in *Discover* works the same way as queries in the APM UI, @@ -54,7 +58,7 @@ and *Discover* supports all of the example APM UI queries shown on this page. [float] [[discover-queries]] -==== Discover queries +=== Discover queries One example where you may want to make use of *Discover* is to view _all_ transactions for an endpoint instead of just a sample. diff --git a/docs/en/observability/apm/cross-cluster-search.asciidoc b/docs/en/observability/apm/view-and-analyze/filter-and-search/cross-cluster-search.asciidoc similarity index 94% rename from docs/en/observability/apm/cross-cluster-search.asciidoc rename to docs/en/observability/apm/view-and-analyze/filter-and-search/cross-cluster-search.asciidoc index 282767474e..5fa57c4030 100644 --- a/docs/en/observability/apm/cross-cluster-search.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/filter-and-search/cross-cluster-search.asciidoc @@ -1,5 +1,9 @@ [[apm-cross-cluster-search]] -=== Cross-cluster search += Cross-cluster search with application data + +++++ +Cross-cluster search +++++ Elastic APM utilizes {es}'s cross-cluster search functionality. Cross-cluster search lets you run a single search request against one or more @@ -10,7 +14,7 @@ and allowing for better performance while managing multiple observability use ca [float] [[apm-set-up-cross-cluster-search]] -==== Set up cross-cluster search +== Set up cross-cluster search *Step 1. Set up remote clusters.* diff --git a/docs/en/observability/apm-ui/filters.asciidoc b/docs/en/observability/apm/view-and-analyze/filter-and-search/filters.asciidoc similarity index 94% rename from docs/en/observability/apm-ui/filters.asciidoc rename to docs/en/observability/apm/view-and-analyze/filter-and-search/filters.asciidoc index b2aa0f0fbd..573bcc0653 100644 --- a/docs/en/observability/apm-ui/filters.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/filter-and-search/filters.asciidoc @@ -1,8 +1,8 @@ [[apm-filters]] -=== Filters += Filter application data ++++ -Filter data +Filters ++++ Global filters are ways you can filter data across the APM UI based on a specific @@ -20,13 +20,13 @@ of information, see <>. [discrete] [[global-time-range]] -==== Global time range +== Global time range The global time range filter in {kib} restricts APM data to a specific time period. [discrete] [[environment-selector]] -==== Service environment filter +== Service environment filter The environment selector is a global filter for `service.environment`. It allows you to view only relevant data and is especially useful for separating development from production environments. diff --git a/docs/en/observability/apm/view-and-analyze/filter-and-search/index.asciidoc b/docs/en/observability/apm/view-and-analyze/filter-and-search/index.asciidoc new file mode 100644 index 0000000000..4b93e3ceee --- /dev/null +++ b/docs/en/observability/apm/view-and-analyze/filter-and-search/index.asciidoc @@ -0,0 +1,22 @@ +[[apm-filter-and-search-data]] += Filter and search application data + +++++ +Filter and search data +++++ + +Because Elastic APM is built on top of the {stack}, you have the full power of Elastic's powerful +search capabilities to filter and search through your application data. Mastering how to filter and +search your data can help you find bottlenecks in your code faster: + +* Use global filters to <> across the APM UI based on a specific time range or environment. +* Use <> on your data to filter on specific pieces of information. +* Use {es}'s <> functionality to search APM data across multiple sources. + +:leveloffset: +1 + +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/filter-and-search/filters.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/filter-and-search/advanced-queries.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/filter-and-search/cross-cluster-search.asciidoc[] + +:!leveloffset: \ No newline at end of file diff --git a/docs/en/observability/apm/view-and-analyze/index.asciidoc b/docs/en/observability/apm/view-and-analyze/index.asciidoc new file mode 100644 index 0000000000..a9a946c0c2 --- /dev/null +++ b/docs/en/observability/apm/view-and-analyze/index.asciidoc @@ -0,0 +1,39 @@ +[[apm-view-and-analyze-data]] += View and analyze data + +After you've started <>, +you can open the APM UI in {kib} to view your data in a variety of visualizations and +start analyzing data. + +The APM UI allows you to monitor your software services and applications in real-time. +You can visualize detailed performance information on your services, +identify and analyze errors, +and monitor host-level and APM agent-specific metrics like JVM and Go runtime metrics. + +Having access to application-level insights with just a few clicks can drastically decrease the time you spend +debugging errors, slow response times, and crashes. + +For example, you can see information about response times, requests per minute, and status codes per endpoint. +You can even dive into a specific request sample and get a complete waterfall view of what your application is spending its time on. +You might see that your bottlenecks are in database queries, cache calls, or external requests. +For each incoming request and each application error, +you can also see contextual information such as the request header, user information, +system values, or custom data that you manually attached to the request. + +To get started with the APM UI: + +* Start with quick, high-level <> that show you the overall health and performance of + your application. +* <> for specific services or traces to get additional insight into + your application. +* Learn how to get the most out of your data by mastering how to <> + in {kib}, getting tips on <>, and taking advantage of + <>. + +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/ui-overview/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/drill-down/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/filter-and-search/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/interpret/index.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/machine-learning.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/agent-explorer.asciidoc[leveloffset=+1] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/settings.asciidoc[leveloffset=+1] diff --git a/docs/en/observability/apm-ui/correlations.asciidoc b/docs/en/observability/apm/view-and-analyze/interpret/correlations.asciidoc similarity index 96% rename from docs/en/observability/apm-ui/correlations.asciidoc rename to docs/en/observability/apm/view-and-analyze/interpret/correlations.asciidoc index b03e3b7895..36ba4cc963 100644 --- a/docs/en/observability/apm-ui/correlations.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/interpret/correlations.asciidoc @@ -1,5 +1,5 @@ [[apm-correlations]] -=== Find transaction latency and failure correlations += Find transaction latency and failure correlations Correlations surface attributes of your data that are potentially correlated with high-latency or erroneous transactions. For example, if you are a site @@ -17,7 +17,7 @@ NOTE: Queries within the APM UI are also applied to the correlations. [discrete] [[correlations-latency]] -==== Find high transaction latency correlations +== Find high transaction latency correlations The correlations on the *Latency correlations* tab help you discover which attributes are contributing to increased transaction latency. @@ -57,7 +57,7 @@ filtered out, you can begin viewing sample traces to continue your investigation [discrete] [[correlations-error-rate]] -==== Find failed transaction correlations +== Find failed transaction correlations The correlations on the *Failed transaction correlations* tab help you discover which attributes are most influential in distinguishing between transaction diff --git a/docs/en/observability/apm-ui/deployment-annotations.asciidoc b/docs/en/observability/apm/view-and-analyze/interpret/deployment-annotations.asciidoc similarity index 98% rename from docs/en/observability/apm-ui/deployment-annotations.asciidoc rename to docs/en/observability/apm/view-and-analyze/interpret/deployment-annotations.asciidoc index 64ec043eac..7c455096a2 100644 --- a/docs/en/observability/apm-ui/deployment-annotations.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/interpret/deployment-annotations.asciidoc @@ -1,5 +1,5 @@ [[apm-transactions-annotations]] -=== Track deployments with annotations += Track deployments with annotations ++++ Track deployments with annotations diff --git a/docs/en/observability/apm/view-and-analyze/interpret/index.asciidoc b/docs/en/observability/apm/view-and-analyze/interpret/index.asciidoc new file mode 100644 index 0000000000..668061b4ff --- /dev/null +++ b/docs/en/observability/apm/view-and-analyze/interpret/index.asciidoc @@ -0,0 +1,33 @@ +[[apm-interpret-data]] += Interpret application data + +++++ +Interpret data +++++ + +Learn how to get the most out of your data using the APM UI. + +[cols="1,1"] +|=== +| <> +| Surface characteristics of your data that are potentially correlated with high-latency or erroneous transactions. + +| <> +| Annotations enable you to easily determine if your deployment has increased response times for an end-user or if the memory/CPU footprint of your application has changed. + +| <> +| Use session tracking via a globally unique identifier to explore the activities of a specific user during a specific period of time. + +| <> +| Learn how your AWS Lambda functions relate to and depend on other services, and get insight into function execution and runtime behavior, like lambda duration, cold start rate, cold start duration, compute usage, memory usage, and more. + +|=== + +:leveloffset: +1 + +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/interpret/correlations.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/interpret/deployment-annotations.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/interpret/mobile-session-explorer.asciidoc[] +include::{observability-docs-root}/docs/en/observability/apm/view-and-analyze/interpret/lambda.asciidoc[] + +:!leveloffset: \ No newline at end of file diff --git a/docs/en/observability/apm-ui/lambda.asciidoc b/docs/en/observability/apm/view-and-analyze/interpret/lambda.asciidoc similarity index 94% rename from docs/en/observability/apm-ui/lambda.asciidoc rename to docs/en/observability/apm/view-and-analyze/interpret/lambda.asciidoc index e0cbf756ce..d72b210e2d 100644 --- a/docs/en/observability/apm-ui/lambda.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/interpret/lambda.asciidoc @@ -1,5 +1,5 @@ [[apm-lambda]] -=== Observe Lambda functions += Observe Lambda functions Elastic APM provides performance and error monitoring for AWS Lambda functions. See how your Lambda functions relate to and depend on other services, and @@ -13,7 +13,7 @@ image::./images/lambda-overview.png[lambda overview] [float] [[apm-lambda-cold-start-info]] -==== Cold starts +== Cold starts A cold start occurs when a Lambda function has not been used for a certain period of time. A lambda worker receives a request to run the function and prepares an execution environment. @@ -21,7 +21,7 @@ Cold starts are an unavoidable byproduct of the serverless world, but visibility [float] [[apm-lambda-cold-start-rate]] -===== Cold start rate +=== Cold start rate The cold start rate (i.e. proportion of requests that experience a cold start) is displayed per service and per transaction. @@ -32,7 +32,7 @@ image::./images/lambda-cold-start-trace.png[lambda cold start trace] [float] [[apm-lambda-cold-start-latency]] -===== Latency distribution correlation +=== Latency distribution correlation The <> feature can be used to visualize the impact of Lambda cold starts on latency--just select the `faas.coldstart` field. @@ -41,7 +41,7 @@ image::./images/lambda-correlations.png[lambda correlations example] [float] [[apm-lambda-service-config]] -==== AWS Lambda function grouping +== AWS Lambda function grouping The default APM agent configuration results in one APM service per AWS Lambda function, where the Lambda function name is the service name. diff --git a/docs/en/observability/apm-ui/mobile-session-explorer.asciidoc b/docs/en/observability/apm/view-and-analyze/interpret/mobile-session-explorer.asciidoc similarity index 95% rename from docs/en/observability/apm-ui/mobile-session-explorer.asciidoc rename to docs/en/observability/apm/view-and-analyze/interpret/mobile-session-explorer.asciidoc index dc1a2fb8cb..62329f7dc4 100644 --- a/docs/en/observability/apm-ui/mobile-session-explorer.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/interpret/mobile-session-explorer.asciidoc @@ -1,12 +1,12 @@ [[apm-mobile-session-explorer]] -=== Explore mobile sessions with Discover += Explore mobile sessions with Discover Elastic Mobile APM provides session tracking by attaching a `session.id`, a guid, to every span and event. This allows for the recall of the activities of a specific user during a specific period of time. The best way recall these data points is using {kibana-ref}/document-explorer.html[Discover]. This guide will explain how to do that. [discrete] [[viewing-sessions-with-discover]] -=== Viewing sessions with Discover +== Viewing sessions with Discover The first step is to find the relevant `session.id`. In this example, we'll walk through investigating a crash. Since all events and spans have `session.id` attributes, a crash is no different. diff --git a/docs/en/observability/apm-ui/machine-learning.asciidoc b/docs/en/observability/apm/view-and-analyze/machine-learning.asciidoc similarity index 96% rename from docs/en/observability/apm-ui/machine-learning.asciidoc rename to docs/en/observability/apm/view-and-analyze/machine-learning.asciidoc index adfff00d5c..6bc0dbc25f 100644 --- a/docs/en/observability/apm-ui/machine-learning.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/machine-learning.asciidoc @@ -1,5 +1,5 @@ [[apm-machine-learning-integration]] -=== Machine learning integration += Machine learning integration ++++ Integrate with machine learning @@ -32,7 +32,7 @@ image::./images/apm-service-map-anomaly.png[Example view of anomaly scores on se [float] [[create-ml-integration]] -=== Enable anomaly detection +== Enable anomaly detection To enable machine learning anomaly detection: @@ -53,7 +53,7 @@ To manage existing jobs, click **Manage jobs**. [float] [[warning-ml-integration]] -=== Anomaly detection warning +== Anomaly detection warning To make machine learning as easy as possible to set up, the APM UI will warn you when filtered to an environment without a machine learning job. @@ -63,7 +63,7 @@ image::./images/apm-anomaly-alert.png[Example view of anomaly alert in the APM U [float] [[unkown-ml-integration]] -=== Unknown service health +== Unknown service health After enabling anomaly detection, service health may display as "Unknown". Here are some reasons why this can occur: diff --git a/docs/en/observability/apm-ui/settings.asciidoc b/docs/en/observability/apm/view-and-analyze/settings.asciidoc similarity index 95% rename from docs/en/observability/apm-ui/settings.asciidoc rename to docs/en/observability/apm/view-and-analyze/settings.asciidoc index e678768fcb..7b3bfa55e4 100644 --- a/docs/en/observability/apm-ui/settings.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/settings.asciidoc @@ -1,5 +1,5 @@ [[apm-settings-in-kibana]] -== APM UI settings += APM UI settings ++++ Settings @@ -10,7 +10,7 @@ If you'd like to adjust the default settings, see {kibana-ref}/apm-settings-kb.h [float] [[apm-indices-settings]] -=== APM Indices +== APM Indices The APM UI uses data views to query APM indices. To change the default APM indices that the APM UI queries, open the APM UI and select **Settings** > **Indices**. @@ -22,7 +22,7 @@ See <> for more information. [float] [[apm-labs]] -=== APM Labs +== APM Labs **APM Labs** allows you to easily try out new features that are technical preview. diff --git a/docs/en/observability/apm-ui/dependencies.asciidoc b/docs/en/observability/apm/view-and-analyze/ui-overview/dependencies.asciidoc similarity index 98% rename from docs/en/observability/apm-ui/dependencies.asciidoc rename to docs/en/observability/apm/view-and-analyze/ui-overview/dependencies.asciidoc index 28072b4439..cf801c042c 100644 --- a/docs/en/observability/apm-ui/dependencies.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/ui-overview/dependencies.asciidoc @@ -1,5 +1,5 @@ [[apm-dependencies]] -=== Dependencies += Dependencies APM agents collect details about external calls made from instrumented services. Sometimes, these external calls resolve into a downstream service that's instrumented -- in these cases, @@ -32,7 +32,7 @@ impacted services to determine why that pattern change has occurred. [float] [[dependencies-operations]] -==== Operations +== Operations beta::[] diff --git a/docs/en/observability/apm/view-and-analyze/ui-overview/index.asciidoc b/docs/en/observability/apm/view-and-analyze/ui-overview/index.asciidoc new file mode 100644 index 0000000000..d371f73c3e --- /dev/null +++ b/docs/en/observability/apm/view-and-analyze/ui-overview/index.asciidoc @@ -0,0 +1,31 @@ +[[apm-ui]] += High-level overviews of application data + +++++ +Overviews +++++ + +For a quick, high-level overview of the health and performance of your application, +start with: + +* <> +* <> +* <> +* <> + +View an individual service: + +* <> +* <> + +:leveloffset: +1 + +include::services.asciidoc[] +include::new-experience-services.asciidoc[] +include::traces.asciidoc[] +include::dependencies.asciidoc[] +include::service-maps.asciidoc[] +include::service-overview.asciidoc[] +include::mobile-service.asciidoc[] + +:!leveloffset: \ No newline at end of file diff --git a/docs/en/observability/apm-ui/mobile-service.asciidoc b/docs/en/observability/apm/view-and-analyze/ui-overview/mobile-service.asciidoc similarity index 94% rename from docs/en/observability/apm-ui/mobile-service.asciidoc rename to docs/en/observability/apm/view-and-analyze/ui-overview/mobile-service.asciidoc index b1d7352429..934b2fa0c5 100644 --- a/docs/en/observability/apm-ui/mobile-service.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/ui-overview/mobile-service.asciidoc @@ -1,5 +1,5 @@ [[apm-mobile-service-overview]] -=== Mobile service overview += Mobile service overview Selecting a mobile service brings you to the *Mobile service overview*. The *Mobile service overview* contains a wide variety of charts and tables that provide @@ -22,7 +22,7 @@ of their mobile application environment and the impact of backend errors and bot [discrete] [[mobile-service-stats]] -=== Quick stats +== Quick stats Understand the impact of slow application load times and variations in application crash rate on user traffic (coming soon). Visualize session and HTTP trends, and see where your users are located--enabling you to optimize your infrastructure deployment and routing topology. @@ -34,7 +34,7 @@ image::./images/mobile-location.png[mobile service overview centered on location [discrete] [[mobile-service-most-used]] -=== Most used +== Most used Optimize your end-user experience and your application QA strategy based on your most used device models and operating system versions. @@ -44,13 +44,13 @@ image::./images/mobile-most-used.png[mobile service overview showing most used d [discrete] [[mobile-throughput-transactions]] -=== Throughput and transactions +== Throughput and transactions include::./service-overview.asciidoc[tag=throughput-transactions] [discrete] [[mobile-error-and-dependencies]] -=== Failed transaction rate and dependencies +== Failed transaction rate and dependencies include::./service-overview.asciidoc[tag=ftr] diff --git a/docs/en/observability/apm-ui/new-experience-services.asciidoc b/docs/en/observability/apm/view-and-analyze/ui-overview/new-experience-services.asciidoc similarity index 100% rename from docs/en/observability/apm-ui/new-experience-services.asciidoc rename to docs/en/observability/apm/view-and-analyze/ui-overview/new-experience-services.asciidoc diff --git a/docs/en/observability/apm-ui/service-maps.asciidoc b/docs/en/observability/apm/view-and-analyze/ui-overview/service-maps.asciidoc similarity index 97% rename from docs/en/observability/apm-ui/service-maps.asciidoc rename to docs/en/observability/apm/view-and-analyze/ui-overview/service-maps.asciidoc index 84f1cb7dd4..ffe627d401 100644 --- a/docs/en/observability/apm-ui/service-maps.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/ui-overview/service-maps.asciidoc @@ -1,5 +1,5 @@ [[apm-service-maps]] -=== Service Map += Service Map A service map is a real-time visual representation of the instrumented services in your application's architecture. It shows you how these services are connected, along with high-level metrics like average transaction duration, @@ -37,7 +37,7 @@ We currently surface two types of service maps: [float] [[service-maps-how]] -=== How do service maps work? +== How do service maps work? Service Maps rely on distributed traces to draw connections between services. As {apm-guide-ref}/apm-distributed-tracing.html[distributed tracing] is enabled out-of-the-box for supported technologies, so are service maps. @@ -47,7 +47,7 @@ distributed tracing will not work, and the connection will not be drawn on the m [float] [[visualize-your-architecture]] -=== Visualize your architecture +== Visualize your architecture Select the **Service Map** tab to get started. By default, all instrumented services and connections are shown. @@ -70,7 +70,7 @@ image::./images/service-maps-java.png[Example view of service maps in the APM UI [float] [[service-map-anomaly-detection]] -=== Anomaly detection with machine learning +== Anomaly detection with machine learning You can create machine learning jobs to calculate anomaly scores on APM transaction durations within the selected service. When these jobs are active, service maps will display a color-coded anomaly indicator based on the detected anomaly score: @@ -90,7 +90,7 @@ To learn how to create a machine learning job, see <> brings you to the *Service overview*. The *Service overview* contains a wide variety of charts and tables that provide @@ -14,7 +14,7 @@ high-level visibility into how a service is performing across your infrastructur [discrete] [[service-time-comparison]] -=== Time series and expected bounds comparison +== Time series and expected bounds comparison For insight into the health of your services, you can compare how a service performs relative to a previous time frame or to the expected bounds from the @@ -48,7 +48,7 @@ environment and you have [discrete] [[service-latency]] -=== Latency +== Latency Response times for the service. You can filter the *Latency* chart to display the average, 95th, or 99th percentile latency times for the service. @@ -58,7 +58,7 @@ image::./images/latency.png[Service latency] [discrete] [[service-throughput-transactions]] -=== Throughput and transactions +== Throughput and transactions // tag::throughput-transactions[] The *Throughput* chart visualizes the average number of transactions per minute for the selected service. @@ -77,7 +77,7 @@ image::./images/traffic-transactions.png[Traffic and transactions] [discrete] [[service-error-rates]] -=== Failed transaction rate and errors +== Failed transaction rate and errors // tag::ftr[] The failed transaction rate represents the percentage of failed transactions from the perspective of the selected service. @@ -104,7 +104,7 @@ image::./images/error-rate.png[failed transaction rate and errors] [discrete] [[service-span-duration]] -=== Span types average duration and dependencies +== Span types average duration and dependencies The *Time spent by span type* chart visualizes each span type's average duration and helps you determine which spans could be slowing down transactions. The "app" label displayed under the @@ -127,7 +127,7 @@ image::./images/spans-dependencies.png[Span type duration and dependencies] [discrete] [[service-cold-start]] -=== Cold start rate +== Cold start rate The cold start rate chart is specific to serverless services, and displays the percentage of requests that trigger a cold start of a serverless function. @@ -140,7 +140,7 @@ functions and Azure functions. [discrete] [[service-instances]] -=== Instances +== Instances The *Instances* table displays a list of all the available service instances within the selected time range. Depending on how the service runs, the instance could be a host or a container. The table displays latency, throughput, @@ -151,7 +151,7 @@ image::./images/all-instances.png[All instances] [discrete] [[service-metadata]] -=== Service metadata +== Service metadata To view metadata relating to the service agent, and if relevant, the container and cloud provider, click on each icon located at the top of the page beside the service name. diff --git a/docs/en/observability/apm-ui/services.asciidoc b/docs/en/observability/apm/view-and-analyze/ui-overview/services.asciidoc similarity index 98% rename from docs/en/observability/apm-ui/services.asciidoc rename to docs/en/observability/apm/view-and-analyze/ui-overview/services.asciidoc index de30fff587..4194e1f087 100644 --- a/docs/en/observability/apm-ui/services.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/ui-overview/services.asciidoc @@ -1,5 +1,5 @@ [[apm-services]] -=== Services += Services *Service* inventory provides a quick, high-level overview of the health and general performance of all instrumented services. @@ -18,7 +18,7 @@ TIP: Want to monitor service logs without instrumenting all your services? Learn [float] [[service-groups]] -==== Service groups +== Service groups beta::[] diff --git a/docs/en/observability/apm-ui/traces.asciidoc b/docs/en/observability/apm/view-and-analyze/ui-overview/traces.asciidoc similarity index 98% rename from docs/en/observability/apm-ui/traces.asciidoc rename to docs/en/observability/apm/view-and-analyze/ui-overview/traces.asciidoc index 4a082198b5..229a08a7e0 100644 --- a/docs/en/observability/apm-ui/traces.asciidoc +++ b/docs/en/observability/apm/view-and-analyze/ui-overview/traces.asciidoc @@ -1,5 +1,5 @@ [[apm-traces]] -=== Traces += Traces TIP: Traces link together related transactions to show an end-to-end performance of how a request was served and which services were part of it. @@ -25,7 +25,7 @@ image::./images/apm-traces.png[Example view of the Traces overview in APM UI in [float] [[trace-explorer]] -==== Trace explorer +== Trace explorer preview::[] diff --git a/docs/en/observability/create-alerts.asciidoc b/docs/en/observability/create-alerts.asciidoc index 8b22a26b31..e5e0d1ce12 100644 --- a/docs/en/observability/create-alerts.asciidoc +++ b/docs/en/observability/create-alerts.asciidoc @@ -162,6 +162,8 @@ xpack.observability.unsafe.alertingExperience.enabled: 'false' ---- +include::apm-alerts.asciidoc[leveloffset=+2] + include::threshold-alert.asciidoc[leveloffset=+2] include::logs-threshold-alert.asciidoc[leveloffset=+2] diff --git a/docs/en/observability/images/icons/check.svg b/docs/en/observability/images/icons/check.svg new file mode 100644 index 0000000000..1145dd301d --- /dev/null +++ b/docs/en/observability/images/icons/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/en/observability/images/icons/cross.svg b/docs/en/observability/images/icons/cross.svg new file mode 100644 index 0000000000..82df3e03d3 --- /dev/null +++ b/docs/en/observability/images/icons/cross.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/en/observability/redirects.asciidoc b/docs/en/observability/redirects.asciidoc index ca06f129e0..e841392382 100644 --- a/docs/en/observability/redirects.asciidoc +++ b/docs/en/observability/redirects.asciidoc @@ -901,3 +901,28 @@ Refer to <>. === AWS Lambda support Refer to <>. + +[role="exclude",id="apm-log-correlation"] +=== Logging integration + +Refer to <>. + +[role="exclude",id="apm-app-troubleshooting"] +=== Troubleshoot the APM UI + +Refer to <>. + +[role="exclude",id="apm-how-to-guides"] +=== Perform common tasks in the APM UI + +Refer to <>. + +[role="exclude",id="apm-span-compression"] +=== Span compression + +Refer to <>. + +[role="exclude",id="apm-features"] +=== Features + +Refer to <>.