From 34bc774e475574d1b087a6d9f3001c007d4e6440 Mon Sep 17 00:00:00 2001 From: Harsh <6162866+harsh62@users.noreply.github.com> Date: Tue, 24 Jun 2025 13:48:59 -0400 Subject: [PATCH 1/3] fix(logging): crash on release builds in rotation logger (#4009) * fix(logging): crash on release builds in rotation logger * worked on review comment --- .../AWSCloudWatchLoggingSession.swift | 13 +++++++++++-- .../CloudWatchLoggingStreamNameFormatter.swift | 7 +++++++ .../Persistence/LogRotation.swift | 7 ++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/AWSCloudWatchLoggingSession.swift b/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/AWSCloudWatchLoggingSession.swift index cfa0013092..7e470dd935 100644 --- a/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/AWSCloudWatchLoggingSession.swift +++ b/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/AWSCloudWatchLoggingSession.swift @@ -43,12 +43,21 @@ final class AWSCloudWatchLoggingSession { let directory = try directory(for: category, userIdentifier: userIdentifier) try fileManager.createDirectory(at: directory, withIntermediateDirectories: true) try (directory as NSURL).setResourceValue(true, forKey: URLResourceKey.isExcludedFromBackupKey) - let cacheMaxSizeInBytes = localStoreMaxSizeInMB * 1048576 + + // Calculate appropriate file size limit (individual file, not total cache) + // Use a reasonable file size limit that's a fraction of the total cache size + // Ensure it meets the minimum requirement of 1KB + let totalCacheSizeInBytes = localStoreMaxSizeInMB * 1048576 + let fileSizeLimitInBytes = max( + LogRotation.minimumFileSizeLimitInBytes, + totalCacheSizeInBytes / LogRotation.fileCountLimit + ) + return try RotatingLogger(directory: directory, category: category, namespace: namespace, logLevel: logLevel, - fileSizeLimitInBytes: cacheMaxSizeInBytes) + fileSizeLimitInBytes: fileSizeLimitInBytes) } private static func directory(for category: String, userIdentifier: String?, fileManager: FileManager = .default) throws -> URL { diff --git a/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Consumer/CloudWatchLoggingStreamNameFormatter.swift b/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Consumer/CloudWatchLoggingStreamNameFormatter.swift index 94fb9850ba..08031decbd 100644 --- a/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Consumer/CloudWatchLoggingStreamNameFormatter.swift +++ b/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Consumer/CloudWatchLoggingStreamNameFormatter.swift @@ -44,4 +44,11 @@ struct CloudWatchLoggingStreamNameFormatter { func formattedStreamName() async -> String { return "\(await deviceIdentifier ?? "").\(userIdentifier ?? "guest")" } + + // Add the missing deviceIdentifierFromBundle static method + private static func deviceIdentifierFromBundle() -> String? { + // Use bundle identifier as a fallback device identifier + // This provides a consistent identifier per app installation + return Bundle.main.bundleIdentifier + } } diff --git a/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Persistence/LogRotation.swift b/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Persistence/LogRotation.swift index 32552df26c..cd5fdca853 100644 --- a/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Persistence/LogRotation.swift +++ b/AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/Persistence/LogRotation.swift @@ -17,12 +17,13 @@ final class LogRotation { } static let minimumFileSizeLimitInBytes = 1024 /* 1KB */ + static let fileCountLimit: Int = 5 /// The name pattern of files managed by `LogRotation`. private static let filePattern = #"amplify[.]([0-9])[.]log"# let directory: URL - let fileCountLimit: Int = 5 + let fileSizeLimitInBytes: UInt64 private(set) var currentLogFile: LogFile { @@ -40,7 +41,7 @@ final class LogRotation { self.directory = directory.absoluteURL self.fileSizeLimitInBytes = UInt64(fileSizeLimitInBytes) self.currentLogFile = try Self.selectNextLogFile(from: self.directory, - fileCountLimit: fileCountLimit, + fileCountLimit: Self.fileCountLimit, fileSizeLimitInBytes: self.fileSizeLimitInBytes) } @@ -55,7 +56,7 @@ final class LogRotation { /// 3. If no files matching #1 are present, the file with the oldest last modified date is cleared and selected. func rotate() throws { self.currentLogFile = try Self.selectNextLogFile(from: self.directory, - fileCountLimit: self.fileCountLimit, + fileCountLimit: Self.fileCountLimit, fileSizeLimitInBytes: self.fileSizeLimitInBytes) } From d56a2e98fef8644895a2b2d868f9376fc866a7c5 Mon Sep 17 00:00:00 2001 From: Harsh <6162866+harsh62@users.noreply.github.com> Date: Thu, 26 Jun 2025 19:31:26 -0400 Subject: [PATCH 2/3] chore: fix integration tests (#4011) --- .../IdentifyBasicIntegrationTests.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AmplifyPlugins/Predictions/Tests/PredictionsHostApp/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift b/AmplifyPlugins/Predictions/Tests/PredictionsHostApp/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift index 3b8762e00d..969c0b0dc4 100644 --- a/AmplifyPlugins/Predictions/Tests/PredictionsHostApp/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift +++ b/AmplifyPlugins/Predictions/Tests/PredictionsHostApp/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift @@ -225,11 +225,11 @@ class IdentifyBasicIntegrationTests: AWSPredictionsPluginTestBase { XCTAssertNotNil(result) XCTAssertFalse(result.fullText.isEmpty) XCTAssertFalse(result.words.isEmpty) - XCTAssertEqual(result.words.count, 30) + XCTAssertEqual(result.words.count, 28) XCTAssertFalse(result.rawLineText.isEmpty) - XCTAssertEqual(result.rawLineText.count, 17) + XCTAssertEqual(result.rawLineText.count, 11) XCTAssertFalse(result.identifiedLines.isEmpty) - XCTAssertEqual(result.identifiedLines.count, 17) + XCTAssertEqual(result.identifiedLines.count, 11) XCTAssertFalse(result.keyValues.isEmpty) XCTAssertEqual(result.keyValues.count, 7) } From a002c5412ccf4093ce5a2fafaff966fc8d489a75 Mon Sep 17 00:00:00 2001 From: Harsh <6162866+harsh62@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:02:56 -0400 Subject: [PATCH 3/3] fix(api): fixing mis-classified errors (#4012) --- .../Core/AWSPluginsCore/WebSocket/WebSocketClient.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/AmplifyPlugins/Core/AWSPluginsCore/WebSocket/WebSocketClient.swift b/AmplifyPlugins/Core/AWSPluginsCore/WebSocket/WebSocketClient.swift index 2267ea6cb5..21e867ab4e 100644 --- a/AmplifyPlugins/Core/AWSPluginsCore/WebSocket/WebSocketClient.swift +++ b/AmplifyPlugins/Core/AWSPluginsCore/WebSocket/WebSocketClient.swift @@ -250,9 +250,7 @@ extension WebSocketClient: URLSessionWebSocketDelegate { switch (nsError.domain, nsError.code) { case (NSURLErrorDomain.self, NSURLErrorNetworkConnectionLost), (NSURLErrorDomain.self, NSURLErrorCannotConnectToHost), - (NSURLErrorDomain.self, NSURLErrorTimedOut), (NSURLErrorDomain.self, NSURLErrorNotConnectedToInternet), - (NSURLErrorDomain.self, NSURLErrorDataNotAllowed), (NSPOSIXErrorDomain.self, Int(ECONNABORTED)), (NSPOSIXErrorDomain.self, 57): self.subject.send(.error(WebSocketClient.Error.connectionLost))