How to write logs using the EntainLogcatLogger
Overview
This document provides an overview of the new logging approach for our Android app. Our goal is to streamline and optimize logging across the codebase, addressing the current inconsistencies where a mix of Log.d
, Log.e
, EntainLogger.log
, Timber.d
, and others are used. The new logging module centralizes logging practices to provide a consistent, simple, and efficient way to handle logs throughout the app.
Why This New Logging Approach?
The previous logging setup was fragmented and required injecting instances of EntainLogger
into any class that needs to use its logging functions. This is cumbersome and prone to inconsistencies. To improve upon this, we have developed a new logging module that simplifies access to logging and provides several benefits:
Key Benefits
Improved Performance: In the current implementation, logs that use string interpolation can cause unnecessary CPU usage. This is because Kotlin evaluates the string expression even when logging is disabled. By using an inlined string-producing lambda in the
logcat()
function, we avoid this overhead. The string is only evaluated when logging is enabled, making it more performant.Simplified Tagging: The new
logcat()
function automatically uses the outermost class name as the log tag unless a specific tag is provided. This reduces the need for developers to manually define log tags and ensures that logs are consistently tagged throughout the app.Familiar Command Naming: The
logcat()
function's name matches the familiar Androidlogcat
command, making it easy to remember and reducing the learning curve for new developers who join the team.Flexible Logging Levels: With the new implementation, developers can easily specify the log priority using one of the
LogPriority
options. This flexibility allows for better control over log levels, helping to filter logs based on severity.Consistent and Simple Usage: The
logcat()
function defaults to the "debug" level, ensuring consistency across the codebase. This reduces the risk of forgetting to set a log level and keeps logging practices uniform.Effortless Throwable Logging: The
Throwable.asLog()
extension function allows easy logging of exceptions without adding a parameter to thelogcat()
method. This reduces cognitive load and eliminates the need to memorize parameter orders.Print Logs While Running Unit Tests: Logs are now available during unit testing. By adding
@ExtendWith(TestLogcatLoggingRule::class)
to your test class, you can output any logs from the functions that the test calls. This feature is great for quickly debugging tests.
How to Use the New Logging Module
The new logging module can be accessed anywhere that has the :core:common
dependency added. If a module does not have this dependency, you can directly add the :core:logging
dependency to use the logging functionalities.
Example usages
- Basic Debug Logging:
logcat { "message to log..." }
// Output: D/ClassName: message to log... - Logging with a Specific Tag::
logcat(tag = YOUR_TAG_HERE) { "message to log $item1, $item2" }
// Output: D/YOUR_TAG_HERE: message to log apple, orange - Logging with a Specific Priority::
logcat(tag = YOUR_TAG_HERE, LogPriority.INFO) { "test 123..." }
// Output: I/YOUR_TAG_HERE: test 123... - Logging Exceptions::
logcat { exception.asLog() }
// Output: D/ClassName: java.lang.RuntimeException: SOME EXCEPTION WAS THROWN
// at com.EntainApp.example(HomeFragment.kt:22)