Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ let package = Package(
.library(name: "SmithyCBOR", targets: ["SmithyCBOR"]),
.library(name: "SmithyWaitersAPI", targets: ["SmithyWaitersAPI"]),
.library(name: "SmithyTestUtil", targets: ["SmithyTestUtil"]),
.library(name: "SmithySwiftNIO", targets: ["SmithySwiftNIO"]),
.library(name: "SmithyTelemetry", targets: ["SmithyTelemetry"]),
.library(name: "SmithyHTTPClientAPI", targets: ["SmithyHTTPClientAPI"]),
],
dependencies: {
var dependencies: [Package.Dependency] = [
.package(url: "https://github.com/awslabs/aws-crt-swift.git", exact: "0.54.2"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
.package(url: "https://github.com/open-telemetry/opentelemetry-swift", from: "1.13.0"),
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.26.0"),
.package(url: "https://github.com/swift-server/async-http-client.git", exact: "1.22.0"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just noting that this needs to be switched to from: for release...
IIRC this is exact for testing the minimum supported version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup exactly, will switch it to from since we can see it passed all integration tests

]

let isDocCEnabled = ProcessInfo.processInfo.environment["AWS_SWIFT_SDK_ENABLE_DOCC"] != nil
Expand All @@ -75,10 +78,27 @@ let package = Package(
.product(name: "Logging", package: "swift-log"),
]
),
.target(
name: "SmithyTelemetry",
dependencies: [
"Smithy",
]
),
.target(
name: "SmithyHTTPClientAPI",
dependencies: [
"Smithy",
"SmithyHTTPAPI",
"SmithyTelemetry",
.product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This CRT dependency is not needed & should be removed.

(also, any "API" package shouldn't depend on an external implementation like CRT, per SRA)

]
),
.target(
name: "ClientRuntime",
dependencies: [
"Smithy",
"SmithyTelemetry",
"SmithyHTTPClientAPI",
"SmithyRetriesAPI",
"SmithyRetries",
"SmithyXML",
Expand All @@ -98,7 +118,6 @@ let package = Package(
"SmithyChecksums",
"SmithyCBOR",
.product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift"),
.product(name: "AsyncHTTPClient", package: "async-http-client"),
// Only include these on macOS, iOS, tvOS, watchOS, and macCatalyst (visionOS and Linux are excluded)
.product(
name: "InMemoryExporter",
Expand All @@ -125,6 +144,19 @@ let package = Package(
.copy("PrivacyInfo.xcprivacy")
]
),
.target(
name: "SmithySwiftNIO",
dependencies: [
"Smithy",
"SmithyHTTPAPI",
"SmithyHTTPClient",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SmithyHTTPClient depends on CRT, which means that SmithySwiftNIO depends on CRT.

We need to find a way to break that dependency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use some CRT interfaces within this package, that is the likely cause of this dependency.

We've already replaced many of those - in particular, for GA I got rid of all the CRT references in generated code - but there are still some between modules in this package & aws-sdk-swift.

"SmithyStreams",
"SmithyHTTPClientAPI",
"ClientRuntime",
.product(name: "AsyncHTTPClient", package: "async-http-client"),
],
path: "Sources/SmithySwiftNIO"
),
.target(
name: "SmithyRetriesAPI"
),
Expand Down Expand Up @@ -270,6 +302,13 @@ let package = Package(
],
resources: [ .process("Resources") ]
),
.testTarget(
name: "SmithySwiftNIOTests",
dependencies: [
"SmithySwiftNIO",
"SmithyTestUtil",
]
),
.testTarget(
name: "SmithyCBORTests",
dependencies: ["SmithyCBOR", "ClientRuntime", "SmithyTestUtil"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import protocol SmithyHTTPAPI.HTTPClient
import class SmithyHTTPAPI.HTTPRequest
import class SmithyHTTPAPI.HTTPResponse
import enum SmithyHTTPAPI.HTTPStatusCode
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class SmithyStreams.BufferedStream
#if os(Linux)
import Glibc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0.
*/

import class SmithyHTTPClientAPI.HttpTelemetry

struct CRTClientEngineConfig: Sendable {

/// Max connections the manager can contain per endpoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import AwsCommonRuntimeKit
import struct Smithy.Attributes
import enum Smithy.ByteStream
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys

extension HTTP2Stream {
/// Returns the recommended size, in bytes, for the data to write
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,87 +5,8 @@
// SPDX-License-Identifier: Apache-2.0
//

import AwsCommonRuntimeKit
import struct Foundation.TimeInterval
import enum Smithy.URIScheme
import struct SmithyHTTPAPI.Headers
import SmithyHTTPClientAPI

public class HttpClientConfiguration {

/// The timeout for establishing a connection, in seconds.
///
/// If none is provided, the client will use default values based on the platform.
public var connectTimeout: TimeInterval?

/// The timeout for socket, in seconds.
/// Sets maximum time to wait between two data packets.
/// Used to close stale connections that have no activity.
///
/// Defaults to 60 seconds if no value is provided.
public var socketTimeout: TimeInterval

/// HTTP headers to be submitted with every HTTP request.
///
/// If none is provided, defaults to no extra headers.
public var defaultHeaders: Headers

/// The maximum connections the HTTP client makes per host or per endpoint depending on the OS.
///
/// For Apple platforms, it will be per host.
/// For Linux, it will be per endpoint (protocol + host + port).
public var maxConnections: Int

// add any other properties here you want to give the service operations
// control over to be mapped to the Http Client

/// The URL scheme to be used for HTTP requests. Supported values are `http` and `https`.
///
/// If none is provided, the default protocol for the operation will be used
public var protocolType: URIScheme?

/// Custom TLS configuration for HTTPS connections.
///
/// Enables specifying client certificates and trust stores for secure communication.
/// Defaults to system's TLS settings if `nil`.
public var tlsConfiguration: (any TLSConfiguration)?

/// HTTP Client Telemetry
public var telemetry: HttpTelemetry?

/// Creates a configuration object for a SDK HTTP client.
///
/// Not all configuration settings may be followed by all clients.
/// - Parameters:
/// - connectTimeout: The maximum time to wait for a connection to be established.
/// - socketTimeout: The maximum time to wait between data packets.
/// - defaultHeaders: HTTP headers to be included with every HTTP request.
/// Note that certain headers may cause your API request to fail. Defaults to no headers.
/// - protocolType: The HTTP scheme (`http` or `https`) to be used for API requests. Defaults to the operation's standard configuration.
/// - tlsConfiguration: Optional custom TLS configuration for HTTPS requests. If `nil`, defaults to a standard configuration.
/// - maxConnections: The maximum number of connections the HTTP client makes per host (for Apple platforms) or per endpoint (for Linux). For non-mac Apple platforms, defaults to 6. For macOS and Linux, defaults to 50.
public init(
connectTimeout: TimeInterval? = nil,
socketTimeout: TimeInterval = 60.0,
protocolType: URIScheme = .https,
defaultHeaders: Headers = Headers(),
tlsConfiguration: (any TLSConfiguration)? = nil,
telemetry: HttpTelemetry? = nil,
maxConnections: Int? = nil
) {
self.socketTimeout = socketTimeout
self.protocolType = protocolType
self.defaultHeaders = defaultHeaders
self.connectTimeout = connectTimeout
self.tlsConfiguration = tlsConfiguration
self.telemetry = telemetry
if let maxConnections {
self.maxConnections = maxConnections
} else {
#if os(macOS) || os(Linux)
self.maxConnections = 50
#else // iOS, ipadOS, watchOS, tvOS.
self.maxConnections = 6 // URLSession default.
#endif
}
}
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyHTTPClientAPI.
public typealias HttpClientConfiguration = SmithyHTTPClientAPI.HttpClientConfiguration
12 changes: 12 additions & 0 deletions Sources/ClientRuntime/Networking/Http/TLSConfiguration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import SmithyHTTPClientAPI

/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyHTTPClientAPI.
public typealias TLSConfiguration = SmithyHTTPClientAPI.TLSConfiguration
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import class Foundation.DispatchQueue
import class Foundation.InputStream
import class Foundation.NSObject
import class Foundation.OutputStream
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class Foundation.RunLoop
import class Foundation.Stream
import protocol Foundation.StreamDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import class Foundation.NSRecursiveLock
import var Foundation.NSURLAuthenticationMethodClientCertificate
import var Foundation.NSURLAuthenticationMethodServerTrust
import struct Foundation.TimeInterval
import class SmithyHTTPClientAPI.HttpTelemetry
import enum SmithyHTTPClientAPI.HttpMetricsAttributesKeys
import class Foundation.URLAuthenticationChallenge
import struct Foundation.URLComponents
import class Foundation.URLCredential
Expand Down
14 changes: 4 additions & 10 deletions Sources/ClientRuntime/Telemetry/Context/TelemetryContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@
// SPDX-License-Identifier: Apache-2.0
//

/// A Telemetry Context is a container that can be associated with Tracers and Metrics.
///
/// Context implementations may be containers for execution-scoped values across API boundaries (both in-process and
/// distributed).
public protocol TelemetryContext: Sendable {
import SmithyTelemetry

/// Make this context the currently active context.
///
/// - Returns: the scope of the current context
func makeCurrent() -> TelemetryScope
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias TelemetryContext = SmithyTelemetry.TelemetryContext
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check what appears in IDE help when you put the cursor on ClientRuntime.TelemetryContext.

We might need to preserve the original doc comment here.

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
// SPDX-License-Identifier: Apache-2.0
//

/// A Telemetry Context Manager manages the Telemetry Contexts in a client.
///
/// Implementations should be able to manage contexts in a thread-safe way.
public protocol TelemetryContextManager: Sendable {
import SmithyTelemetry

/// - Returns: the current Telemetry Context
func current() -> TelemetryContext
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias TelemetryContextManager = SmithyTelemetry.TelemetryContextManager
9 changes: 4 additions & 5 deletions Sources/ClientRuntime/Telemetry/Context/TelemetryScope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
// SPDX-License-Identifier: Apache-2.0
//

/// Delineates a Telemetry Scope that has a beginning and end, particularly for Telemetry Contexts.
public protocol TelemetryScope: Sendable {
import SmithyTelemetry

/// Ends the scope.
func end()
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias TelemetryScope = SmithyTelemetry.TelemetryScope
1 change: 1 addition & 0 deletions Sources/ClientRuntime/Telemetry/DefaultTelemetry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import struct Smithy.AttributeKey
import struct Smithy.Attributes
import protocol Smithy.LogAgent
import struct Smithy.SwiftLogger
import SmithyTelemetry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move DefaultTelemetry from ClientRuntime to SmithyTelemetry, then typealias it here to prevent the breaking change.

Even though it is technically an "implementation", it has no dependencies other than Smithy and SmithyTelemetry so SmithyTelemetry is the right place for it.

Also, consider renaming SmithyTelemetry to SmithyTelemetryAPI, which would follow the SRA naming pattern for packages that contain interfaces but not implementations (at least not implementations with dependencies.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


/// Namespace for the Default SDK Telemetry implementations.
public enum DefaultTelemetry: Sendable {
Expand Down
13 changes: 4 additions & 9 deletions Sources/ClientRuntime/Telemetry/Logging/LoggerProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@
// SPDX-License-Identifier: Apache-2.0
//

import protocol Smithy.LogAgent
import SmithyTelemetry

/// A Logger Provider provides implementations of LogAgents.
public protocol LoggerProvider: Sendable {
/// Provides a LogAgent.
///
/// - Parameter name: the name associated with the LogAgent
/// - Returns: a LogAgent
func getLogger(name: String) -> LogAgent
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias LoggerProvider = SmithyTelemetry.LoggerProvider
35 changes: 13 additions & 22 deletions Sources/ClientRuntime/Telemetry/Metrics/AsyncMeasurement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,20 @@
// SPDX-License-Identifier: Apache-2.0
//

import struct Smithy.Attributes
import SmithyTelemetry

/// Handle to stop recording values of an AsyncMeasurement.
public protocol AsyncMeasurementHandle: Sendable {
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias AsyncMeasurementHandle = SmithyTelemetry.AsyncMeasurementHandle

/// Stop recording values of an AsyncMeasurement.
///
/// Implementations probably will unregister an AsyncMeasurement callback.
func stop()
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias LongAsyncMeasurement = SmithyTelemetry.LongAsyncMeasurement

public typealias LongAsyncMeasurement = AsyncMeasurement<Int>
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias DoubleAsyncMeasurement = SmithyTelemetry.DoubleAsyncMeasurement

public typealias DoubleAsyncMeasurement = AsyncMeasurement<Double>

/// Async measurement of a specific numeric type.
public protocol AsyncMeasurement<NumericType> {
associatedtype NumericType: Numeric

/// Asynchronously records a value for a metric, usually as a callback to an async instrument created by a Meter.
///
/// - Parameter value: value to record
/// - Parameter attributes: associated attributes, typically of the metric
/// - Parameter context: context in which value is recorded in
func record(value: NumericType, attributes: Attributes?, context: TelemetryContext?)
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias AsyncMeasurement = SmithyTelemetry.AsyncMeasurement
17 changes: 4 additions & 13 deletions Sources/ClientRuntime/Telemetry/Metrics/Histogram.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,8 @@
// SPDX-License-Identifier: Apache-2.0
//

import struct Smithy.Attributes
import SmithyTelemetry

/// A Histogram measures a value where the statistics are likely meaningful.
///
/// Examples include: request latency, HTTP response times
public protocol Histogram: Sendable {

/// Records a value for a metric.
///
/// - Parameter value: value to record
/// - Parameter attributes: associated attributes, typically of the metric
/// - Parameter context: context in which value is recorded in
func record(value: Double, attributes: Attributes?, context: TelemetryContext?)
}
/// Typealias for backward compatibility.
/// The actual implementation is now in SmithyTelemetry.
public typealias Histogram = SmithyTelemetry.Histogram
Loading