Einleitung: Warum reicht Standard-Monitoring nicht aus?
Das grundlegende Monitoring von Swift-Apps (Crashlytics, API-Antwortzeiten) löst nur einen Teil der Probleme. Auf fortgeschrittener Ebene müssen Entwickler die interne Telemetrie verstehen: Verzögerungen im UI-Thread, Speicherlecks auf bestimmten Bildschirmen, die Häufigkeit von Geschäftslogik-Ausführungen und die Auslastung von Hintergrund-Warteschlangen. Ohne benutzerdefinierte Metriken und intelligente Alarme ist es schwierig, „stille“ Leistungseinbußen zu erkennen, bevor sie sich auf die Benutzer auswirken.
In diesem Artikel betrachten wir, wie man ein erweitertes Monitoring von Swift-Apps mit benutzerdefinierten Metriken, Integration mit Prometheus/Grafana und der Einrichtung von Alarmen basierend auf Perzentilen und Anomalien organisiert.
Architektur der Metrikenerfassung: Von der App zum Dashboard
Für ein effektives Monitoring ist eine dreistufige Architektur erforderlich:
- Anwendungsebene (Swift): Erfassung von Metriken über ein benutzerdefiniertes Modul MetricCollector.
- Transportebene: Übertragung der Metriken an den Server (HTTP, WebSocket oder gRPC).
- Visualisierungsebene: Prometheus + Grafana (oder Alternativen wie Datadog).
Beispiel eines grundlegenden Metrik-Sammlers 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 mit Prometheus: Metriken exportieren
Verwenden Sie zum Senden von Daten an Prometheus das OpenMetrics-Format. Erstellen Sie einen HTTP-Endpunkt, der die Metriken auf Anfrage ausgibt:
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}
// Registrierung der Routeapp.get("metrics", use: metricsRoute)Konfigurieren Sie auf der Serverseite Prometheus so, dass es Metriken von diesem Endpunkt sammelt. Verwenden Sie in der Swift-App eine Hintergrundwarteschlange, um die Daten regelmäßig zu senden (alle 10-15 Sekunden).
Wichtige Metriken für erweitertes Monitoring
Fügen Sie neben den Standardmetriken (CPU, Speicher, Netzwerk) Geschäfts- und Leistungsmetriken hinzu:
- UI-Verzögerungen: Zeit zwischen CADisplayLink und dem Rendern.
- Cache-Größe: Anzahl der Objekte in NSCache auf Bildschirmen.
- API-Aufrufhäufigkeit: Anzahl der Anfragen pro Minute an einen bestimmten Endpunkt.
- Warteschlangenverarbeitungszeit: Durchschnittliche Ausführungszeit einer Aufgabe in DispatchQueue.
Beispiel für die Messung der Ausführungszeit eines Blocks:
func measure(_ name: String, block: () -> Void) { let start = CFAbsoluteTimeGetCurrent() block() let duration = CFAbsoluteTimeGetCurrent() - start MetricCollector.shared.record("\\(name)_duration_ms", value: duration * 1000)}Verwenden Sie diese Methode, um kritische Codeabschnitte zu umschließen:
measure("data_processing") { // Ihr Datenverarbeitungscode}Einrichtung intelligenter Alarme
Alarme auf Basis von Schwellenwerten (z. B. CPU > 90%) führen oft zu Fehlalarmen. Ein fortgeschrittener Ansatz sind Alarme auf Basis von Perzentilen und Anomalien.