mirror of https://github.com/vapor/docs.git
Adds tracing documentation (#1039)
<!-- 🚀 Thank you for contributing! --> <!-- Describe your changes clearly and use examples if possible. --> Adds new Tracing chapter to document API introduced in https://github.com/vapor/vapor/pull/3253 <!-- When this PR is merged, the title and body will be --> <!-- used to generate a release automatically. -->
This commit is contained in:
parent
399b55f27f
commit
a0d7615b8d
|
|
@ -0,0 +1,83 @@
|
||||||
|
# Tracing
|
||||||
|
|
||||||
|
Tracing is a powerful tool for monitoring and debugging distributed systems. Vapor's tracing API allows developers to easily track request lifecycles, propagate metadata, and integrate with popular backends like OpenTelemetry.
|
||||||
|
|
||||||
|
Vapor's tracing API is built on top of [swift-distributed-tracing](https://github.com/apple/swift-distributed-tracing), which means it is compatible with all of swift-distributed-tracing's [backend implementations](https://github.com/apple/swift-distributed-tracing/blob/main/README.md#tracing-backends).
|
||||||
|
|
||||||
|
If you are unfamiliar with tracing and spans in Swift, review the [OpenTelemetry Trace documentation](https://opentelemetry.io/docs/concepts/signals/traces/) and [swift-distributed-tracing documentation](https://swiftpackageindex.com/apple/swift-distributed-tracing/main/documentation/tracing).
|
||||||
|
|
||||||
|
## TracingMiddleware
|
||||||
|
|
||||||
|
To automatically create a fully annotated span for each request, add the `TracingMiddleware` to your application.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
app.middleware.use(TracingMiddleware())
|
||||||
|
```
|
||||||
|
|
||||||
|
To get accurate span measurements and ensure that tracing identifiers are passed along correctly to other services, add this middleware before other middlewares.
|
||||||
|
|
||||||
|
## Adding Spans
|
||||||
|
|
||||||
|
When adding spans to route handlers, it's ideal for them to be associated with the top-level request span. This is referred to as "span propagation" and can be handled in two different ways: automatic or manual.
|
||||||
|
|
||||||
|
### Automatic Propagation
|
||||||
|
|
||||||
|
Vapor has support to automatically propagate spans between middleware and route callbacks. To do so, set the `Application.traceAutoPropagation` property to true during configuration.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
app.traceAutoPropagation = true
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Enabling auto-propagation may degrade performance on high-throughput APIs with minimal tracing needs, since request span metadata must be restored for every route handler regardless of whether spans are created.
|
||||||
|
|
||||||
|
Then spans may be created in the route closure using the ordinary distributed tracing syntax.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
app.get("fetchAndProcess") { req in
|
||||||
|
let result = try await fetch()
|
||||||
|
return try await withSpan("getNameParameter") { _ in
|
||||||
|
try await process(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Propagation
|
||||||
|
|
||||||
|
To avoid the performance implications of automatic propagation, you may manually restore span metadata where necessary. `TracingMiddleware` automatically sets a `Request.serviceContext` property which may be used directly in `withSpan`'s `context` parameter.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
app.get("fetchAndProcess") { req in
|
||||||
|
let result = try await fetch()
|
||||||
|
return try await withSpan("getNameParameter", context: req.serviceContext) { _ in
|
||||||
|
try await process(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To restore the span metadata without creating a span, use `ServiceContext.withValue`. This is valuable if you know that downstream async libraries emit their own tracing spans, and those should be nested underneath the parent request span.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
app.get("fetchAndProcess") { req in
|
||||||
|
try await ServiceContext.withValue(req.serviceContext) {
|
||||||
|
try await fetch()
|
||||||
|
return try await process(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## NIO Considerations
|
||||||
|
|
||||||
|
Because `swift-distributed-tracing` uses [`TaskLocal properties`](https://developer.apple.com/documentation/swift/tasklocal) to propagate, you must manually re-restore the context whenever you cross `NIO EventLoopFuture` boundaries to ensure spans are linked correctly. **This is necessary regardless of whether automatic propagation is enabled**.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
app.get("fetchAndProcessNIO") { req in
|
||||||
|
withSpan("fetch", context: req.serviceContext) { span in
|
||||||
|
fetchSomething().map { result in
|
||||||
|
withSpan("process", context: span.context) { _ in
|
||||||
|
process(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -578,6 +578,7 @@ nav:
|
||||||
- Services: "advanced/services.md"
|
- Services: "advanced/services.md"
|
||||||
- Request: "advanced/request.md"
|
- Request: "advanced/request.md"
|
||||||
- APNS: "advanced/apns.md"
|
- APNS: "advanced/apns.md"
|
||||||
|
- Tracing: "advanced/tracing.md"
|
||||||
- Security:
|
- Security:
|
||||||
- Authentication: "security/authentication.md"
|
- Authentication: "security/authentication.md"
|
||||||
- Crypto: "security/crypto.md"
|
- Crypto: "security/crypto.md"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue