İçeriğe geç

Swift Uygulamalarinda Daha Iyi Hata Raporlama: Otomatik Loglar + Analitik

"Calismiyor" gibi belirsiz bug raporlarindan mi biktiniz? Bu yazida Swift uygulamalarinda otomatik log toplama ve gercek dunya hatalarini izlemeyi -- sadece birkac satir kodla -- ogreneceksin.

Swift Uygulamalarinda Daha Iyi Hata Raporlama: Otomatik Loglar + Analitik

“Calismiyor.”

Bir iOS uygulamasinin destegini yaptiysan, bu sinir bozucu derecede belirsiz kullanici geri bildirimini almissindir. Yeniden olusturma adimlari yok, hata mesaji yok, baglam yok – sadece seni cevaptan cok soruyla basi basa birakan o korkunc “calismiyor” raporu.

En detayci kullanicilar bile sorunlari teshis etmek icin hangi bilgiye ihtiyacin oldugunu nadiren bilir. Yardim etmeye calistiklarinda bile, dogru detaylari saglayacak teknik bilgiye sahip olmayabilirler. Bu kopukluk herkes icin sinir bozucu bir deneyim yaratiyor.

Bu yazida, bu bosluyu kapatmak icin ErrorKit icerisinde uyguladigim iki pratik yaklasimi paylasacagim: otomatik olarak tanisal loglar toplayan basit bir geri bildirim butonu ve dogrudan kullanici raporlari olmadan bile kaliplari belirlemenize yardimci olan yapilandirilmis bir hata analitigi yaklasimi.

Eksik Baglam Sorunu

Kullanicilar sorunlarla karsilastiginda, teshisi zorlastiran birkac engel var:

  1. Hangi bilgiye ihtiyacin oldugunu bilmiyorlar

  2. Sistem loglarina kolayca eriselemiyorlar

  3. Tam adimlari hatirlayip ifade etmekte zorlaniyorlar

  4. Karmasik sorunlar birden fazla bileseni icerebilir

  5. Aralikli sorunlari talep uzerine yeniden uretmek zor

Duzgun bir baglam olmadan hata ayiklama bir tahmin oyununa donusuyor. Dogru bilgiyle dakikalar icinde cozulebilecek bir sorunu yeniden uretmeye calisarak saatler harcayabilirsin.

Cozum 1: Log Ekli Geri Bildirim Butonu

Ilk cozum, kullanicilarin sana eksiksiz bilgi gondermesini son derece kolaylastirmak. ErrorKit, otomatik log toplama ile bir mail olusucu ekleyen bir SwiftUI modifier’i sunuyor:

struct ContentView: View {
    @State private var showMailComposer = false

    var body: some View {
        VStack {
            // Your app content

            Button("Report a Problem") {
                showMailComposer = true
            }
            .mailComposer(
                isPresented: $showMailComposer,
                recipient: "[email protected]",
                subject: "YourApp Bug Report",
                messageBody: """
                   Please describe what happened:



                   ----------------------------------
                   Device: \(UIDevice.current.model)
                   iOS: \(UIDevice.current.systemVersion)
                   App version: \(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown")
                   """,
                attachments: [
                    try? ErrorKit.logAttachment(ofLast: .minutes(30))
                ]
            )
        }
    }
}

Bu basit bir “Sorun Bildir” butonu olusturuyor ve su isleri yapiyor:

  1. Onceden doldurulmus bir e-posta olusucu aciyor

  2. Cihaz ve uygulama bilgilerini iceriyor

  3. Otomatik olarak yakin zamandaki sistem loglarini ekliyor

  4. Kullanicinin sorunu aciklamasi icin alan sagliyor

Buradaki gizli sos log eki. Kullanici bir sorunla karsilastiktan sonra bu butona dokunursa, sorun olustugunda uygulamanda ve cevresinde neler olduguna dair kapsamli bir tablo elde ediyorsun.

Apple’in Unified Logging Sisteminden Yararlanmak

ErrorKit, tanisal bilgi toplamak icin Apple’in unified logging sistemi (OSLog/Logger) kullaniyor. Henuz yapilandirilmis loglama kullanmiyorsan, iste kisa bir giris:

import OSLog

// Create loggers
let logger = Logger()
// or with subsystem and category
let networkLogger = Logger(subsystem: "com.yourapp", category: "networking")

// Log at appropriate levels
logger.debug("Detailed connection info")      // Development debugging
logger.info("User tapped submit button")      // General information
logger.notice("Profile successfully loaded")   // Important events
logger.error("Failed to load user data")      // Errors that should be fixed
logger.fault("Database corruption detected")   // System failures

// Format values and control privacy
logger.info("User \(userId, privacy: .private) logged in from \(ipAddress, privacy: .public)")

Unified logging sistemi print() ifadelerine kiyasla birkac avantaj sagliyor:

  • Bilgi filtreleme icin log seviyeleri

  • Hassas veriler icin gizlilik kontrolleri

  • Minimal ek yukle verimli performans

  • Uygulama yeniden baslatmalari arasinda kalicilik

Kapsamli Log Toplama

ErrorKit’in yaklasiminin onemli bir avantaji, sadece uygulamanin loglarini degil, ayni zamanda sunlardan gelen ilgili loglari da yakalamasi:

  1. Apple’in unified logging sistemini kullanan ucuncu parti framework’ler

  2. Uygulamanin etkilestigi sistem bilesenleri (ag, dosya sistemi vb.)

  3. Uygulamanin islevselligiyle ilgili arka plan surecleri

Bu, sorun olustugunda uygulamanda ve cevresinde neler olduguna dair tam bir tablo sunuyor – sadece kendin acikca ekledigin loglar degil.

Log Toplamayi Kontrol Etmek

Detay ve gizlilik arasinda denge kurmak icin log toplamayi ozellestirebilirsin:

// Collect logs from last 30 minutes with notice level or higher (default)
try ErrorKit.logAttachment(ofLast: .minutes(30), minLevel: .notice)

// Collect logs from last hour with error level or higher (less verbose)
try ErrorKit.logAttachment(ofLast: .hours(1), minLevel: .error)

// Collect logs from last 5 minutes with debug level (very detailed)
try ErrorKit.logAttachment(ofLast: .minutes(5), minLevel: .debug)

minLevel parametresi loglari oneme gore filtreliyor:

  • .debug: Tum loglar (cok detayli)

  • .info: Bilgilendirme loglari ve ustundekiler

  • .notice: Dikkat cekici olaylar (varsayilan)

  • .error: Sadece hatalar ve arizalar

  • .fault: Sadece kritik hatalar

Bu, teshis icin ihtiyacin olan baglami saglarken ne kadar bilgi toplayacagin uzerinde kontrol sagliyor.

Daha Fazla Kontrol Icin Alternatif Yontemler

Log isleme uzerinde daha fazla kontrole ihtiyacin varsa, ErrorKit ek yaklasimlar sunuyor:

Log Verisini Dogrudan Alma

Kendi backend’ine log gondermek veya uygulama icinde islemek icin loggedData kullan:

let logData = try ErrorKit.loggedData(
    ofLast: .minutes(10),
    minLevel: .notice
)

// Use the data with your custom reporting system
analyticsService.sendLogs(data: logData)

Gecici Dosyaya Aktarma

Loglari baska mekanizmalarla paylasmak icin exportLogFile kullan:

let logFileURL = try ErrorKit.exportLogFile(
    ofLast: .hours(1),
    minLevel: .error
)

// Share the log file
let activityVC = UIActivityViewController(
    activityItems: [logFileURL],
    applicationActivities: nil
)
present(activityVC, animated: true)

Cozum 2: Gruplama ID’leriyle Akilli Hata Analitigi

Geri bildirim butonu kullanicilarin fark ettigi sorunlari bildirmelerine yardimci olurken, bircok sorun bildirilmeden kaliyor. Kullanicilar bir hatayla karsilasabilir, omuz silkip tekrar deneyebilir ve sana hic bahsetmeyebilir. Iste burada hata analitigi devreye giriyor.

ErrorKit, hatalari otomatik olarak izlemek ve akilli bir sekilde gruplamak icin araclar sagliyor:

func handleError(_ error: Error) {
    // Get a stable ID that ignores dynamic parameters
    let groupID = ErrorKit.groupingID(for: error)

    // Get the full error chain description
    let errorDetails = ErrorKit.errorChainDescription(for: error)

    // Send to your analytics system
    Analytics.track(
        event: "error_occurred",
        properties: [
            "error_group": groupID,
            "error_details": errorDetails,
            "user_id": currentUser.id
        ]
    )

    // Show appropriate UI to the user
    showErrorAlert(message: ErrorKit.userFriendlyMessage(for: error))
}

Uygulamana ekleyebilecegin ornek genel hata isleme fonksiyonu.

Buradaki sihir groupingID(for:) fonksiyonunda. Hatanin tur yapisi ve enum case’lerine dayali, dinamik parametreleri ve lokalize mesajlari gormezden gelen kararli bir tanimlayici uretiyor.

Bu, ayni temel nedene sahip hatalarin – spesifik detaylar (dosya yollari veya kullanici ID’leri gibi) farkli olsa bile – ayni gruplama ID’sine sahip olacagi anlamina geliyor:

// Both generate the same groupID: "3f9d2a"
ProfileError
└─ DatabaseError
   └─ FileError.notFound(path: "/Users/john/data.db")

ProfileError
└─ DatabaseError
   └─ FileError.notFound(path: "/Users/jane/backup.db")

Bu yaklasim birkac fayda sagliyor:

  1. Yaygin sorunlari belirleme: En sik hangi hatalarin olustugunu gor

  2. Duzeltimeleri onceliklendirme: Yuksek etkili sorunlara oncelik ver

  3. Cozumu izleme: Duzeltmelerden sonra hata oranlarinin dusup dusmedigini izle

  4. Yeni sorunlari tespit etme: Surum sonrasi yeni hata kaliplarini hizla belirle

  5. Kullanici segmentleriyle iliskilendirme: Bazi hatalarin belirli kullanicilari etkileyip etkilemedigini gor

Maksimum Icgoru Icin Her Iki Yaklasimi Birlestir

Guclu bir yaklasim, otomatik analitigi kullanici tarafindan baslatilan geri bildirimle birlestirmek – yani soyle bir sey yapabilirsin:

func handleError(_ error: Error) {
    // Always track for analytics
    trackErrorAnalytics(error)

    // For serious or unexpected errors, prompt for feedback
    if isSerious(error) {
        showErrorAlert(
            message: ErrorKit.userFriendlyMessage(for: error),
            feedbackOption: true
        )
    } else {
        // For minor issues, just show a message
        showErrorAlert(message: ErrorKit.userFriendlyMessage(for: error))
    }
}

func showErrorAlert(message: String, feedbackOption: Bool = false) {
    // Implementation of an alert that optionally includes a
    // "Send Feedback" button that opens the mail composer with logs
}

Bu, su kapsamli sistemi olusturuyor:

  1. Tum hatalar analitik icin izleniyor, genis kaliplari gormeni sagliyor

  2. Ciddi hatalar kullanicilari loglarla birlikte detayli geri bildirim icin yonlendiriyor

  3. Kullanicilar izleyemeyecegin sorunlar icin her zaman geri bildirim baslatabiliyor

Loglama Icin En Iyi Pratikler

Log toplamanin degerini en ust seviyeye cikarmak icin su en iyi pratikleri dikkate al:

1. Baglam Icin Loglari Yapilandir

Loglarinda neler oldugunu anlamak icin yeterli baglam sagla:

// Instead of:
Logger().error("Failed to load")

// Use:
Logger().error("Failed to load document \(documentId): \(ErrorKit.errorChainDescription(for: error))")

2. Uygun Log Seviyelerini Sec

Ayrintililik seviyesini kontrol etmek icin log seviyelerini stratejik kullan:

  • .debug – sadece gelistirme sirasinda gereken gelistirici detaylari icin

  • .info – normal uygulama akisini izlemek icin

  • .notice – kullanicilarin onemseyecegi onemli olaylar icin

  • .error – duzeltilmesi gereken ama temel islevselligi engellemeyen sorunlar icin

  • .fault – temel islevselligi bozan kritik sorunlar icin

3. Hassas Bilgileri Koru

Kullanici verilerini korumak icin gizlilik duzenleyicileri kullan:

Logger().info("Processing payment for user \(userId, privacy: .private)")

4. Onemli Kullanici Eylemlerini Logla

Hatalara giden yolu anlamak icin kullanici etkinliginden iz birakmalar olustur:

Logger().notice("User navigated to profile screen")
Logger().info("User tapped edit button")
Logger().notice("User saved profile changes")

5. Onemli Islemlerin Baslangic ve Tamamlanmasini Logla

Tamamlanmamis gorevleri belirlemek icin onemli islemleri cifte paranteze al:

Logger().notice("Starting data sync")
// ... sync implementation
Logger().notice("Completed data sync")

Destek ve Gelistirme Uzerindeki Etkisi

Bu araclari uygulamak hem kullanici deneyimini hem de gelistirme is akislarini donusturebilir:

Kullanicilar Icin:

  • Basitlestirilmis Raporlama: Tek dokunusla geri bildirim gonder

  • Teknik Soru Yok: Sinir bozucu ileri-geri iletisimden kacin

  • Daha Hizli Cozum: Sorunlar daha hizli teshis edilip duzeltilir

  • Daha Iyi Deneyim: Kullanicilara sorunlarini ciddiye aldigini gosterir

Gelistiriciler Icin:

  • Tam Baglam: Sorunlar olustugunda tam olarak neler oldugunu gor

  • Azaltilmis Destek Suresi: Ek bilgi istemek icin daha az zaman harca

  • Daha Iyi Yeniden Uretim: Log verilerine dayali daha guvenilir yeniden uretim adimlari

  • Verimli Hata Ayiklama: Hata raporlarindaki kaliplari hizla belirle

  • Veriye Dayali Onceliklendirme: En yaygin sorunlari duzeltmeye odaklan

Sonuc

ErrorKit’in yaklasimi, bir kullanicinin “calismiyor” demesi ile gercekte ne oldugunu bilmek arasindaki sinir bozucu boslugu kopruluyor. Otomatik log toplamanin akilli hata analitigiyle birlestirilmesinin gercekten ise yarayan bir geri bildirim dongusu olusturdugunu gordum.

Gercekten guclu olan sey, kullanicilar sorunlari bildirmeyi sectiklerinde detayli loglar alirken ayni zamanda hic bahsetmedikleri sorunlari da yakalamak. Bu cift tarafli yaklasim, uygulamalarimdaki sorunlari anlama ve duzeltme seklimi donusturdu. Eger sorunlari gozleri bagli ayiklamaktan biktiysan, ErrorKit tum bu loglama araclarini ve hata yonetimi iyilestirmelerini iceriyor – bunlar kendim ihtiyac duydugum icin gelistirdigim araclar:

github.comFlineDev / ErrorKitSimplified error handling with built-in user-friendly messages for common errors. Fully localized. Community-driven

Kullanici geri bildirimi ve hata raporlamayi nasil yonetiyorsun? Gercekten ise yarayan baska etkili teknikler buldun mu? Sosyal medyada (asagidaki linklerden) bana bildir!

Bu serideki onceki yazilar:

  1. Swift Error Handling Done Right: Overcoming the ObjC Legacy

  2. Unlocking the Power of Swift 6’s Typed Throws with Error Chains

Bu serideki sonraki yazi:

  1. Making Swift Error Messages Human-Friendly—Together

Bu yazıyı beğendin mi? Swift ipuçları ve indie geliştirici güncellemeleri için Bluesky ve Mastodon üzerinden takip et.