Skip to content

Commit 0691ec8

Browse files
authored
add telemetry support (#971)
1 parent 33d6bc7 commit 0691ec8

File tree

1 file changed

+98
-3
lines changed

1 file changed

+98
-3
lines changed

Sources/ClientRuntime/Networking/Http/NIO/NIOHTTPClient.swift

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,39 @@ import AsyncHTTPClient
99
import NIOCore
1010
import NIOPosix
1111
import 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.
1628
public 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

Comments
 (0)