Skip to content

Commit 3a9b0e0

Browse files
committed
[Only for discussion] Simple/naive tracing
1 parent 7dc119c commit 3a9b0e0

File tree

3 files changed

+85
-18
lines changed

3 files changed

+85
-18
lines changed

Package.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ let package = Package(
4545
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.26.0"),
4646
.package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.24.0"),
4747
.package(url: "https://github.com/apple/swift-log.git", from: "1.6.0"),
48+
.package(url: "https://github.com/apple/swift-distributed-tracing.git", from: "1.2.2"),
4849
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"),
4950
.package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"),
5051
],
@@ -71,6 +72,7 @@ let package = Package(
7172
.product(name: "NIOSOCKS", package: "swift-nio-extras"),
7273
.product(name: "NIOTransportServices", package: "swift-nio-transport-services"),
7374
.product(name: "Logging", package: "swift-log"),
75+
.product(name: "Tracing", package: "swift-distributed-tracing"),
7476
.product(name: "Atomics", package: "swift-atomics"),
7577
.product(name: "Algorithms", package: "swift-algorithms"),
7678
],

Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+execute.swift

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,22 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
import Logging
16+
import Tracing
1617
import NIOCore
1718
import NIOHTTP1
1819

1920
import struct Foundation.URL
2021

22+
private struct HTTPHeadersInjector: Injector, @unchecked Sendable {
23+
static let shared: HTTPHeadersInjector = HTTPHeadersInjector()
24+
25+
private init() {}
26+
27+
func inject(_ value: String, forKey name: String, into headers: inout HTTPHeaders) {
28+
headers.add(name: name, value: value)
29+
}
30+
}
31+
2132
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
2233
extension HTTPClient {
2334
/// Execute arbitrary HTTP requests.
@@ -36,12 +47,27 @@ extension HTTPClient {
3647
deadline: NIODeadline,
3748
logger: Logger? = nil
3849
) async throws -> HTTPClientResponse {
39-
try await self.executeAndFollowRedirectsIfNeeded(
40-
request,
41-
deadline: deadline,
42-
logger: logger ?? Self.loggingDisabled,
43-
redirectState: RedirectState(self.configuration.redirectConfiguration.mode, initialURL: request.url)
44-
)
50+
func perform(request: HTTPClientRequest) async throws -> HTTPClientResponse {
51+
try await self.executeAndFollowRedirectsIfNeeded(
52+
request,
53+
deadline: deadline,
54+
logger: logger ?? Self.loggingDisabled,
55+
redirectState: RedirectState(self.configuration.redirectConfiguration.mode, initialURL: request.url)
56+
)
57+
}
58+
if let tracer = self.configuration.tracer {
59+
return try await tracer.withSpan("HTTPClient.execute") { span in
60+
var request = request
61+
tracer.inject(
62+
span.context,
63+
into: &request.headers,
64+
using: HTTPHeadersInjector.shared
65+
)
66+
return try await perform(request: request)
67+
}
68+
} else {
69+
return try await perform(request: request)
70+
}
4571
}
4672
}
4773

Sources/AsyncHTTPClient/HTTPClient.swift

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import Atomics
1616
import Foundation
1717
import Logging
18+
import Tracing
1819
import NIOConcurrencyHelpers
1920
import NIOCore
2021
import NIOHTTP1
@@ -807,7 +808,7 @@ public final class HTTPClient: Sendable {
807808
public struct Configuration {
808809
/// TLS configuration, defaults to `TLSConfiguration.makeClientConfiguration()`.
809810
public var tlsConfiguration: Optional<TLSConfiguration>
810-
811+
811812
/// Sometimes it can be useful to connect to one host e.g. `x.example.com` but
812813
/// request and validate the certificate chain as if we would connect to `y.example.com`.
813814
/// ``dnsOverride`` allows to do just that by mapping host names which we will request and validate the certificate chain, to a different
@@ -817,7 +818,7 @@ public final class HTTPClient: Sendable {
817818
/// `url` of `https://example.com/`, the ``HTTPClient`` will actually open a connection to `localhost` instead of `example.com`.
818819
/// ``HTTPClient`` will still request certificates from the server for `example.com` and validate them as if we would connect to `example.com`.
819820
public var dnsOverride: [String: String] = [:]
820-
821+
821822
/// Enables following 3xx redirects automatically.
822823
///
823824
/// Following redirects are supported:
@@ -841,24 +842,24 @@ public final class HTTPClient: Sendable {
841842
/// Ignore TLS unclean shutdown error, defaults to `false`.
842843
@available(
843844
*,
844-
deprecated,
845-
message:
845+
deprecated,
846+
message:
846847
"AsyncHTTPClient now correctly supports handling unexpected SSL connection drops. This property is ignored"
847848
)
848849
public var ignoreUncleanSSLShutdown: Bool {
849850
get { false }
850851
set {}
851852
}
852-
853+
853854
/// What HTTP versions to use.
854855
///
855856
/// Set to ``HTTPVersion-swift.struct/automatic`` by default which will use HTTP/2 if run over https and the server supports it, otherwise HTTP/1
856857
public var httpVersion: HTTPVersion
857-
858+
858859
/// Whether ``HTTPClient`` will let Network.framework sit in the `.waiting` state awaiting new network changes, or fail immediately. Defaults to `true`,
859860
/// which is the recommended setting. Only set this to `false` when attempting to trigger a particular error path.
860861
public var networkFrameworkWaitForConnectivity: Bool
861-
862+
862863
/// The maximum number of times each connection can be used before it is replaced with a new one. Use `nil` (the default)
863864
/// if no limit should be applied to each connection.
864865
///
@@ -870,20 +871,35 @@ public final class HTTPClient: Sendable {
870871
}
871872
}
872873
}
873-
874+
874875
/// Whether ``HTTPClient`` will use Multipath TCP or not
875876
/// By default, don't use it
876877
public var enableMultipath: Bool
877-
878+
878879
/// A method with access to the HTTP/1 connection channel that is called when creating the connection.
879880
public var http1_1ConnectionDebugInitializer: (@Sendable (Channel) -> EventLoopFuture<Void>)?
880-
881+
881882
/// A method with access to the HTTP/2 connection channel that is called when creating the connection.
882883
public var http2ConnectionDebugInitializer: (@Sendable (Channel) -> EventLoopFuture<Void>)?
883-
884+
884885
/// A method with access to the HTTP/2 stream channel that is called when creating the stream.
885886
public var http2StreamChannelDebugInitializer: (@Sendable (Channel) -> EventLoopFuture<Void>)?
886-
887+
888+
private var anyTracer: (any Sendable)?
889+
890+
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
891+
public var tracer: (any Tracer)? {
892+
get {
893+
guard let anyTracer else {
894+
return nil
895+
}
896+
return anyTracer as! (any Tracer)?
897+
}
898+
set {
899+
self.anyTracer = newValue
900+
}
901+
}
902+
887903
public init(
888904
tlsConfiguration: TLSConfiguration? = nil,
889905
redirectConfiguration: RedirectConfiguration? = nil,
@@ -903,6 +919,29 @@ public final class HTTPClient: Sendable {
903919
self.networkFrameworkWaitForConnectivity = true
904920
self.enableMultipath = false
905921
}
922+
923+
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
924+
public init(
925+
tlsConfiguration: TLSConfiguration? = nil,
926+
redirectConfiguration: RedirectConfiguration? = nil,
927+
timeout: Timeout = Timeout(),
928+
connectionPool: ConnectionPool = ConnectionPool(),
929+
proxy: Proxy? = nil,
930+
ignoreUncleanSSLShutdown: Bool = false,
931+
decompression: Decompression = .disabled,
932+
tracer: (any Tracer)? = InstrumentationSystem.tracer
933+
) {
934+
self.init(
935+
tlsConfiguration: tlsConfiguration,
936+
redirectConfiguration: redirectConfiguration,
937+
timeout: timeout,
938+
connectionPool: connectionPool,
939+
proxy: proxy,
940+
ignoreUncleanSSLShutdown: ignoreUncleanSSLShutdown,
941+
decompression: decompression
942+
)
943+
self.anyTracer = tracer
944+
}
906945

907946
public init(
908947
tlsConfiguration: TLSConfiguration? = nil,

0 commit comments

Comments
 (0)