log well live well

Improve your logging in Android

Logging – you’re sure to have heard of it and are perhaps wondering, what else can I learn about it?

Well, funny fact first, did you know that in the English language logging actually means the transporting and processing of wood? So, lumbermen log as well 😊 Bet you feel like a real man now, right bruh? 💪

But let’s get back to our universe, where logging means the recording of useful information. It can be our helping hand, but it can become a nightmare as well. I’m sure you can recall at least a couple of occasions when you’ve gaped at a stream of thousands of log messages at a late evening hour, your eyes hurt and you just couldn’t seem to hunt down that bug. Which is why it’s important to have some standards for doing even the most basic kinds of developer’s activity, such as logging.

You’re probably familiar with the Logging API:

Log.e(TAG, "message")

You can log with different priority levels, where “e” (error) is the highest priority, shown in red in the Logcat window in Android Studio, with the lowest being “v” (verbose). More info on that can be found here: Write and View Logs with Logcat  |  Android Developers

There is even a method called Log.wtf() 😊 Let’s be clear here, WTF in this case stands for “What a Terrible Failure” and you use this to log something that should technically never happen.

Now, what about real-world logging situations? You might have seen someone commit this kind of log into a codebase:

Log.d("jonny", "1 prc: " + model.price + " comput: " + model.width * model.height)

It surely have helped Jonny to fix his issue that day, and deserve his after-shift beer, but even he would have a hard time reading these logs after a while. So how could Jonny improve this?

Firstly, he could start grouping logs by the tags. Documentation says a tag should be the name of the activity or class from where you call it.

You can define Kotlin extension for a TAG property this way:

val Any.TAG: String
    get() {
        val tag = javaClass.simpleName
        return if (tag.length <= 23) tag else tag.substring(0, 23)
    }

This way, you don’t have to define it independently for each of your classes.

The next step would be to clarify the message itself. It should be easily readable, convey only necessary information and it should not bloat the log output.

So in the end, Jonny’s log would work better this way:

Log.d(TAG, "Price of the property: " + model.price + ",  property area: " + model.width * model.height)

You can see that this was logged under a debug level. Some developers tend to log only error states. Good practice is somewhere in between – not to log too much, or too little.

Logs and releasing

You don’t want to risk a skilled user accidentally finding some sensitive logs – such as user information, tokens, credit card numbers, birth dates etc. – on his device. So before you release an app to the stores, make sure all logs are removed. One of the options for doing this is to use BuildConfig.DEBUG property. BuildConfig is a Gradle generated class, so you can find it in your generated-files source path.

You can use it simply like this:

if (BuildConfig.DEBUG) {
    Log.d(TAG, "message")
}

Or create an extension similarly as for TAG:

val Any.isDebug: Boolean
    get() = BuildConfig.DEBUG

However, handling all of the logs this way is quite a cumbersome process. In case you don’t want to overcrowd your code with so many conditions, or to make sure that you’ve really taken care of all your logs and haven’t missed one, you can configure Proguard to remove all log calls for release builds this way:

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** e(...);
    public static *** i(...);
}

Timber

If this is still too much to bother with, you can consider using Timber.

You can simply initialize Timber in debug mode only, by planting DebugTree (more info about this can be found here: https://github.com/JakeWharton/timber)

Timber’s API is very similar to Android Log API, but you don’t even have to provide the TAG as it detects it itself.

That’s it for today – hopefully you found some useful information here, and happy logging!

about author

Pavol Madeja

Pavol is the leader of mobile stream in Hotovo and a real mobile enthusiast. Starting with the coding of programmable calculators in his childhood, he is no stranger to the idea of developing mobile devices. He previously worked for companies like Samsung and Nokia and is now strengthening our mobile development team.

READ MORE

newsletter

Color formats in CSS, news in Angular v13 and a whole lot more

Hello readers!  Just as we do every month, we’ve pulled …

programming principles cover

Programming Principles – My Way of Being a 10x Developer

If I can name one thing that opened my eyes …

programming principles cover

Learn with HOTOVO (video)

“Learning and improving not only yourself, but also helping others …