All skills
rshankras avatar

/logging-setup

@32566aa

Generates structured logging infrastructure using os.log/Logger to replace print() statements. Use when user wants to add proper logging, replace print statements, or set up app logging.

Use this Skill: https://skilld.dev/gh/rshankras/claude-code-apple-skills/logging-setup

This session only. Nothing lands on disk.

migration-guide.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

print() to Logger Migration Guide

Quick Migration Reference

print() Pattern Logger Equivalent
print("Message") AppLogger.general.info("Message")
print("Error: \(error)") AppLogger.general.error("Error: \(error)")
print("Debug: \(value)") AppLogger.general.debug("Debug: \(value, privacy: .private)")
print("User: \(email)") AppLogger.auth.info("User: \(email, privacy: .private)")

Migration by Context

Debug Output

// Before
print("DEBUG: \(someValue)")
print(">>> \(debugInfo)")

// After
AppLogger.general.debug("\(someValue, privacy: .private)")

Error Logging

// Before
print("Error: \(error)")
print("Failed to load: \(error.localizedDescription)")

// After
AppLogger.general.error("Failed to load: \(error.localizedDescription)")

Network Debugging

// Before
print("Request: \(url)")
print("Response: \(statusCode)")
print("Body: \(responseBody)")

// After
AppLogger.network.debug("Request: \(url, privacy: .public)")
AppLogger.network.info("Response: \(statusCode, privacy: .public)")
AppLogger.network.debug("Body: \(responseBody, privacy: .private)")

User Data

// Before
print("User logged in: \(email)")
print("User ID: \(userId)")

// After
AppLogger.auth.info("User logged in: \(email, privacy: .private)")
AppLogger.auth.info("User ID: \(userId, privacy: .private(mask: .hash))")

State Changes

// Before
print("State changed to: \(newState)")

// After
AppLogger.ui.debug("State changed to: \(String(describing: newState), privacy: .public)")

Bulk Migration Strategy

Step 1: Audit Current print() Usage

Run this search to find all print statements:

Grep pattern: print\s*\(

Step 2: Categorize by Purpose

Group print statements by their purpose:

  • Debug/Development: → .debug level
  • Information: → .info level
  • Warnings: → .warning level
  • Errors: → .error level

Step 3: Assign Categories

Map to appropriate logger categories:

  • Network/API calls → AppLogger.network
  • Authentication → AppLogger.auth
  • Data operations → AppLogger.data
  • UI/Navigation → AppLogger.ui
  • General/Other → AppLogger.general

Step 4: Add Privacy Annotations

Review each log for sensitive data:

  • User identifiable info → .private
  • Passwords/tokens → .sensitive
  • IDs, counts, status codes → .public

Common Migration Patterns

Function Entry/Exit

// Before
func processOrder(_ order: Order) {
    print("Processing order: \(order.id)")
    // ... work ...
    print("Order processed")
}

// After
func processOrder(_ order: Order) {
    AppLogger.data.debug("Processing order: \(order.id, privacy: .private(mask: .hash))")
    // ... work ...
    AppLogger.data.info("Order processed: \(order.id, privacy: .private(mask: .hash))")
}

Conditional Logging

// Before
#if DEBUG
print("Debug info: \(value)")
#endif

// After (no #if needed - debug logs are compiled out in release)
AppLogger.general.debug("Debug info: \(value, privacy: .private)")

Error Handling

// Before
do {
    try something()
} catch {
    print("Error: \(error)")
}

// After
do {
    try something()
} catch {
    AppLogger.general.error("Operation failed: \(error.localizedDescription)")
}

Performance Logging

// Before
let start = Date()
// ... work ...
print("Took: \(Date().timeIntervalSince(start))s")

// After
let start = CFAbsoluteTimeGetCurrent()
// ... work ...
let duration = CFAbsoluteTimeGetCurrent() - start
AppLogger.performance.info("Operation took \(duration, format: .fixed(precision: 3))s")

Temporary Migration Helper

If you want to migrate gradually, you can create a temporary bridge:

// TEMPORARY: Remove after full migration
func debugPrint(_ message: String, file: String = #file, line: Int = #line) {
    #if DEBUG
    let filename = (file as NSString).lastPathComponent
    AppLogger.general.debug("[\(filename):\(line)] \(message)")
    #endif
}

// Usage during migration
debugPrint("Old print statement") // Easy to find and replace later

Verification Checklist

After migration:

  • No print() statements remain (or only intentional ones)
  • All user data has privacy annotations
  • Appropriate log levels used
  • Categories match the code area
  • App builds without warnings
  • Logs appear in Console.app with correct subsystem

Source: SKILL.md on GitHub

No alerts2mo3 checks · Risk SAFE
  • Gen Agent Trust Hub2mo

    This skill is a development utility designed to modernize logging in Swift applications by migrating from print() statements to Apple's OSLog/Logger framework. It performs local file audits and generates template-based configuration files without external network requests, third-party dependencies, or persistence mechanisms.

  • Socket2mo

    No alerts

  • Snyk2mo

    Risk: LOW · No issues

Signed by skilld at 32566aa. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 3 months ago
What it can do
Reads files Edits files Runs commands
last_verified
2026-07-16
review_by
2027-06-22
os_version
iOS 27 / macOS 27
All 7 allowed tools
ReadWriteEditGlobGrepBashAskUserQuestion

README badge

README badge for rshankras/claude-code-apple-skills/logging-setup