Home > Software design >  How to throttle the same messages in the Logcat?
How to throttle the same messages in the Logcat?

Time:12-07

I need to log important stuff of the Android application using Log class. Mostly I used debug, info and error type. My problem is that some logs are quite often printed to the Logcat e.g. GPS status, listening free space of the phone etc. For the application this gap between some updates it's crucial and cannot be changed, but I don't need so many repetitive lines in Logcat.

My goals are:

  • if it's the first time of some message, print it as it is
  • if the message happens to occur earlier check if the defined gap of the time has passed if not ignore the log

I created LogData class:

data class LogData(
    val message: String,
    val type: LogType
)

where type is:

enum class LogType {
    DEBUG,
    INFO,
    ERR
}

I wonder if it's possible to use RxJava for that and some throttle operator but I don't know how exactly to take the same message into consideration and ignore it:

        log.throttleFirst(GAP_IN_MS, TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { (message, type) ->
                when(type) {
                    LogType.DEBUG -> debugMessage(message)
                    LogType.INFO -> infoMessage(message)
                    LogType.ERR -> errorMessage(message)
                }
            }

where private val log = BehaviorSubject.create<LogData>()

CodePudding user response:

I don't see a need for RX here, just a wrapper around log.

class MyLogger {

  private val messagesSent = mutableMapOf<LogData, Long>()
  private val timeOut = 1000;  //number of ms that must pass before logging the same object again
  
  fun log(message: LogData) {
    if((messagesSent?.get(message) ?: 0) < System.getCurrentTimeMillis - timeOut) {
      Log.d(message.message)
      messagesSent.put(message, System.getCurrentTimeMillis())
    }
  }
}

Then use this instead of the android logger. If you want something more complex than a timeout for throttling, just put that logic in here instead.

Now this will slowly increase the size of the messagesSent map over time. If this becomes a memory concern, you can just create a thread or coroutine that every so often walks the map and evicts anything over timeOut seconds ago from it.

Now you will have threading issues. The easiest way to avoid it is to use a synchronized map class. If you don't want to do that you could use rx and have the logger class have an observable, have log publish the value to that observable, and have a subscriber to that observable that does the logic in my log function currently. That will definitely work, although I'd just use the synchronized map class for easier to understand code unless you have so many log statements that locking time becomes an issue.

  • Related