Tüm Yazılar
KategoriPerformance
Okuma Süresi
23 dk
Yayın Tarihi
2025-08-25
Kelime Sayısı
1.706kelime

Kahveni hazırla - bu içerikli bir makale!

iOS Performance Monitoring & Observability Rehberi

Özet

MetricKit, os_signpost, OSLog, custom telemetry ve production performance monitoring. Crash reporting, ANR detection ve kullanici deneyimi metrikleri.

  • Kullanicilarin %53'u 3 saniyeden uzun yuklemelerde uygulamayi terk ediyor (Google Research).
  • MetricKit ile launch time, hang rate, memory peak, crash rate metrikleri izlenir.
  • Main thread 250ms'den fazla bloklanirsa ANR olusur, watchdog ile tespit edilir.
  • OSLog/signpost, Xcode Organizer, crash reporting ve custom telemetri ele aliniyor.
iOS Performance Monitoring & Observability Rehberi

# iOS Performance Monitoring & Observability Rehberi

Uygulamaniz App Store'da yayinlandiktan sonra performans izleme kritik oneme sahiptir. Gelistirme ortamindaki testler gercek dunyadaki milyonlarca farkli cihaz, network kosulu ve kullanim senaryosunu temsil edemez. Bu rehberde Apple'in native araclari, ucuncu parti cozumler ve production-grade monitoring stratejilerini ele alacagiz.

Gercek: Kullanicilarin %53'u 3 saniyeden uzun suren sayfa yuklemelerinde uygulamayi terk ediyor (Google Research).

Icindekiler


1. Observability Neden Onemli?

Observability uc temel sutun uzerine kurulur:

Sutun
Aciklama
iOS Araci
Metrics
Sayisal olcumler
MetricKit, custom counters
Logs
Olay kayitlari
OSLog, os_log
Traces
Islem akis takibi
os_signpost, Instruments

Performance Metrikleri ve Hedefler

Metrik
Hedef
Kritik Esik
Olcum Araci
App Launch
< 400ms
> 2s
MetricKit
Hang Rate
< %0.1
> %1
MetricKit
Memory Peak
< 200MB
> 500MB
MetricKit
Crash Rate
< %0.1
> %1
Xcode Organizer
Frame Drop
< %5
> %15
CADisplayLink
Battery
< %5/saat
> %10/saat
MetricKit
Disk Write
< 100MB/gun
> 1GB/gun
MetricKit

2. MetricKit Framework

MetricKit, Apple'in production performance olcum framework'udur. Gunluk ve anlik metrikler saglar.

swift
1import MetricKit
2 
3final class PerformanceMonitor: NSObject, MXMetricManagerSubscriber {
4 static let shared = PerformanceMonitor()
5 
6 private override init() {
7 super.init()
8 }
9 
10 func startMonitoring() {
11 let manager = MXMetricManager.shared
12 manager.add(self)
13 }
14 
15 func stopMonitoring() {
16 MXMetricManager.shared.remove(self)
17 }
18 
19 // Gunluk metrik raporu (24 saatte bir)
20 func didReceive(_ payloads: [MXMetricPayload]) {
21 for payload in payloads {
22 processMetricPayload(payload)
23 }
24 }
25 
26 // Anlik teshis raporu (crash, hang vb.)
27 func didReceive(_ payloads: [MXDiagnosticPayload]) {
28 for payload in payloads {
29 processDiagnosticPayload(payload)
30 }
31 }
32 
33 private func processMetricPayload(_ payload: MXMetricPayload) {
34 // Launch metrikleri
35 if let launchMetrics = payload.applicationLaunchMetrics {
36 let resumeTime = launchMetrics.histogrammedTimeToFirstDraw
37 logMetric("launch_time", histogram: resumeTime)
38 }
39 
40 // Memory metrikleri
41 if let memoryMetrics = payload.memoryMetrics {
42 let peakMemory = memoryMetrics.peakMemoryUsage
43 logMetric("peak_memory", measurement: peakMemory)
44 }
45 
46 // CPU metrikleri
47 if let cpuMetrics = payload.cpuMetrics {
48 let cumulativeCPU = cpuMetrics.cumulativeCPUTime
49 logMetric("cpu_time", measurement: cumulativeCPU)
50 }
51 
52 // Disk I/O
53 if let diskMetrics = payload.diskIOMetrics {
54 let writes = diskMetrics.cumulativeLogicalWrites
55 logMetric("disk_writes", measurement: writes)
56 }
57 
58 // JSON olarak server'a gonder
59 if let jsonData = payload.jsonRepresentation() {
60 sendToServer(data: jsonData, type: "metric")
61 }
62 }
63 
64 private func processDiagnosticPayload(_ payload: MXDiagnosticPayload) {
65 // Crash raporlari
66 if let crashDiags = payload.crashDiagnostics {
67 for crash in crashDiags {
68 logDiagnostic("crash", callStack: crash.callStackTree)
69 }
70 }
71 
72 // Hang raporlari
73 if let hangDiags = payload.hangDiagnostics {
74 for hang in hangDiags {
75 let duration = hang.hangDuration
76 logDiagnostic("hang", duration: duration)
77 }
78 }
79 
80 // CPU exception
81 if let cpuDiags = payload.cpuExceptionDiagnostics {
82 for cpuException in cpuDiags {
83 logDiagnostic("cpu_exception", callStack: cpuException.callStackTree)
84 }
85 }
86 
87 // Disk write exception
88 if let diskDiags = payload.diskWriteExceptionDiagnostics {
89 for diskException in diskDiags {
90 logDiagnostic("disk_exception", callStack: diskException.callStackTree)
91 }
92 }
93 
94 if let jsonData = payload.jsonRepresentation() {
95 sendToServer(data: jsonData, type: "diagnostic")
96 }
97 }
98 
99 private func logMetric(_ name: String, histogram: MXHistogram<UnitDuration>? = nil, measurement: Measurement<UnitDuration>? = nil) {
100 // Analytics backend'e gonder
101 }
102 
103 private func logDiagnostic(_ type: String, callStack: MXCallStackTree? = nil, duration: Measurement<UnitDuration>? = nil) {
104 // Crash reporting backend'e gonder
105 }
106 
107 private func sendToServer(data: Data, type: String) {
108 // HTTP POST ile server'a gonder
109 }
110}

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?


3. OSLog ve Signpost

OSLog, Apple'in modern logging framework'udur. Console.app ve Instruments ile entegre calisir.

swift
1import OSLog
2 
3// Logger tanimlama
4extension Logger {
5 private static let subsystem = Bundle.main.bundleIdentifier ?? "com.app"
6 
7 static let network = Logger(subsystem: subsystem, category: "Network")
8 static let database = Logger(subsystem: subsystem, category: "Database")
9 static let ui = Logger(subsystem: subsystem, category: "UI")
10 static let auth = Logger(subsystem: subsystem, category: "Auth")
11 static let performance = Logger(subsystem: subsystem, category: "Performance")
12}
13 
14// Kullanim
15struct NetworkService {
16 func fetchUsers() async throws -> [User] {
17 Logger.network.info("Kullanici listesi isteniyor")
18 
19 let startTime = CFAbsoluteTimeGetCurrent()
20 
21 do {
22 let users = try await apiClient.get("/users")
23 let elapsed = CFAbsoluteTimeGetCurrent() - startTime
24 
25 Logger.network.info("Basarili: \(users.count) kullanici, \(elapsed, format: .fixed(precision: 2))s")
26 Logger.performance.notice("API /users suresi: \(elapsed, format: .fixed(precision: 2))s")
27 
28 return users
29 } catch {
30 Logger.network.error("Hata: \(error.localizedDescription)")
31 throw error
32 }
33 }
34}

OSLog Seviyeleri

Seviye
Kullanim
Disk'e Yazilir mi?
Performans Etkisi
.debug
Gelistirme
Hayir
Yok
.info
Genel bilgi
Hafizada, gerekirse
Minimal
.notice
Onemli olaylar (default)
Evet
Dusuk
.error
Hatalar
Evet
Dusuk
.fault
Kritik hatalar
Evet + kalici
Dusuk

4. Xcode Organizer

Xcode Organizer (Window > Organizer), App Store'daki uygulamanizin performans verilerini gosterir:

  • Crashes: Crash raporlari ve stack trace'ler
  • Energy: Pil tuketim raporlari
  • Hangs: UI donma raporlari
  • Disk Writes: Asiri disk yazimi
  • Scrolling: Scroll performansi
  • Launch Time: Uygulama acilis suresi
  • Memory: Bellek kullanimi

5. Crash Reporting

swift
1// Custom crash handler
2final class CrashReporter {
3 static let shared = CrashReporter()
4 
5 func install() {
6 // Uncaught exception handler
7 NSSetUncaughtExceptionHandler { exception in
8 let info = CrashInfo(
9 name: exception.name.rawValue,
10 reason: exception.reason ?? "Bilinmeyen",
11 callStack: exception.callStackSymbols,
12 timestamp: Date()
13 )
14 CrashReporter.shared.saveCrash(info)
15 }
16 
17 // Signal handler (EXC_BAD_ACCESS vb.)
18 setupSignalHandlers()
19 
20 // Onceki crash varsa gonder
21 sendPendingCrashes()
22 }
23 
24 private func saveCrash(_ info: CrashInfo) {
25 // UserDefaults'a kaydet (FileManager crash sirasinda guvenli degil)
26 if let data = try? JSONEncoder().encode(info) {
27 UserDefaults.standard.set(data, forKey: "pending_crash")
28 }
29 }
30 
31 private func sendPendingCrashes() {
32 guard let data = UserDefaults.standard.data(forKey: "pending_crash"),
33 let crash = try? JSONDecoder().decode(CrashInfo.self, from: data) else {
34 return
35 }
36 
37 // Server'a gonder
38 Task {
39 do {
40 try await uploadCrash(crash)
41 UserDefaults.standard.removeObject(forKey: "pending_crash")
42 } catch {
43 Logger.performance.error("Crash raporu gonderilemedi")
44 }
45 }
46 }
47 
48 private func setupSignalHandlers() {
49 // SIGSEGV, SIGABRT, SIGBUS vb. icin
50 }
51 
52 private func uploadCrash(_ crash: CrashInfo) async throws {
53 // HTTP POST
54 }
55}
56 
57struct CrashInfo: Codable {
58 let name: String
59 let reason: String
60 let callStack: [String]
61 let timestamp: Date
62}

6. ANR (Application Not Responding) Detection

Main thread'in 250ms'den fazla bloklanmasi kullanici deneyimini bozar. Bunu tespit etmek icin watchdog mekanizmasi kurabilirsiniz.

swift
1final class HangDetector {
2 private var watchdogThread: Thread?
3 private let threshold: TimeInterval
4 private var lastPing = Date()
5 
6 init(threshold: TimeInterval = 0.5) {
7 self.threshold = threshold
8 }
9 
10 func start() {
11 // Main thread'den periyodik ping
12 let mainTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
13 self?.lastPing = Date()
14 }
15 RunLoop.main.add(mainTimer, forMode: .common)
16 
17 // Background thread'den izleme
18 watchdogThread = Thread {
19 while !Thread.current.isCancelled {
20 Thread.sleep(forTimeInterval: self.threshold)
21 let elapsed = Date().timeIntervalSince(self.lastPing)
22 if elapsed > self.threshold {
23 self.reportHang(duration: elapsed)
24 }
25 }
26 }
27 watchdogThread?.name = "HangDetector"
28 watchdogThread?.start()
29 }
30 
31 func stop() {
32 watchdogThread?.cancel()
33 }
34 
35 private func reportHang(duration: TimeInterval) {
36 let symbols = Thread.callStackSymbols
37 Logger.performance.warning("Main thread hang: \(duration, format: .fixed(precision: 2))s")
38 // Server'a bildir
39 }
40}

7. Network Monitoring

URLSession metrikleri ile network performansini izleyin:

swift
1final class NetworkMetricsCollector: NSObject, URLSessionTaskDelegate {
2 func urlSession(
3 _ session: URLSession,
4 task: URLSessionTask,
5 didFinishCollecting metrics: URLSessionTaskMetrics
6 ) {
7 for transaction in metrics.transactionMetrics {
8 let dns = transaction.domainLookupEndDate?.timeIntervalSince(
9 transaction.domainLookupStartDate ?? Date()
10 ) ?? 0
11 
12 let connect = transaction.connectEndDate?.timeIntervalSince(
13 transaction.connectStartDate ?? Date()
14 ) ?? 0
15 
16 let ttfb = transaction.responseStartDate?.timeIntervalSince(
17 transaction.requestStartDate ?? Date()
18 ) ?? 0
19 
20 Logger.network.info(
21 "DNS: \(dns)s, Connect: \(connect)s, TTFB: \(ttfb)s"
22 )
23 }
24 }
25}

8. Custom Telemetry

Kendi metriklerinizi tanimlayin ve izleyin.

Telemetri Katmanlari

Katman
Icerik
Ornek
Teknik
CPU, memory, disk
MetricKit
Uygulama
API suresi, cache hit
Custom
Is
Conversion, engagement
Analytics
Kullanici
Session suresi, retention
Analytics

9. Dashboard ve Alerting

Production monitoring icin bir dashboard kurulmalidir:

  • Grafana + Prometheus: Acik kaynak, esnek
  • Datadog: Kapsamli SaaS cozum
  • Firebase Performance: Google'in ucretsiz araci
  • Sentry: Hata ve performans izleme
  • New Relic: Enterprise cozum

10. Best Practices

Monitoring Checklist

  • MetricKit subscriber'i ekleyin
  • OSLog ile yapisal logging yapin
  • Crash reporting kurun
  • Hang detection aktif edin
  • Network metrikleri toplayin
  • Launch time izleyin
  • Memory uyarilari ekleyin
  • Alerting kurallari tanimlayin

11. Sonuc ve Oneriler

Performance monitoring bir lüks degil, zorunluluktur. Kullanicilariniz sessizce terk etmeden once sorunlari tespit edin.

Oncelik Sirasi

  1. Crash reporting (en kritik)
  2. Launch time monitoring
  3. Hang detection
  4. Memory metrikleri
  5. Network performansi
  6. Custom is metrikleri

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:

Etiketler

#Performance#Monitoring#MetricKit#OSLog#Observability#Crash#iOS
Muhittin Çamdalı

Muhittin Çamdalı

Lead Mobile Engineer

12+ yıllık deneyime sahip Lead Mobile Engineer. Swift, SwiftUI, Kotlin ve Flutter ile iOS, Android ve cross-platform mimarilerde uzman. Performanslı ve kullanıcı dostu mobil uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

İlgili İçerik