Skip to content

Commit a0d7615

Browse files
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 vapor/vapor#3253 <!-- When this PR is merged, the title and body will be --> <!-- used to generate a release automatically. -->
1 parent 399b55f commit a0d7615

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

β€Ždocs/advanced/tracing.mdβ€Ž

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Tracing
2+
3+
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.
4+
5+
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).
6+
7+
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).
8+
9+
## TracingMiddleware
10+
11+
To automatically create a fully annotated span for each request, add the `TracingMiddleware` to your application.
12+
13+
```swift
14+
app.middleware.use(TracingMiddleware())
15+
```
16+
17+
To get accurate span measurements and ensure that tracing identifiers are passed along correctly to other services, add this middleware before other middlewares.
18+
19+
## Adding Spans
20+
21+
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.
22+
23+
### Automatic Propagation
24+
25+
Vapor has support to automatically propagate spans between middleware and route callbacks. To do so, set the `Application.traceAutoPropagation` property to true during configuration.
26+
27+
```swift
28+
app.traceAutoPropagation = true
29+
```
30+
31+
!!! note
32+
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.
33+
34+
Then spans may be created in the route closure using the ordinary distributed tracing syntax.
35+
36+
```swift
37+
app.get("fetchAndProcess") { req in
38+
let result = try await fetch()
39+
return try await withSpan("getNameParameter") { _ in
40+
try await process(result)
41+
}
42+
}
43+
```
44+
45+
### Manual Propagation
46+
47+
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.
48+
49+
```swift
50+
app.get("fetchAndProcess") { req in
51+
let result = try await fetch()
52+
return try await withSpan("getNameParameter", context: req.serviceContext) { _ in
53+
try await process(result)
54+
}
55+
}
56+
```
57+
58+
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.
59+
60+
```swift
61+
app.get("fetchAndProcess") { req in
62+
try await ServiceContext.withValue(req.serviceContext) {
63+
try await fetch()
64+
return try await process(result)
65+
}
66+
}
67+
```
68+
69+
## NIO Considerations
70+
71+
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**.
72+
73+
```swift
74+
app.get("fetchAndProcessNIO") { req in
75+
withSpan("fetch", context: req.serviceContext) { span in
76+
fetchSomething().map { result in
77+
withSpan("process", context: span.context) { _ in
78+
process(result)
79+
}
80+
}
81+
}
82+
}
83+
```

β€Žmkdocs.ymlβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ nav:
578578
- Services: "advanced/services.md"
579579
- Request: "advanced/request.md"
580580
- APNS: "advanced/apns.md"
581+
- Tracing: "advanced/tracing.md"
581582
- Security:
582583
- Authentication: "security/authentication.md"
583584
- Crypto: "security/crypto.md"

0 commit comments

Comments
Β (0)