Advanced Swift Application Monitoring: Metrics and Alerts

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

Introduction: Why Standard Monitoring Is Not Enough?

Basic monitoring of Swift applications (crashlytics, API response time) solves only part of the problems. At an advanced level, developers need to understand internal telemetry: delays in the UI thread, memory leaks on specific screens, the frequency of business logic execution, and the load on background queues. Without custom metrics and intelligent alerts, it is difficult to identify "silent" performance degradations before they affect users.

In this article, we will look at how to organize advanced monitoring of Swift applications using custom metrics, integration with Prometheus/Grafana, and setting up alerts based on percentiles and anomalies.



Metric Collection Architecture: From Application to Dashboard

Effective monitoring requires a three-tier architecture:

  • Application Layer (Swift): collecting metrics via a custom MetricCollector module.
  • Transport Layer: transmitting metrics to the server (HTTP, WebSocket, or gRPC).
  • Visualization Layer: Prometheus + Grafana (or alternatives like Datadog).

Example of a basic metric collector in Swift:

import Foundation

final class MetricCollector { static let shared = MetricCollector() private var metrics: [String: Double] = [:] private let queue = DispatchQueue(label: "com.app.metrics", attributes: .concurrent) func record(_ name: String, value: Double) { queue.async(flags: .barrier) { self.metrics[name, default: 0] += value } } func snapshot() -> [String: Double] { queue.sync { return metrics } } func reset() { queue.async(flags: .barrier) { self.metrics.removeAll() } }}


Integration with Prometheus: Exporting Metrics

To send data to Prometheus, use the OpenMetrics format. Create an HTTP endpoint that serves metrics on request:

import Vapor

func metricsRoute(req: Request) -> String { let snapshot = MetricCollector.shared.snapshot() var output = "" for (name, value) in snapshot { output += "# HELP \\(name) Custom metric" output += "# TYPE \\(name) gauge" output += "\\(name) \\(value)" } return output}

// Route registrationapp.get("metrics", use: metricsRoute)

On the server side, configure Prometheus to collect metrics from this endpoint. In the Swift application, use a background queue to periodically send data (every 10-15 seconds).



Key Metrics for Advanced Monitoring

In addition to standard metrics (CPU, memory, network), add business and performance metrics:

  • UI delays: time between CADisplayLink and rendering.
  • Cache size: number of objects in NSCache on screens.
  • API call frequency: number of requests per minute to a specific endpoint.
  • Queue processing time: average task execution time in DispatchQueue.

Example of measuring block execution time:

func measure(_ name: String, block: () -> Void) {    let start = CFAbsoluteTimeGetCurrent()    block()    let duration = CFAbsoluteTimeGetCurrent() - start    MetricCollector.shared.record("\\(name)_duration_ms", value: duration * 1000)}

Use this method to wrap critical code sections:

measure("data_processing") {    // your data processing code}


Configuring Intelligent Alerts

Alerts based on threshold values (e.g., CPU > 90%) often produce false positives. An advanced approach is alerts based on percentiles and anom

Blogs

Book Recommendations