Skip to content

Commit 44978d7

Browse files
committed
Merge branch 'main' into feature/translation_EN_ES_jwt.es.md
2 parents 7992644 + 0946bf8 commit 44978d7

File tree

4 files changed

+132
-48
lines changed

4 files changed

+132
-48
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+
```

docs/basics/errors.md

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -136,51 +136,6 @@ struct MyError: DebuggableError {
136136

137137
`DebuggableError` has several other properties like `possibleCauses` and `suggestedFixes` that you can use to improve the debuggability of your errors. Take a look at the protocol itself for more information.
138138

139-
## Stack Traces
140-
141-
Vapor includes support for viewing stack traces for both normal Swift errors and crashes.
142-
143-
### Swift Backtrace
144-
145-
Vapor uses the [SwiftBacktrace](https://github.com/swift-server/swift-backtrace) library to provide stack traces after a fatal error or assertion on Linux. In order for this to work, your app must include debug symbols during compilation.
146-
147-
```sh
148-
swift build -c release -Xswiftc -g
149-
```
150-
151-
### Error Traces
152-
153-
By default, `Abort` will capture the current stack trace when initialized. Your custom error types can achieve this by conforming to `DebuggableError` and storing `StackTrace.capture()`.
154-
155-
```swift
156-
import Vapor
157-
158-
struct MyError: DebuggableError {
159-
var identifier: String
160-
var reason: String
161-
var stackTrace: StackTrace?
162-
163-
init(
164-
identifier: String,
165-
reason: String,
166-
stackTrace: StackTrace? = .capture()
167-
) {
168-
self.identifier = identifier
169-
self.reason = reason
170-
self.stackTrace = stackTrace
171-
}
172-
}
173-
```
174-
175-
When your application's [log level](logging.md#level) is set to `.debug` or lower, error stack traces will be included in log output.
176-
177-
Stack traces will not be captured when the log level is greater than `.debug`. To override this behavior, set `StackTrace.isCaptureEnabled` manually in `configure`.
178-
179-
```swift
180-
// Always capture stack traces, regardless of log level.
181-
StackTrace.isCaptureEnabled = true
182-
```
183-
184139
## Error Middleware
185140

186141
`ErrorMiddleware` is one of the only two middlewares added to your application by default. This middleware converts Swift errors that have been thrown or returned by your route handlers into HTTP responses. Without this middleware, errors thrown will result in the connection being closed without a response.

docs/basics/validation.md

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Validation
22

3-
Vapor's Validation API helps you validate incoming request before using the [Content](content.md) API to decode data.
3+
Vapor's Validation API helps you validate the body and query parameters of an incoming request before using the [Content](content.md) API to decode data.
44

55
## Introduction
66

@@ -219,8 +219,9 @@ Below is a list of the currently supported validators and a brief explanation of
219219
|`.nil`|Value is `null`.|
220220
|`.range(_:)`|Value is within supplied `Range`.|
221221
|`.url`|Contains a valid URL.|
222+
|`.custom(_:, validationClosure: (value) -> Bool)`|Custom, once-off validation.|
222223

223-
Validators can also be combined to build complex validations using operators.
224+
Validators can also be combined to build complex validations using operators. More information on `.custom` validator at [[#Custom Validators]].
224225

225226
|Operator|Position|Description|
226227
|-|-|-|
@@ -232,7 +233,11 @@ Validators can also be combined to build complex validations using operators.
232233

233234
## Custom Validators
234235

235-
Creating a custom validator for zip codes allows you to extend the functionality of the validation framework. In this section, we'll walk you through the steps to create a custom validator for validating zip codes.
236+
There are two ways to create custom validators.
237+
238+
### Extending Validation API
239+
240+
Extending the Validation API is best suited for cases where you plan on using the custom validator in more than one `Content` object. In this section, we'll walk you through the steps to create a custom validator for validating zip codes.
236241

237242
First create a new type to represent the `ZipCode` validation results. This struct will be responsible for reporting whether a given string is a valid zip code.
238243

@@ -289,4 +294,44 @@ Now that you've defined the custom `zipCode` validator, you can use it to valida
289294
```swift
290295
validations.add("zipCode", as: String.self, is: .zipCode)
291296
```
297+
### `Custom` Validator
298+
299+
The `Custom` validator is best suited for cases where you want to validate a property in only one `Content` object. This implementation has the following two advantages compared to extending the Validation API:
300+
301+
- Simpler to implement custom validation logic.
302+
- Shorter syntax.
303+
304+
In this section, we'll walk you through the steps to create a custom validator for checking whether an employee is part of our company by looking at the `nameAndSurname` property.
292305

306+
```swift
307+
let allCompanyEmployees: [String] = [
308+
"Everett Erickson",
309+
"Sabrina Manning",
310+
"Seth Gates",
311+
"Melina Hobbs",
312+
"Brendan Wade",
313+
"Evie Richardson",
314+
]
315+
316+
struct Employee: Content {
317+
var nameAndSurname: String
318+
var email: String
319+
var age: Int
320+
var role: String
321+
322+
static func validations(_ validations: inout Validations) {
323+
validations.add(
324+
"nameAndSurname",
325+
as: String.self,
326+
is: .custom("Validates whether employee is part of XYZ company by looking at name and surname.") { nameAndSurname in
327+
for employee in allCompanyEmployees {
328+
if employee == nameAndSurname {
329+
return true
330+
}
331+
}
332+
return false
333+
}
334+
)
335+
}
336+
}
337+
```

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)