跨度
编辑跨度
编辑跨度 包含有关特定代码路径执行的信息。它们测量从活动开始到结束的时间,并且可以与其他跨度具有父子关系。
代理会自动检测各种库以从您的应用程序中捕获这些跨度,但您也可以使用代理 API 对特定代码路径进行自定义检测。
除其他事项外,跨度可以包含
- 一个
transaction.id
属性,它引用其父事务。 - 一个
parent.id
属性,它引用其父跨度或事务。 - 其开始时间和持续时间。
- 一个
name
、type
、subtype
和action
——有关跨度名称模式和 APM 代理的示例,请参阅跨度名称/类型对齐 表格。此外,一些 APM 代理会针对公共跨度类型/子类型规范进行测试。 - 一个可选的
stack trace
(堆栈跟踪)。堆栈跟踪由堆栈帧组成,这些堆栈帧表示调用堆栈上的函数调用。它们包括函数名称、文件名和路径、行号等属性。
大多数代理将关键字字段(如 span.id
)限制为 1024 个字符,并将非关键字字段(如 span.start.us
)限制为 10,000 个字符。
丢弃的跨度
编辑出于性能原因,APM 代理可以选择有目的地采样或省略跨度。这对于防止极端情况(例如,具有超过 100 个跨度的长时间运行的事务)非常有用,否则这些情况会使代理和 APM 服务器都过载。发生这种情况时,应用程序 UI 将显示已丢弃的跨度数量。
要配置每个事务记录的跨度数量,请参阅相关的代理文档
- Android:尚不支持
- Go:
ELASTIC_APM_TRANSACTION_MAX_SPANS
- iOS:尚不支持
- Java:
transaction_max_spans
- .NET:
TransactionMaxSpans
- Node.js:
transactionMaxSpans
- PHP:
transaction_max_spans
- Python:
transaction_max_spans
- Ruby:
transaction_max_spans
缺失的跨度
编辑代理将跨度流式传输到 APM 服务器,这与它们的事务分开。因此,不可预见的错误可能会导致跨度丢失。代理知道事务应该有多少个跨度;如果预期跨度数与 APM 服务器接收到的跨度数不相等,则应用程序 UI 将计算差值并显示消息。
数据流
编辑跨度与事务一起存储在以下数据流中
- 应用程序跟踪:
traces-apm-<namespace>
- RUM 和 iOS 代理应用程序跟踪:
traces-apm.rum-<namespace>
请参阅数据流了解更多信息。
示例跨度文档
编辑此示例显示跨度文档在 Elasticsearch 中编入索引时的外观。
展开 Elasticsearch 文档
[ { "@timestamp": "2017-05-30T18:53:27.154Z", "agent": { "name": "elastic-node", "version": "3.14.0" }, "ecs": { "version": "1.12.0" }, "event": { "outcome": "unknown" }, "http": { "request": { "method": "GET" }, "response": { "status_code": 200 } }, "labels": { "span_tag": "something" }, "observer": { "hostname": "ix.lan", "type": "apm-server", "version": "8.0.0" }, "parent": { "id": "945254c567a5417e" }, "processor": { "event": "span", "name": "transaction" }, "service": { "environment": "staging", "name": "1234_service-12a3" }, "span": { "action": "query", "db": { "instance": "customers", "statement": "SELECT * FROM product_types WHERE user_id=?", "type": "sql", "user": { "name": "readonly_user" } }, "duration": { "us": 3781 }, "http": { "method": "GET", "response": { "status_code": 200 } }, "http.url.original": "https://127.0.0.1:8000", "id": "0aaaaaaaaaaaaaaa", "name": "SELECT FROM product_types", "stacktrace": [ { "abs_path": "net.js", "context": { "post": [ " ins.currentTransaction = prev", " return result", "}" ], "pre": [ " var trans = this.currentTransaction", "" ] }, "exclude_from_grouping": false, "filename": "net.js", "function": "onread", "library_frame": true, "line": { "column": 4, "context": "line3", "number": 547 }, "module": "some module", "vars": { "key": "value" } }, { "exclude_from_grouping": false, "filename": "my2file.js", "line": { "number": 10 } } ], "start": { "us": 2830 }, "subtype": "postgresql", "sync": false, "type": "db" }, "timestamp": { "us": 1496170407154000 }, "trace": { "id": "945254c567a5417eaaaaaaaaaaaaaaaa" }, "transaction": { "id": "945254c567a5417e" }, "url": { "original": "https://127.0.0.1:8000" } }, { "@timestamp": "2017-05-30T18:53:42.281Z", "agent": { "name": "js-base", "version": "1.3" }, "destination": { "address": "0:0::0:1", "ip": "0:0::0:1", "port": 5432 }, "ecs": { "version": "1.12.0" }, "event": { "outcome": "unknown" }, "observer": { "ephemeral_id": "2f13d8fa-83cd-4356-8123-aabfb47a1808", "hostname": "goat", "id": "17ad47dd-5671-4c89-979f-ef4533565ba2", "type": "apm-server", "version": "8.0.0" }, "parent": { "id": "85925e55b43f4342" }, "processor": { "event": "span", "name": "transaction" }, "service": { "environment": "staging", "name": "serviceabc" }, "span": { "action": "query.custom", "db": { "instance": "customers", "statement": "SELECT * FROM product_types WHERE user_id=?", "type": "sql", "user": { "name": "readonly_user" } }, "destination": { "service": { "name": "postgresql", "resource": "postgresql", "type": "db" } }, "duration": { "us": 3781 }, "id": "15aaaaaaaaaaaaaa", "name": "SELECT FROM product_types", "start": { "us": 2830 }, "subtype": "postgresql", "type": "db.postgresql.query" }, "timestamp": { "us": 1496170422281000 }, "trace": { "id": "85925e55b43f4342aaaaaaaaaaaaaaaa" }, "transaction": { "id": "85925e55b43f4342" } }, { "@timestamp": "2017-05-30T18:53:27.154Z", "agent": { "name": "elastic-node", "version": "3.14.0" }, "ecs": { "version": "1.12.0" }, "event": { "outcome": "unknown" }, "observer": { "ephemeral_id": "2f13d8fa-83cd-4356-8123-aabfb47a1808", "hostname": "goat", "id": "17ad47dd-5671-4c89-979f-ef4533565ba2", "type": "apm-server", "version": "8.0.0" }, "parent": { "id": "945254c567a5417e" }, "processor": { "event": "span", "name": "transaction" }, "service": { "environment": "staging", "name": "1234_service-12a3" }, "span": { "duration": { "us": 32592 }, "id": "1aaaaaaaaaaaaaaa", "name": "GET /api/types", "start": { "us": 0 }, "subtype": "external", "type": "request" }, "timestamp": { "us": 1496170407154000 }, "trace": { "id": "945254c567a5417eaaaaaaaaaaaaaaaa" }, "transaction": { "id": "945254c567a5417e" } }, { "@timestamp": "2017-05-30T18:53:27.154Z", "agent": { "name": "elastic-node", "version": "3.14.0" }, "ecs": { "version": "1.12.0" }, "event": { "outcome": "unknown" }, "observer": { "ephemeral_id": "2f13d8fa-83cd-4356-8123-aabfb47a1808", "hostname": "goat", "id": "17ad47dd-5671-4c89-979f-ef4533565ba2", "type": "apm-server", "version": "8.0.0" }, "parent": { "id": "945254c567a5417e" }, "processor": { "event": "span", "name": "transaction" }, "service": { "environment": "staging", "name": "1234_service-12a3" }, "span": { "action": "post", "duration": { "us": 3564 }, "id": "2aaaaaaaaaaaaaaa", "name": "GET /api/types", "start": { "us": 1845 }, "subtype": "http", "type": "request" }, "timestamp": { "us": 1496170407154000 }, "trace": { "id": "945254c567a5417eaaaaaaaaaaaaaaaa" }, "transaction": { "id": "945254c567a5417e" } }, { "@timestamp": "2017-05-30T18:53:27.154Z", "agent": { "name": "elastic-node", "version": "3.14.0" }, "child": { "id": [ "4aaaaaaaaaaaaaaa" ] }, "ecs": { "version": "1.12.0" }, "event": { "outcome": "unknown" }, "observer": { "ephemeral_id": "2f13d8fa-83cd-4356-8123-aabfb47a1808", "hostname": "goat", "id": "17ad47dd-5671-4c89-979f-ef4533565ba2", "type": "apm-server", "version": "8.0.0" }, "parent": { "id": "945254c567a5417e" }, "processor": { "event": "span", "name": "transaction" }, "service": { "environment": "staging", "name": "1234_service-12a3" }, "span": { "duration": { "us": 13980 }, "id": "3aaaaaaaaaaaaaaa", "name": "GET /api/types", "start": { "us": 0 }, "type": "request" }, "timestamp": { "us": 1496170407154000 }, "trace": { "id": "945254c567a5417eaaaaaaaaaaaaaaaa" }, "transaction": { "id": "945254c567a5417e" } } ]
跨度压缩
编辑在某些情况下,APM 代理可能会在一个事务中收集大量非常相似或相同的跨度。例如,如果在循环内捕获跨度,或者在使用多个查询而不是连接来获取相关数据的未优化的 SQL 查询中,就会发生这种情况。在这种情况下,每个事务的跨度上限(默认为 500 个跨度)可能会很快达到,导致代理停止捕获给定事务的可能更相关的跨度。
这种重复的相似跨度本身通常不太相关,尤其是在它们的持续时间非常短的情况下。它们还会使 UI 混乱,并导致处理和存储开销。
为了解决这个问题,APM 代理可以将这些跨度压缩成单个跨度。压缩的跨度保留了大部分原始跨度信息,例如总持续时间及其表示的跨度数量。
无论压缩策略如何,如果满足以下条件,跨度都符合压缩条件:
- 它没有传播其跟踪上下文。
- 是出口跨度(例如数据库查询跨度)。
- 其结果不是
"failure"
。
APM 代理可以在两种策略之间进行选择,以确定是否可以压缩两个相邻的跨度。两种策略都有一个优点,即只需要将一个之前的跨度保留在内存中。这对于确保代理不需要大量内存来启用跨度压缩非常重要。
如果两个相邻的跨度具有相同的以下属性,则代理将选择此策略:
- 跨度类型
- 跨度子类型
-
destination.service.resource
(例如数据库名称)
如果两个相邻的跨度具有相同的以下属性,则代理将选择此策略:
- 跨度名称
- 跨度类型
- 跨度子类型
-
destination.service.resource
(例如数据库名称)
代理具有配置设置,用于根据两种策略定义跨度持续时间的上限阈值。“相同类型”策略的默认限制为 0 毫秒,这意味着默认情况下“相同类型”策略处于禁用状态。“完全匹配”策略的默认限制为 50 毫秒。持续时间更长的跨度不会被压缩。请参阅代理文档以了解详细信息。
这些代理支持跨度压缩
代理 | 相同类型配置 | 完全匹配配置 |
---|---|---|
Go 代理 |
||
Java 代理 |
||
.NET 代理 |
||
Node.js 代理 |
||
Python 代理 |