@@ -9,16 +9,39 @@ import AsyncHTTPClient
99import NIOCore
1010import NIOPosix
1111import NIOSSL
12- import SmithyHTTPAPI
12+ import struct Smithy. Attributes
13+ import struct Smithy. SwiftLogger
14+ import protocol Smithy. LogAgent
15+ import struct SmithyHTTPAPI. Headers
16+ import protocol SmithyHTTPAPI. HTTPClient
17+ import class SmithyHTTPAPI. HTTPResponse
18+ import class SmithyHTTPAPI. HTTPRequest
19+ import enum SmithyHTTPAPI. HTTPStatusCode
20+ import protocol Smithy. ReadableStream
21+ import enum Smithy. ByteStream
22+ import class SmithyStreams. BufferedStream
23+ import struct Foundation. Date
24+ import AwsCommonRuntimeKit
1325
1426/// AsyncHTTPClient-based HTTP client implementation that conforms to SmithyHTTPAPI.HTTPClient
1527/// This implementation is thread-safe and supports concurrent request execution.
1628public final class NIOHTTPClient : SmithyHTTPAPI . HTTPClient {
29+ public static let noOpNIOHTTPClientTelemetry = HttpTelemetry (
30+ httpScope: " NIOHTTPClient " ,
31+ telemetryProvider: DefaultTelemetry . provider
32+ )
33+
1734 private let client : AsyncHTTPClient . HTTPClient
1835 private let config : HttpClientConfiguration
1936 private let tlsConfiguration : NIOHTTPClientTLSOptions ?
2037 private let allocator : ByteBufferAllocator
2138
39+ /// HTTP Client Telemetry
40+ private let telemetry : HttpTelemetry
41+
42+ /// Logger for HTTP-related events.
43+ private var logger : LogAgent
44+
2245 /// Creates a new `NIOHTTPClient`.
2346 ///
2447 /// The client is created with its own internal `AsyncHTTPClient`, which is configured with system defaults.
@@ -28,6 +51,8 @@ public final class NIOHTTPClient: SmithyHTTPAPI.HTTPClient {
2851 httpClientConfiguration: HttpClientConfiguration
2952 ) throws {
3053 self . config = httpClientConfiguration
54+ self . telemetry = httpClientConfiguration. telemetry ?? NIOHTTPClient . noOpNIOHTTPClientTelemetry
55+ self . logger = self . telemetry. loggerProvider. getLogger ( name: " NIOHTTPClient " )
3156 self . tlsConfiguration = httpClientConfiguration. tlsConfiguration as? NIOHTTPClientTLSOptions
3257 self . allocator = ByteBufferAllocator ( )
3358
@@ -42,7 +67,77 @@ public final class NIOHTTPClient: SmithyHTTPAPI.HTTPClient {
4267 }
4368
4469 public func send( request: SmithyHTTPAPI . HTTPRequest ) async throws -> SmithyHTTPAPI . HTTPResponse {
45- // TODO
46- return HTTPResponse ( )
70+ let telemetryContext = telemetry. contextManager. current ( )
71+ let tracer = telemetry. tracerProvider. getTracer (
72+ scope: telemetry. tracerScope
73+ )
74+ do {
75+ // START - smithy.client.http.requests.queued_duration
76+ let queuedStart = Date ( ) . timeIntervalSinceReferenceDate
77+ let span = tracer. createSpan (
78+ name: telemetry. spanName,
79+ initialAttributes: telemetry. spanAttributes,
80+ spanKind: SpanKind . internal,
81+ parentContext: telemetryContext)
82+ defer {
83+ span. end ( )
84+ }
85+
86+ // START - smithy.client.http.connections.acquire_duration
87+ let acquireConnectionStart = Date ( ) . timeIntervalSinceReferenceDate
88+
89+ // TODO: Convert Smithy HTTPRequest to AsyncHTTPClient HTTPClientRequest
90+
91+ let acquireConnectionEnd = Date ( ) . timeIntervalSinceReferenceDate
92+ telemetry. connectionsAcquireDuration. record (
93+ value: acquireConnectionEnd - acquireConnectionStart,
94+ attributes: Attributes ( ) ,
95+ context: telemetryContext)
96+ // END - smithy.client.http.connections.acquire_duration
97+
98+ let queuedEnd = acquireConnectionEnd
99+ telemetry. requestsQueuedDuration. record (
100+ value: queuedEnd - queuedStart,
101+ attributes: Attributes ( ) ,
102+ context: telemetryContext)
103+ // END - smithy.client.http.requests.queued_duration
104+
105+ // TODO: Update connection and request usage metrics based on AsyncHTTPClient configuration
106+ telemetry. updateHTTPMetricsUsage { httpMetricsUsage in
107+ // TICK - smithy.client.http.connections.limit
108+ httpMetricsUsage. connectionsLimit = 0 // TODO: Get from AsyncHTTPClient configuration
109+
110+ // TICK - smithy.client.http.connections.usage
111+ httpMetricsUsage. acquiredConnections = 0 // TODO: Get from AsyncHTTPClient
112+ httpMetricsUsage. idleConnections = 0 // TODO: Get from AsyncHTTPClient
113+
114+ // TICK - smithy.client.http.requests.usage
115+ httpMetricsUsage. inflightRequests = httpMetricsUsage. acquiredConnections
116+ httpMetricsUsage. queuedRequests = httpMetricsUsage. idleConnections
117+ }
118+
119+ // DURATION - smithy.client.http.connections.uptime
120+ let connectionUptimeStart = acquireConnectionEnd
121+ defer {
122+ telemetry. connectionsUptime. record (
123+ value: Date ( ) . timeIntervalSinceReferenceDate - connectionUptimeStart,
124+ attributes: Attributes ( ) ,
125+ context: telemetryContext)
126+ }
127+
128+ // TODO: Execute the HTTP request using AsyncHTTPClient
129+
130+ // TODO: Log body description
131+
132+ // TODO: Handle response
133+ // TODO: Record bytes sent during request body streaming with server address attributes
134+ // TODO: Record bytes received during response streaming with server address attributes
135+
136+ // TODO: Convert NIO response to Smithy HTTPResponse
137+
138+ return HTTPResponse ( ) // TODO: Return actual response
139+ } catch {
140+ // TODO: Handle catch
141+ }
47142 }
48143}
0 commit comments