非官方的 AWS X-Ray SDK for Swift。
功能性 Beta 版。
目前 SDK 尚不支持采样规则,跟踪功能只能启用或禁用(问题 57)。
AWS X-Ray SDK for Swift 遵循 SemVer 版本规范。在 1.0.0 版本之前,次要版本号的变更可能会引入破坏性更改。
将包依赖项添加到您的 Swift Package Manager 包清单文件 Package.swift
中
.package(url: "https://github.com/pokryfka/aws-xray-sdk-swift.git", upToNextMinor(from: "0.7.1"))
并将 AWSXRaySDK
库添加到您的目标(此处为 AWSXRaySDKExample
)
.target(name: "AWSXRaySDKExample", dependencies: [
.product(name: "AWSXRaySDK", package: "aws-xray-sdk-swift"),
])
创建 XRayRecorder
的实例和新的上下文
import AWSXRaySDK
let recorder = XRayRecorder()
let context = XRayContext()
显式地开始和结束(子)段
let segment = recorder.beginSegment(name: "Segment 1", context: context)
usleep(100_000)
segment.end()
为了方便起见,可以使用闭包
recorder.segment(name: "Segment 2", context: context) { segment in
try? segment.subsegment(name: "Subsegment 2.1") { segment in
_ = segment.subsegment(name: "Subsegment 2.1.1 with Result") { _ -> String in
usleep(100_000)
return "Result"
}
try segment.subsegment(name: "Subsegment 2.1.2 with Error") { _ in
usleep(200_000)
throw ExampleError.test
}
}
}
您可以记录 错误和异常
segment.addError(ExampleError.test)
segment.addException(message: "Test Exception")
请注意,闭包中抛出的 Error
会被记录下来。
您可以记录有关您的应用程序服务或向下游 HTTP API 发出的 HTTP 请求的详细信息,请参阅 HTTP 请求数据
segment.setHTTPRequest(method: .POST, url: "http://www.example.com/api/user")
segment.setHTTPResponse(status: .ok)
段和子段可以包含 注释
segment.setAnnotation(98101, forKey: "zip_code")
和 元数据
segment.setMetadata(["debug": ["test": "Metadata string"]])
事件会在结束后立即发射。
子段必须在父段结束之前创建。
子段可能在父段结束后结束,在这种情况下,它们将被显示为待处理,直到它们结束。
确保在程序退出前关闭记录器
recorder.shutdown()
您可以在关闭之前刷新它
recorder.wait()
或者,如果使用 SwiftNIO,则在提供的 EventLoop
上刷新
try recorder.flush(on: eventLoop).wait()
在 AWS X-Ray 控制台中查看结果
有关完整示例,请参阅 AWSXRaySDKExample/main.swift
。
默认情况下,事件以 UDP 形式发送到 AWS X-Ray 守护程序,该守护程序会缓冲这些事件并将它们中继到 AWS X-Ray API。
自定义发射器必须实现 XRayEmitter
协议
public protocol XRayEmitter {
func send(_ segment: XRayRecorder.Segment)
func flush(_ callback: @escaping (Error?) -> Void)
func shutdown(_ callback: @escaping (Error?) -> Void)
}
它也可以实现 XRayNIOEmitter
public protocol XRayNIOEmitter: XRayEmitter {
func flush(on eventLoop: EventLoop?) -> EventLoopFuture<Void>
}
必须在创建 XRayRecorder
实例时提供发射器
let recorder = XRayRecorder(emitter: XRayNoOpEmitter())
与其他 X-Ray SDK 不同,AWS X-Ray SDK for Swift 中的 XRayRecorder
不会公开(线程本地)当前的 Segment
。
上下文(广义上包括但不限于跟踪上下文)应在 BaggageContext
中显式传递
// the baggage should contain trace context
var baggage: BaggageContext
let segment = recorder.beginSegment(name: "Segment 1", baggage: baggage)
// create subsegment by passing the parent segment baggage
let subsegment = recorder.beginSegment(name: "Subsegment 1.1", baggage: segment.baggage)
// or using segment function
let subsegment2 = segment.beginSubsegment(name: "Subsegment 1.2")
您可以从跟踪标头创建新的 X-Ray 上下文
let context = try XRayContext(tracingHeader: "Root=1-5759e988-bd862e3fe1be46a994272793")
或者使用提供的(或生成的)TraceID、父段和采样决策
let newContext = XRayContext(traceId: .init(), parentId: nil, sampled: true)
您可以在 baggage 中更新 X-Ray 上下文
// empty baggage
var baggage = BaggageContext()
// create new X-Ray context
baggage.xRayContext = XRayContext()
请注意,该主题目前正在 swift-server
社区中讨论
与 swift-server
生态系统中的库的集成正在(将要)使用 AWSXRayInstrument
完成,该工具实现了 swift-tracing 库中定义的 TracingInstrument
。
由于 TracingInstrument
的 API 不稳定,XRayInstrument
的 PoC 实现位于 feature/instrument
分支上。
示例
import AWSXRayInstrument
import TracingInstrumentation
// create and bootstrap the tracer
let instrument = XRayRecorder()
InstrumentationSystem.bootstrap(instrument)
// get the tracer
let tracer = InstrumentationSystem.tracer
// extract the context from HTTP headers
let headers = HTTPHeaders([
("X-Amzn-Trace-Id", "Root=1-5759e988-bd862e3fe1be46a994272793"),
])
var baggage = BaggageContext()
tracer.extract(headers, into: &baggage, using: HTTPHeadersExtractor())
// create new span (aka segment)
var span = tracer.startSpan(named: "Span 1", context: baggage)
库的行为可以使用环境变量进行配置
AWS_XRAY_SDK_ENABLED
- 设置为 false
以禁用跟踪,默认启用。AWS_XRAY_DAEMON_ADDRESS
- X-Ray 守护程序监听器的 IP 地址和端口,默认为 127.0.0.1:2000
。AWS_XRAY_CONTEXT_MISSING
- 配置 SDK 如何处理丢失的上下文RUNTIME_ERROR
- 指示违反了前提条件。LOG_ERROR
- 记录错误并继续(默认)。XRAY_RECORDER_LOG_LEVEL
- 记录器 swift-log 日志级别,默认为 info
。XRAY_EMITTER_LOG_LEVEL
- 发射器 swift-log 日志级别,默认为 info
。或者,可以使用 XRayRecorder.Config
配置 XRayRecorder
,这将覆盖环境变量
let recorder = XRayRecorder(config: .init(enabled: true, logLevel: .debug))
您可以在本地或 Docker 容器中运行 AWS X-Ray 守护程序,请参阅本地运行 X-Ray 守护程序
您可以使用 AWSXRayTesting
中的 XRayLogEmitter
将段“发射”到控制台
import AWSXRaySDK
import AWSXRayTesting
let recorder = XRayRecorder(emitter: XRayLogEmitter())
使用 swiftformat 格式化代码
swiftformat .
考虑创建 Git pre-commit hook
echo 'swiftformat --lint .' > .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
按照“将 AWS Lambda 与 AWS X-Ray 结合使用”中的说明启用跟踪。
注意那
当为采样的请求调用函数时,Lambda 会自动运行守护程序。
确保在每次调用中刷新记录器
private struct ExampleLambdaHandler: EventLoopLambdaHandler {
typealias In = Cloudwatch.ScheduledEvent
typealias Out = Void
private let recorder = XRayRecorder()
private func doWork(on eventLoop: EventLoop) -> EventLoopFuture<Void> {
eventLoop.submit { usleep(100_000) }.map { _ in }
}
func handle(context: Lambda.Context, event: In) -> EventLoopFuture<Void> {
recorder.segment(name: "ExampleLambdaHandler", context: context) {
self.doWork(on: context.eventLoop)
}.flatMap {
self.recorder.flush(on: context.eventLoop)
}
}
}
有关完整示例,请参阅 AWSXRaySDKExampleLambda/main.swift
。
请注意,当 Swift AWS Lambda Runtime 被 instrumentation 时,将不需要创建记录器或刷新它,请参阅 PoC。
AWS X-Ray SDK for Swift 在 Apache 2.0 许可证下获得许可。有关更多信息,请参阅 LICENSE.txt。