Replace print with Logger.debug in ISODurationFormatter#6691
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1688f41. Configure here.
|
|
||
| guard let match = match else { | ||
| print("Failed to parse ISO duration: \(periodString)") | ||
| Logger.warn(Strings.codable.failed_to_parse_duration(periodString: periodString)) |
There was a problem hiding this comment.
Wrong log level: warn used instead of debug
Low Severity
The PR title says "Replace print with Logger.debug" and the reviewer explicitly suggested Logger.debug, but the code uses Logger.warn. A failed ISO duration parse is a decoding-level detail that would generate unnecessary noise at the warn level in production logs. Logger.debug is the appropriate level here, consistent with the stated intent and reviewer feedback.
Reviewed by Cursor Bugbot for commit 1688f41. Configure here.
|
|
||
| guard let match = match else { | ||
| print("Failed to parse ISO duration: \(periodString)") | ||
| Logger.warn(Strings.codable.failed_to_parse_duration(periodString: periodString)) |
There was a problem hiding this comment.
[Not for this PR]
Wonder if we should add a linter to avoid this from happening in the future in production code at least...
* Replace print with Logger.error in ISODurationFormatter (#6691) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * Decode reward payload in RewardVerification poll response (#6678) * Decode reward payload in RewardVerification poll response Plumbs the verified-reward payload from the backend response through the internal `pollRewardVerificationStatus` SPI so RC ad adapters can dispatch meaningful "verified" events with the granted reward. * Adds `VirtualCurrencyReward` and `VerifiedReward` (`@_spi(Internal) public`) under `Sources/Ads/RewardVerification/`. * Extends `RewardVerificationStatusResponse` to optionally decode a typed nested reward payload (`{ type, code, amount }`) on `verified` responses. - `reward` absent or null → `.noReward` - `type == "virtual_currency"` with valid `code`+`amount` → `.virtualCurrency` - any other `type` (or malformed `virtual_currency`) → `.unsupportedReward` + warn * `RewardVerificationPollStatus.verified` now carries the `VerifiedReward`. * `Purchases.pollRewardVerificationStatus` returns `.verified(reward)`. * Test mocks injected via a new `BasePurchasesTests.MockBackend` convenience init so `backend.adsAPI` resolves to `MockAdsAPI`. * Add unit tests for VerifiedReward and VirtualCurrencyReward Co-locates the unit tests next to the types this PR introduces under `Sources/Ads/RewardVerification/`: - `Tests/UnitTests/Ads/RewardVerification/VirtualCurrencyRewardTests.swift` Covers field storage, equality (both fields must match), and decimal precision preservation. - `Tests/UnitTests/Ads/RewardVerification/VerifiedRewardTests.swift` Covers `.virtualCurrency(_)` associated-value carrying, `.noReward` vs `.unsupportedReward` distinct-case identity, equality (matching associated reward required), and an exhaustive switch coverage test to guard against silently adding cases. Both tests pass against the existing `Sources/Ads/RewardVerification/` types and require no changes to them. (Originally written on top of #6663; moved to this base PR so the type and its tests ship together rather than splitting across PRs.) * fix: warn when reward verification reward value is not a JSON object Previously, `decodeVerifiedReward` silently returned `.noReward` for any of: missing reward key, null reward, or non-object reward value (e.g. a string/number/array). The first two are expected; the last indicates a backend mismatch and should be surfaced. Now distinguish: - absent or null reward → `.noReward` (silent, expected) - present but not a JSON object → `.unsupportedReward` + `Logger.warn` This matches the existing convention in this file of logging warnings when decoding unrecognized/malformed values into fallback cases. * Fix virtual currency reward amount type to integer. Align reward payload modeling with backend semantics by decoding `amount` as Int and updating tests to reject fractional values as malformed rewards. * fix: address review — couple verified status to reward Make the reward payload part of the verified status case so invalid state combinations are unrepresentable and remove the verified fallback mapping. * fix: address review — reject non-positive reward amounts Treat virtual-currency rewards with non-positive amounts as malformed payloads and return unsupported reward with warning logs. * fix: address review — reject empty reward currency code Validate virtual-currency payloads require a non-empty code and treat empty code values as malformed unsupported rewards. * fix: address review — remove non-actionable enum switch test Drop the exhaustive switch smoke test in VerifiedRewardTests since it did not validate behavior and duplicated compiler guarantees. * fix: address review — remove synthesized equatable assertions Drop VerifiedReward tests that only mirrored compiler-synthesized Equatable behavior and keep behavior-focused coverage. * Delete claude.yml workflow (#6688) * Add workflowTrigger to ButtonComponent.Action (#6693) * Add workflowTrigger case to ButtonComponent.Action Mirrors Android's rename of Action.Workflow → Action.WorkflowTrigger (purchases-android#3380). Decodes backend "type": "workflow" into .workflowTrigger so workflow buttons are rendered (previously decoded as .unknown and hidden) and track as "workflow_trigger" in analytics. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add tests for workflowTrigger action decoding and analytics value Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * Cache decoded images by file URL in `FileImageLoader` `URL.asImageAndSize` (used by `FileImageLoader.loadFromCache`) previously called `UIImage(contentsOfFile:)` / `NSImage(contentsOfFile:)` on every access. A SwiftUI paywall with many `RemoteImage` instances (e.g. a looping carousel that materialises multiple copies of each page) ends up hitting this path hundreds of times because `StateObject(wrappedValue:)` evaluates its closure on every host view re-init. UIKit/AppKit's internal caches still cost ~0.5–1 ms per call, which adds up to ~100+ ms of main-thread blocking for only a handful of unique URLs. Introduce a process-wide `DecodedImageCache` backed by `NSCache<NSURL, _>` so repeated lookups for the same URL become a dictionary hit. `NSCache` evicts on memory pressure, so we don't pin images forever. Reads/writes are serialised through a concurrent dispatch queue with a barrier on writes to keep the cache thread-safe. Made-with: Cursor --------- Co-authored-by: Facundo Menzella <facumenzella@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Pol Miro <polmiro@gmail.com> Co-authored-by: Cesar de la Vega <664544+vegaro@users.noreply.github.com>


Summary
ISODurationFormatter.parse(from:)was using a rawprint()on parse failure, bypassing the SDK's logging infrastructure. Replaced withLogger.error().A bare
printin an SDK outputs unconditionally to the user's console in production builds with no way to filter or silence it.Logger.errorintegrates with the SDK log level, respects any log suppression, and is consistent with error logging everywhere else inSources/.Test plan
swift buildpasses (verified locally)🤖 Generated with Claude Code
Note
Low Risk
Low risk: only replaces a
printside-effect with structured SDK logging, with no behavior change beyond how the message is emitted.Overview
Updates
ISODurationFormatter.parse(from:)to log ISO 8601 duration parse failures via the SDKLoggerinstead of usingprint, so output respects log level/suppression.Adds a new
CodableStrings.failed_to_parse_durationlog message to keep the warning text centralized and consistent.Reviewed by Cursor Bugbot for commit 1688f41. Bugbot is set up for automated code reviews on this repo. Configure here.