Abrova
☰ Docs menu · iOS SDK logging

iOS SDK Logging

Structured logging for iOS apps with automatic batching, exponential backoff, and lifecycle awareness via the native Swift SDK.

Last updated: 27 Oct 2026

Structured logging for iOS apps with automatic batching, exponential backoff, and lifecycle awareness. Logs are buffered and sent in batches to minimize network usage and battery drain.

Automatic Batching

Logs are buffered and sent in batches (default: 50)

Exponential Backoff

Failed batches retry with increasing delays (2s, 4s, 8s... up to 60s, max 10 retries)

Max Buffer Size

Logs are buffered in memory only (enableOfflineStorage covers errors, not logs); the oldest are dropped when the buffer exceeds 1000

Lazy Timer

Timer only runs when buffer has logs — no battery drain when idle

User Context

Automatically attaches user ID set via AbrovaTrace.shared.setUserId()

Native Swift

Built with Swift, supports iOS 12+, macOS 10.14+, tvOS 12+

Enable Logging#

After initializing AbrovaTrace, enable the logging service. (If you call a log method without enabling it, logging is turned on automatically with no sourceId.) Logs appear in the Console under Abrova Trace → Logs; they are separate from captureMessage, which goes to Messages.

UIKit

swift
import UIKit
import AbrovaTrace

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Initialize AbrovaTrace first
        let config = AbrovaTraceConfigBuilder(apiKey: "ab_live_YOUR_API_KEY")
            .environment("production")
            .release(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String)
            .build()

        AbrovaTrace.shared.initialize(config: config)

        // Enable logging with a source identifier
        AbrovaTrace.shared.enableLogging(
            sourceId: "my-ios-app",
            sourceName: "My iOS App",
            batchSize: 50,
            flushInterval: 5.0
        )

        return true
    }
}

SwiftUI

swift
import SwiftUI
import AbrovaTrace

@main
struct MyApp: App {
    init() {
        let config = AbrovaTraceConfigBuilder(apiKey: "ab_live_YOUR_API_KEY")
            .environment("production")
            .build()

        AbrovaTrace.shared.initialize(config: config)

        // Enable logging
        AbrovaTrace.shared.enableLogging(
            sourceId: "my-ios-app",
            sourceName: "My iOS App"
        )
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Sending Logs#

Convenience Methods

swift
// Info log
AbrovaTrace.shared.info("User login successful", metadata: [
    "user_id": "user_123"
])

// Warning log
AbrovaTrace.shared.warn("Slow API response", metadata: [
    "endpoint": "/api/users",
    "duration_ms": 2500
])

// Error log
AbrovaTrace.shared.logErrorMessage("Database query failed", metadata: [
    "query": "SELECT * FROM users",
    "error": "Connection timeout"
])

// Debug log
AbrovaTrace.shared.logDebugMessage("Cache hit for key: user_123")

// Trace log
AbrovaTrace.shared.trace("Entering function processPayment()")

// Fatal log
AbrovaTrace.shared.fatal("App crashed unexpectedly", metadata: [
    "last_screen": "checkout"
])

Generic Log Method

swift
// Generic log with explicit level
AbrovaTrace.shared.log("Custom event", level: .info, metadata: ["key": "value"])

Log Levels#

  • trace — AbrovaTrace.shared.trace() — Very detailed trace-level debugging
  • debug — AbrovaTrace.shared.logDebugMessage() — Debug information during development
  • info — AbrovaTrace.shared.info() — General application information
  • warn — AbrovaTrace.shared.warn() — Warnings about potential issues
  • error — AbrovaTrace.shared.logErrorMessage() — Errors that need attention
  • fatal — AbrovaTrace.shared.fatal() — Critical/unrecoverable errors

Usage with ViewControllers#

swift
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        AbrovaTrace.shared.info("ViewController loaded", metadata: ["screen": "main"])
    }

    func handlePurchase() {
        AbrovaTrace.shared.info("Purchase initiated", metadata: [
            "product_id": "premium_pack",
            "amount": 99.99
        ])

        do {
            try processPurchase()
            AbrovaTrace.shared.info("Purchase completed", metadata: ["amount": 99.99])
        } catch {
            AbrovaTrace.shared.logErrorMessage("Purchase failed", metadata: [
                "error": error.localizedDescription,
                "product_id": "premium_pack"
            ])
            AbrovaTrace.shared.captureError(error)
        }
    }

    func processPurchase() throws { /* ... */ }
}

SwiftUI Views

swift
struct ContentView: View {
    var body: some View {
        Button("Purchase") {
            AbrovaTrace.shared.info("Purchase button tapped")
            handlePurchase()
        }
        .onAppear {
            AbrovaTrace.shared.info("ContentView appeared")
        }
    }

    func handlePurchase() {
        // Purchase logic with logging
    }
}

Manual Operations#

swift
// Force flush all buffered logs
AbrovaTrace.shared.flushLogs { success in
  if success {
      print("Logs flushed successfully")
  }
}

// Check buffer status
let pendingCount = AbrovaTrace.shared.pendingLogCount
print("Pending logs: \(pendingCount)")

Configuration#

OptionTypeRequiredDescription
sourceIdString?NoIdentifier for batch sending (e.g., "my-ios-app"). Without it, buffered logs are sent one request each and failed sends are not retried
sourceNameString?NoHuman-readable name for this source
batchSizeIntNoFlush when buffer reaches this size (default: 50)
flushIntervalTimeIntervalNoMax time before flush in seconds (default: 5.0)

Best Practices#

Enable Early

Enable logging right after AbrovaTrace initialization to capture all events

Use Source IDs

Set a meaningful sourceId to identify logs from this app in the dashboard

Add Metadata

Include structured metadata (user ID, screen name, etc.) for easier debugging

Use Appropriate Levels

Use info for normal events, warn for potential issues, error for failures

Flush on Shutdown

Logs flush automatically when the app enters the background and on terminate; call AbrovaTrace.shared.flushLogs() for other shutdown paths

Don't Over-Log

Avoid logging in tight loops — the buffer has a max size and will drop oldest logs

Was this page helpful?
Report a problem