Monitoring and Logging Swift Applications: Debugging Without Pain

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Is your application working perfectly? Let's check

\n\n

Have you ever launched a Swift application into production and prayed it wouldn't crash? I have. And every time a user wrote "it froze," I felt like a blind kitten. Logging and monitoring are the eyes and ears that turn chaos into order. Without them, you're guessing what went wrong. With them, you see every step.

\n\n

In this article, we'll break down how to set up monitoring for Swift applications so you can sleep soundly. No dry theory — just live code, real cases, and life hacks I've collected over the years. Let's go!

\n\n

Why logging in Swift is not just print()

\n\n

The first impulse of any developer is to stick print("everything broke here") around every corner. And it works... until you release the application. In production, print disappears into the void, and the user is left alone with the bug. We need something more.

\n\n

Modern Swift application logging is structured data, severity levels, and the ability for remote collection. Apple gives us a powerful tool — OSLog. It's lightweight, fast, and built right into the system. Let's see how to tame it.

\n\n

OSLog: Basic Level

\n\n

Import the framework and create a logger:

\n\n
import OSLog\n\nlet logger = Logger(\n    subsystem: "com.pythonlib.monitoring",\n    category: "network"\n)\n\nfunc fetchUserData() {\n    logger.info("Starting user data download")\n    // ... request code ...\n    logger.debug("Response received: \\(response.statusCode)")\n}
\n\n

Notice the subsystem and category. These are your tags for filtering. When you have 50 modules, you can filter out only network logs or only database logs — without extra noise.

\n\n

Logging Levels: When to shout and when to whisper

\n\n

OSLog supports six levels. Here's how to use them:

\n\n
    \n
  • debug — for development, disabled in release (unless explicitly enabled).
  • \n
  • info — useful information that doesn't clutter the console.
  • \n
  • notice — important events, e.g., successful startup.
  • \n
  • error — errors that can be handled.
  • \n
  • fault — critical failures after which the application may crash.
  • \n
\n\n

Example with a real error:

\n\n
func handleApiError(_ error: Error) {\n    logger.error("API Error: \\(error.localizedDescription, privacy: .public)")\n    // privacy: .public — to see the text in logs, otherwise it will be hidden\n}
\n\n

Monitoring Swift Applications: Metrics and Performance

\n\n

Logs are the past. Monitoring Swift applications is the present. You want to know what's happening right now: how much memory your code is consuming, whether animations are lagging, if the frame rate is dropping.

\n\n

Apple provides MetricKit — a framework for collecting diagnostics on user devices. It collects crash reports, battery data, and launch metrics. But for full-fledged monitoring, third-party services are often integrated.

\n\n

Integrating Crashlytics (Firebase) — Fast and Painful

\n\n

Crashlytics remains the industry standard. Here's the minimal setup:

\n\n
import FirebaseCrashlytics\n\n// Somewhere at app startup\nCrashlytics.crashlytics().setUserID("user_123")\nCrashlytics.crashlytics().setCustomValue(true, forKey: "is_premium")\n\n// Log non-fatal errors\ndo {\n    try riskyOperation()\n} catch {\n    Crashlytics.crashlytics().record(error: error)\n    logger.error("Non-fatal error: \\(error)")\n}
\n\n

Important point: do not log user personal data without consent. Use setUserID only if you have an anonymized identifier.

\n\n

Sending m

Blogs

Book Recommendations