Overview › Error Handling & Logging
Error Handling & Logging
30+ print() in production paths; no centralized logger; OSLog/swift-log not adopted.
68
SCORE
Summary
Logging is informal: print() in production widget + analytics utilities, no os.Logger adoption visible in the scan. No central error model. Crashlytics integration unclear from the iOS scan; verify it's wired into application(_:didFinishLaunchingWithOptions:).
Apple-recommended logging stack
| Tool | Use | Status |
|---|---|---|
os.Logger (OSLog) | Structured, categorized logging w/ privacy controls | NOT ADOPTED |
os_signpost / OSSignposter | Performance traces in Instruments | NOT ADOPTED |
| Crashlytics | Crash + non-fatal reporting | VERIFY |
| MetricKit | Hangs, energy, disk, scrolling metrics from real users | NOT FOUND |
print() | Quick debug | PRESENT in production |
| NSLog | Legacy | Audit and remove |
Recommended pattern
import os
extension Logger {
static let subsystem = Bundle.main.bundleIdentifier ?? "com.costco.costco"
static let auth = Logger(subsystem: subsystem, category: "auth")
static let cart = Logger(subsystem: subsystem, category: "cart")
static let network = Logger(subsystem: subsystem, category: "network")
static let pdp = Logger(subsystem: subsystem, category: "pdp")
}
// Usage — privacy-aware interpolation
Logger.auth.debug("OIDC challenge created for member \(memberId, privacy: .private)")
Logger.cart.error("Cart sync failed: \(error.localizedDescription, privacy: .public)")
MetricKit hangs for the iOS analog of ANRs
Android has ANRs; iOS has hangs. MetricKit's MXHangDiagnostic reports them. Adopt MetricKit + push payloads to Crashlytics as non-fatals.
Findings
""HIGH
30+ print() in production paths
DMCWidgetExtension, OffersTestUtilities (used in production widget), various analytics helpers all
print(). print() goes to console regardless of build config, may leak PII.Recommendation: Adopt
os.Logger with categorized signposts; mark sensitive interpolations with privacy: .private; gate raw print by #if DEBUG.MEDIUM
No central typed error model
Without a sealed
AppError enum, error handling drifts per feature.Recommendation: Define
AppError in Core; require all public APIs to throw or return Result<T, AppError>.MEDIUM
Crashlytics integration verification
Confirm Crashlytics is wired with proper symbol upload + dSYM handling.
Recommendation: Verify Build Phase script runs Crashlytics dSYM upload; ensure user identifier is not set to PII.
Findings in this category
Costco iOS · Code Review Report · Generated 2026-05-07 · 88 machine-curated findings