Tech Corner - 11. March 2024
header_image

Improve your logging in Android

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:

kotlin

[code language=kotlin]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:

kotlin

[code language=kotlin]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:

kotlin

[code language=kotlin]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:

kotlin

[code language=kotlin]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:

kotlin

[code language=kotlin]if (BuildConfig.DEBUG) { Log.d(TAG, "message") } 

Or create an extension similarly as for TAG:

kotlin

[code language=kotlin]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:

javascript

[code language=latex]-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 the author

Pavol Madeja

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

READ MORE