A lightweight, intelligent logging library for Android with beautiful tree-structured output and smart object detection.
- π³ Tree-structured output for complex objects and collections
- π Smart object detection with automatic formatting
- β‘ Runtime log level filtering
- π‘οΈ Enhanced reflection safety
- π Grouped logging with
logMany() - π― Zero breaking changes - drop-in upgrade
// build.gradle.kts (app)
implementation("com.github.mikeisesele:easylog:4.0.0")// settings.gradle.kts
repositories {
maven { url = uri("https://jitpack.io") }
}class MyApp : Application() {
override fun onCreate() {
super.onCreate()
EasyLog.setUp {
debugMode(BuildConfig.DEBUG)
filterTag("MyApp") // Optional: custom tag
minimumLogLevel(LogType.DEBUG) // New: runtime filtering
}
}
}// build.gradle.kts (app)
android {
buildFeatures {
buildConfig = true
}
}"Hello World".logD("Greeting")
42.logI("Answer")
true.logE("Boolean value")data class User(val name: String, val age: Int, val emails: List<String>)
val user = User("John", 30, listOf("john@work.com", "john@personal.com"))
user.logD("User profile")Output:
π USER PROFILE: at MainActivity.kt:45
ββ User (com.example.model)
ββ name: "John"
ββ age: 30
β°β emails: List[2]
ββ [0]: "john@work.com"
β°β [1]: "john@personal.com"
listOf("apple", "banana", "cherry").logD("Fruits")
arrayOf(1, 2, 3, 4, 5).logI("Numbers")Output:
π FRUITS: at MainActivity.kt:50
ββ List[3]
ββ [0]: "apple"
ββ [1]: "banana"
β°β [2]: "cherry"
logMany(
header = "App Configuration",
BuildConfig.DEBUG,
BuildConfig.VERSION_NAME,
"Environment: Production",
42
)Output:
π ββ APP CONFIGURATION at MainActivity.kt:55
π ββ [1] true
π ββ [2] "1.0.0"
π ββ [3] "Environment: Production"
π β°β [4] 42
val result = "Processing data"
.logInline("Step 1")
.uppercase()
.logInline("Step 2")
// Logs each step and returns the value for chainingval nullableUser: User? = getUser()
nullableUser.logInlineNullable("User lookup result")// Only show warnings and errors
EasyLog.setMinimumLogLevel(LogType.WARNING)
// Check current level
val currentLevel = EasyLog.getMinimumLogLevel()EasyLog.setUp {
debugMode(BuildConfig.DEBUG)
addDefaultLogger(DefaultLogger.FILE_LOGGER)
context(applicationContext) // Required for file logging
}class MyCustomLogger : Logger {
override fun log(
logMessage: String,
logObject: Any,
level: LogType,
fileName: String?,
lineNumber: Int
) {
// Your custom implementation
}
}
EasyLog.setUp {
addCustomLogger(MyCustomLogger())
}logV()- Verbose πlogD()- Debug πlogI()- Info βΉοΈlogW()- Warningβ οΈ logE()- Error βlogWtf()- What a Terrible Failure π₯
Zero code changes required! EasyLog v2 is 100% backward compatible.
- Enhanced object formatting (automatic)
minimumLogLevel()configurationlogMany()function- Better performance and safety
// Old way (still works)
.defaultLogger(DefaultLogger.DEFAULT_ANDROID)
// New way (recommended)
.addDefaultLogger(DefaultLogger.DEFAULT_ANDROID)- Minimum SDK: 24
- Kotlin reflection: Auto-included
- ProGuard: No configuration needed
-
Use meaningful messages:
user.logD("After API call") // Good user.logD() // Works, but less descriptive
-
Filter by tag in Logcat:
tag:MyApp -
Use appropriate log levels:
result.logD("Debug info") // Development error.logE("API failed") // Production issues config.logI("App started") // Important events
-
Leverage inline logging:
val processed = rawData .logInline("Raw data") .processStep1() .logInline("After step 1") .processStep2() .logInline("Final result")
MIT License - see LICENSE file for details
- Issues: GitHub Issues
Example Outputs
Reflection overhead: EasyLog v4 uses Kotlin reflection for enhanced object formatting, which adds computational overhead Development focus: Designed primarily for development and testing environments where debugging visibility outweighs performance concerns Production recommendations:
Use minimumLogLevel(LogType.WARNING) or higher in production builds Consider disabling complex object logging in release builds via debugMode(false) Monitor app performance when logging large or deeply nested objects
Technical Limitations
Obfuscated code: R8/ProGuard obfuscation may affect property names in formatted output Sealed classes: Some sealed classes or classes with restricted reflection access may display simplified output Memory usage: Complex object trees with circular references are handled safely but may use additional memory Thread safety: While EasyLog is thread-safe, logging very large objects concurrently may impact performance
Best Practices
Development workflow: Use detailed object logging during development and debugging phases Testing environments: Leverage full EasyLog capabilities in staging/testing environments Production deployment: Configure appropriate log levels to balance debugging needs with app performance Large datasets: Consider logging subsets or summaries of large collections rather than complete datasets
Scope & Compatibility
Android focus: Optimized for Android development workflows and Android Studio logcat integration Minimum SDK: Requires Android API 24+ due to reflection requirements Kotlin interop: Full compatibility with Kotlin data classes, sealed classes, and standard collections Java compatibility: Works with Java objects but optimal formatting designed for Kotlin constructs
Made with β€οΈ by Michael Isesele