Introduction : Pourquoi la surveillance standard ne suffit-elle pas ?
La surveillance de base des applications Swift (crashlytics, temps de réponse API) ne résout qu'une partie des problèmes. À un niveau avancé, les développeurs doivent comprendre la télémétrie interne : les latences dans le thread UI, les fuites mémoire sur des écrans spécifiques, la fréquence de déclenchement de la logique métier et la charge sur les files d'attente en arrière-plan. Sans métriques personnalisées et alertes intelligentes, il est difficile de détecter les dégradations « silencieuses » des performances avant qu'elles n'affectent les utilisateurs.
Dans cet article, nous verrons comment organiser une surveillance avancée des applications Swift en utilisant des métriques personnalisées, l'intégration avec Prometheus/Grafana et la configuration d'alertes basées sur les percentiles et les anomalies.
Architecture de collecte des métriques : de l'application au tableau de bord
Pour une surveillance efficace, une architecture à trois niveaux est nécessaire :
- Niveau application (Swift) : collecte des métriques via un module personnalisé MetricCollector.
- Niveau transport : transmission des métriques au serveur (HTTP, WebSocket ou gRPC).
- Niveau visualisation : Prometheus + Grafana (ou des alternatives comme Datadog).
Exemple de collecteur de métriques de base en 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() } }}Intégration avec Prometheus : export des métriques
Pour envoyer des données à Prometheus, utilisez le format OpenMetrics. Créez un endpoint HTTP qui fournit les métriques sur demande :
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}
// Enregistrement de la routeapp.get("metrics", use: metricsRoute)Côté serveur, configurez Prometheus pour collecter les métriques depuis cet endpoint. Dans l'application Swift, utilisez une file d'attente en arrière-plan pour envoyer périodiquement les données (toutes les 10 à 15 secondes).
Métriques clés pour une surveillance avancée
En plus des métriques standard (CPU, mémoire, réseau), ajoutez des métriques métier et de performance :
- Latences UI : temps entre CADisplayLink et le rendu.
- Taille du cache : nombre d'objets dans NSCache sur les écrans.
- Fréquence des appels API : nombre de requêtes par minute vers un endpoint spécifique.
- Temps de traitement de la file d'attente : temps moyen d'exécution d'une tâche dans DispatchQueue.
Exemple de mesure du temps d'exécution d'un bloc :
func measure(_ name: String, block: () -> Void) { let start = CFAbsoluteTimeGetCurrent() block() let duration = CFAbsoluteTimeGetCurrent() - start MetricCollector.shared.record("\\(name)_duration_ms", value: duration * 1000)}Utilisez cette méthode pour encapsuler les sections critiques du code :
measure("data_processing") { // votre code de traitement des données}Configuration d'alertes intelligentes
Les alertes basées sur des seuils (par exemple, CPU > 90 %) génèrent souvent de faux positifs. Une approche avancée consiste à utiliser des alertes basées sur les percentiles et les anomalies.