跳到内容

追踪#

追踪(Tracing)是监控和调试分布式系统的强大工具。Vapor 的追踪 API 让开发者可以轻松地追踪请求的生命周期、传播元数据,并与 OpenTelemetry 等主流后端集成。

Vapor 的追踪 API 构建于 swift-distributed-tracing 之上,这意味着它与 swift-distributed-tracing 的所有后端实现兼容。

如果你不熟悉 Swift 中的追踪和 span,请查阅 OpenTelemetry Trace 文档swift-distributed-tracing 文档

TracingMiddleware#

要为每个请求自动创建一个带有完整注解的 span,请将 TracingMiddleware 添加到你的应用程序中。

app.middleware.use(TracingMiddleware())

为了获得准确的 span 度量,并确保追踪标识符能被正确传递给其他服务,请将此中间件添加在其他中间件之前。

添加 Span#

在路由处理程序中添加 span 时,最好将它们与顶层的请求 span 相关联。这被称为“span 传播”,可以通过两种不同的方式来处理:自动或手动。

自动传播#

Vapor 支持在中间件和路由回调之间自动传播 span。要启用此功能,请在配置期间将 Application.traceAutoPropagation 属性设置为 true。

app.traceAutoPropagation = true

Note

在高吞吐量且追踪需求较小的 API 上启用自动传播可能会降低性能,因为无论是否创建了 span,都必须为每个路由处理程序恢复请求的 span 元数据。

然后就可以在路由闭包中使用普通的分布式追踪语法来创建 span 了。

app.get("fetchAndProcess") { req in
    let result = try await fetch()
    return try await withSpan("getNameParameter") { _ in
        try await process(result)
    }
}

手动传播#

为了避免自动传播带来的性能影响,你可以在必要时手动恢复 span 元数据。TracingMiddleware 会自动设置一个 Request.serviceContext 属性,你可以直接在 withSpancontext 参数中使用它。

app.get("fetchAndProcess") { req in
    let result = try await fetch()
    return try await withSpan("getNameParameter", context: req.serviceContext) { _ in
        try await process(result)
    }
}

要在不创建 span 的情况下恢复 span 元数据,可以使用 ServiceContext.withValue。如果你知道下游的异步库会自行发出追踪 span,并且这些 span 应嵌套在父级请求 span 之下,这将非常有用。

app.get("fetchAndProcess") { req in
    try await ServiceContext.withValue(req.serviceContext) {
        try await fetch()
        return try await process(result)
    }
}

NIO 相关注意事项#

由于 swift-distributed-tracing 使用 TaskLocal properties 来传播,因此每当跨越 NIO EventLoopFuture 边界时,你都必须手动重新恢复上下文,以确保 span 能正确关联。无论是否启用了自动传播,这一点都是必要的

app.get("fetchAndProcessNIO") { req in
    withSpan("fetch", context: req.serviceContext) { span in
        fetchSomething().map { result in
            withSpan("process", context: span.context) { _ in
                process(result)
            }
        }
    }
}
编辑此页