Android SDK Logging
Structured logging for Android apps with automatic batching, exponential backoff, and lifecycle awareness via the native Kotlin SDK.
Structured logging for Android apps with automatic batching, exponential backoff, and lifecycle awareness. Logs are buffered and sent in batches to minimize network usage and battery drain.
Logs are buffered and sent in batches (default: 50)
Failed batches are retried with increasing delays (2s, 4s, 8s... up to 60s)
Drops oldest logs when buffer exceeds 1000 to prevent memory issues
Timer only runs when buffer has logs — no battery drain when idle
Automatically attaches user ID set via AbrovaTrace.setUserId()
Built with Kotlin, supports API 19+ (Android 4.4+)
Enable Logging#
After initializing AbrovaTrace in your Application class, enable the logging service:
import android.app.Application
import ir.abrova.trace.sdk.AbrovaTrace
import ir.abrova.trace.sdk.AbrovaTraceConfig
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// Initialize AbrovaTrace first
val config = AbrovaTraceConfig.Builder("ab_live_YOUR_API_KEY")
.environment("production")
.release(BuildConfig.VERSION_NAME)
.build()
AbrovaTrace.init(this, config)
// Enable logging with a source identifier
AbrovaTrace.enableLogging(
sourceId = "my-android-app",
sourceName = "My Android App",
batchSize = 50,
flushIntervalMs = 5000L
)
}
}Sending Logs#
Convenience Methods
import ir.abrova.trace.sdk.AbrovaTrace
// Info log
AbrovaTrace.info("User login successful", mapOf(
"user_id" to "user_123"
))
// Warning log
AbrovaTrace.warn("Slow API response", mapOf(
"endpoint" to "/api/users",
"duration_ms" to 2500
))
// Error log
AbrovaTrace.logError("Database query failed", mapOf(
"query" to "SELECT * FROM users",
"error" to "Connection timeout"
))
// Debug log
AbrovaTrace.logDebug("Cache hit for key: user_123")
// Trace log
AbrovaTrace.trace("Entering function processPayment()")
// Fatal log
AbrovaTrace.fatal("App crashed unexpectedly", mapOf(
"last_screen" to "checkout"
))Generic Log Method
import ir.abrova.trace.sdk.models.LogLevel
// Generic log with explicit level
AbrovaTrace.log(
"Custom event",
LogLevel.INFO,
mapOf("key" to "value")
)Log Levels#
- trace —
AbrovaTrace.trace()— Very detailed trace-level debugging - debug —
AbrovaTrace.logDebug()— Debug information during development - info —
AbrovaTrace.info()— General application information - warn —
AbrovaTrace.warn()— Warnings about potential issues - error —
AbrovaTrace.logError()— Errors that need attention - fatal —
AbrovaTrace.fatal()— Critical/unrecoverable errors
Usage with Activities#
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AbrovaTrace.info("MainActivity created", mapOf("screen" to "main"))
}
private fun handlePurchase() {
AbrovaTrace.info("Purchase initiated", mapOf(
"product_id" to "premium_pack",
"amount" to 99.99
))
try {
processPurchase()
AbrovaTrace.info("Purchase completed", mapOf("amount" to 99.99))
} catch (e: Exception) {
AbrovaTrace.logError("Purchase failed", mapOf(
"error" to e.message,
"product_id" to "premium_pack"
))
AbrovaTrace.captureException(e)
}
}
override fun onDestroy() {
if (isFinishing) {
AbrovaTrace.flushLogs()
AbrovaTrace.close()
}
super.onDestroy()
}
}Manual Operations#
// Force flush all buffered logs
AbrovaTrace.flushLogs { success ->
if (success) {
Log.d("AbrovaTrace", "Logs flushed successfully")
}
}
// Check buffer status
val pendingCount = AbrovaTrace.getPendingLogCount()
Log.d("AbrovaTrace", "Pending logs: $pendingCount")Configuration#
| Option | Type | Required | Description |
|---|---|---|---|
| sourceId | String? | No | Identifier for batch sending (e.g., "my-android-app") |
| sourceName | String? | No | Human-readable name for this source |
| batchSize | Int | No | Flush when buffer reaches this size (default: 50) |
| flushIntervalMs | Long | No | Max time before flush in ms (default: 5000) |
If you call a log method before enableLogging(), logging is switched on automatically with the defaults above (no sourceId). Without a sourceId, each log is sent individually to /api/logs/ingest and a failed send is not retried; with one, buffered logs go in one request to /api/logs/ingest/batch and a failed batch is retried. Logs are also flushed when the app goes to the background. While the app is in the background the flush timer does not run: logs are sent when the batch size is reached or when the app returns to the foreground.
Best Practices#
Enable logging right after AbrovaTrace.init() to capture all events
Set a meaningful sourceId to identify logs from this app in the dashboard
Include structured metadata (user ID, screen name, etc.) for easier debugging
Use info for normal events, warn for potential issues, error for failures
Call AbrovaTrace.flushLogs() before app close to ensure all logs are sent
Avoid logging in tight loops — the buffer has a max size and will drop oldest logs