Span

编辑

Span 包含有关特定代码路径执行的信息。它们衡量从一个活动开始到结束的时间,并且可以与其他 span 具有父/子关系。

代理会自动检测各种库以捕获应用程序中的这些 span,但您也可以使用代理 API 对特定代码路径进行自定义检测。

除此之外,span 可以包含

  • 一个 transaction.id 属性,该属性引用其父 事务
  • 一个 parent.id 属性,该属性引用其父 span 或事务。
  • 它的开始时间和持续时间。
  • 一个 nametypesubtypeaction — 请参阅 span 名称/类型对齐表,了解按 APM 代理划分的 span 名称模式和示例。此外,一些 APM 代理会针对公共的 span 类型/子类型规范进行测试。
  • 一个可选的 堆栈跟踪。堆栈跟踪由堆栈帧组成,堆栈帧表示调用堆栈上的函数调用。它们包括函数名称、文件名和路径、行号等属性。

大多数代理将关键字字段(如 span.id)限制为 1024 个字符,并将非关键字字段(如 span.start.us)限制为 10,000 个字符。

丢弃的 span
编辑

出于性能原因,APM 代理可以选择采样或有意省略 span。这有助于防止边缘情况,例如超过 100 个 span 的长时间运行的事务,否则会使代理和 APM Server 都过载。发生这种情况时,应用程序 UI 将显示丢弃的 span 数量。

要配置每个事务记录的 span 数量,请参阅相关的代理文档

丢失的 span
编辑

代理将 span 与其事务分开流式传输到 APM Server。因此,不可预见的错误可能会导致 span 丢失。代理知道一个事务应该有多少个 span;如果预期 span 的数量不等于 APM Server 收到的 span 的数量,应用程序 UI 将计算差值并显示一条消息。

数据流
编辑

Span 与事务一起存储在以下数据流中

  • 应用程序跟踪:traces-apm-<namespace>
  • RUM 和 iOS 代理应用程序跟踪:traces-apm.rum-<namespace>

请参阅 数据流 以了解更多信息。

Span 文档示例
编辑

此示例显示了在 Elasticsearch 中索引时 span 文档的样子。

展开 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"
        }
    }
]
Span 压缩
编辑

在某些情况下,APM 代理可能会在一个事务中收集大量非常相似或相同的 span。例如,如果在循环内捕获 span,或者在未优化的 SQL 查询中使用多个查询而不是连接来获取相关数据时,可能会发生这种情况。在这种情况下,每个事务的 span 上限(默认情况下为 500 个 span)可能会很快达到,导致代理停止捕获给定事务的潜在更相关的 span。

这种重复的相似 span 本身通常不是非常相关,尤其是当它们持续时间很短时。它们还会使 UI 变得混乱,并导致处理和存储开销。

为了解决这个问题,APM 代理可以将这些 span 压缩为一个 span。压缩后的 span 会保留大部分原始 span 信息,例如总持续时间和它表示的 span 数量。

无论压缩策略如何,如果满足以下条件,则 span 有资格进行压缩

  • 它尚未传播其跟踪上下文。
  • 是一个退出 span(例如数据库查询 span)。
  • 其结果不是 "failure"
压缩策略编辑

APM 代理可以在两个策略之间选择,以确定是否可以压缩两个相邻的 span。这两个策略的好处是,只需要在内存中保留一个先前的 span。这对于确保代理不需要大量内存来启用 span 压缩非常重要。

同类策略编辑

如果两个相邻的 span 具有相同的

  • span 类型
  • span 子类型
  • destination.service.resource(例如,数据库名称)
精确匹配策略编辑

如果两个相邻的 span 具有相同的

  • span 名称
  • span 类型
  • span 子类型
  • destination.service.resource(例如,数据库名称)
设置编辑

代理具有配置设置,用于定义这两种策略的 span 持续时间上限阈值。“同类”策略的默认限制为 0 毫秒,这意味着默认情况下禁用“同类”策略。“精确匹配”策略的默认限制为 50 毫秒。持续时间较长的 span 不会被压缩。有关详细信息,请参阅代理文档。

代理支持编辑

以下代理支持 span 压缩