Skip to main content

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

  1. 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.

  2. 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.

  3. Familiar Command Naming: The logcat() function's name matches the familiar Android logcat command, making it easy to remember and reducing the learning curve for new developers who join the team.

  4. 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.

  5. 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.

  6. Effortless Throwable Logging: The Throwable.asLog() extension function allows easy logging of exceptions without adding a parameter to the logcat() method. This reduces cognitive load and eliminates the need to memorize parameter orders.

  7. 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

  1. Basic Debug Logging:
    logcat { "message to log..." }
    // Output: D/ClassName: message to log...
  2. 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
  3. Logging with a Specific Priority::
    logcat(tag = YOUR_TAG_HERE, LogPriority.INFO) { "test 123..." }
    // Output: I/YOUR_TAG_HERE: test 123...
  4. Logging Exceptions::
    logcat { exception.asLog() }
    // Output: D/ClassName: java.lang.RuntimeException: SOME EXCEPTION WAS THROWN
    // at com.EntainApp.example(HomeFragment.kt:22)