Print In Production
ID |
swift.print_in_production |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Best Practice |
Language |
Swift |
Tags |
best-practice, leftover-debug, logging |
Description
Reports unqualified calls to print, debugPrint, dump, or
NSLog. These bypass the application’s structured logging pipeline
and are almost always leftover diagnostics.
print("loaded") // FLAW
debugPrint(user) // FLAW
dump(user) // FLAW
NSLog("status %@", state) // FLAW
logger.info("loaded") // OK — structured logger
os_log("loaded", type: .info) // OK — os.log
Custom.print("hi") // OK — namespaced, not the stdlib `print`
Rationale
print and friends write unstructured text to stdout/stderr with no
log level, no subsystem/category, no privacy redaction, and no
filtering. They are perfect for ad-hoc debugging during development
and a liability in production binaries — they leak diagnostics into
the device console (where users and crash collectors can read them),
they bypass remote log shipping, and they slow hot paths since the
format strings are evaluated unconditionally.
Remediation
Use Apple’s os.log or the Logger / os_log APIs (or swift-log
in server-side projects) and pick an appropriate log level and
privacy modifier:
import os
let logger = Logger(subsystem: "com.example.app", category: "loading")
logger.info("loaded \(user, privacy: .public)")
For purely local debugging, wrap calls in #if DEBUG so they are
stripped from release builds:
#if DEBUG
print("loaded")
#endif