- Better Logging In Android Using Timber
- 1. Condition based logging
- 2. ProGuard
- Here comes Timber, the best solution to tackle this problem
- Timber : A step towards better Logging
- Getting Started
- Initializing Timber
- Creating MainActivity
- Customizing Timber for Debug and Release
- Creating a Custom Tree
- Result
- Benefits of using Timber vs Android Logging
- Conclusion
- Mobile File Logging in Android with Timber
- Why Bother?
- File Logging
- 2 Loggers Sucks!
- Update: November 23, 2016
- Передаем Android логи через интернет с Timber и Node.JS
- Часть 1. Проблема
- Часть 2. Описываем проблему
- Часть 3. Пишем для Android
- Часть 4. Пишем сервер
- Часть 5. Заключение
Better Logging In Android Using Timber
While developing android applications we as developers tend to put in a lot of logs with in different different priorities for this sake android sdk comes in with a utility class Log, which does have utility methods to log our messages with different priorities the most common methods that we use for different cases like we uses Log.e(TAG,”message”) in the cases we want to show some error (this usually appears in red color in the logcat window of android studio), or Log.d(TAG, «message») when we want to print some message for the purpose of debugging, like value of some data.
Usually when the application development is completed and its the time to release the app on the play store, we need to remove all Log statement from the app, so that none of the application data such as user information, hidden application data, auth-tokens are available to user in logcat as plain text and this becomes a cumbersome task
There are several ways to tackle this problem
1. Condition based logging
In this we can make a public static boolean variable in Application class like in the below code snippet.
and use this variables value as check for logging like the code snippet below
and use this boolean variable at every place where you want to put a log message, and once you are ready to release the app, just set isDebug = false in the application class, but this approach puts in an extra line of code, which is completely unnecessary and can be avoided.
This simply can be achieved using android’s in built build configuration, BuildConfig. DEBUG can be used instead of that boolean variable for checking if the build type is release or debug.
2. ProGuard
This approach is all also a solution to this problem, you can render the Log class ineffective and can remove those statement in the release build by putting in
into the proguard rules file.
Here comes Timber, the best solution to tackle this problem
What if I tell you there exists a simple library called “Timber” which can log your messages and gives you the control over the flow of logs. Timber is a yet another cool library developed by an awesome developer Jake Wharton.
Adding timber to you project
To add timber to your android studio project, just paste in the below line in to /app/build.gradle file and sync the project.
Once the project is synced just plant a timber debug tree in the Application class, because as per the instruction on Timber’s github page and I quote it
Installation of Tree should be done as early as possible. The onCreate of your application is the most logical choice.
Here, Timber.DebugTree() prints the logs when your application type is debug application.
And that’s all we need to do in order to use timber. Wherever you have used that Log…(…) statement just remove that tag parameter and replace Log with Timber.
as you can see in the above gist, that it is not required to pass in the tag parameter in the Timber.d(. ) or Timber.e(. ) statement, as Timber automatically detects the class in which logs were written.
But there might me requirement when you need to specify a custom tag which can be simply achieved by
as shown in the above gist. More about Timber can be found at :
Источник
Timber : A step towards better Logging
Logging is one of the most used utility in android framework. It is really helpful in debugging your code when debugging by break-point just wont work. It is generally a good practice to place Log statements in your code as it helps you keep a track of flow control in your application. Similarly, it is not a recommended to have log statements in your release ready code, since those log statements can be read by anyone who connects his phone to a PC. So, when releasing your application to the play store, it is recommended to remove all the log statements from your code.
But this can be a real pain. There are so many log statements all over your code and now you have to manually find each one and remove it from your code just for the release version.
Another problem with the default logging mechanism is that you need to pass the TAG, every time you write a log statement.
Wouldn’t it be wonderful if the log statements would automatically disable themselves when in production? Wouldn’t it be great if the Log statements automatically picked up the TAG/classname while logging and you could just focus on writing better code?
Well, problems such as these and many more are solved by a better logging library in android, called Timber (by Jake Wharton).
It is a light-weight, easy to use library which takes care of most of the maintenance you need to do while logging so that you can focus more on writing great code and less on the maintenance stuff.
Let’s go ahead and create a sample application to see how you can include Timber in your android application and make your logging life easier.
Getting Started
We will be creating a simple android application with 4 buttons. Each button would print out different priority log statement on the console.
Create a new project in Android and add a dependency for Timber in your app level build.gradle file. At the time of this writing, this is the latest dependency version for timber:
Initializing Timber
With the dependency downloaded, now it’s time to initialize the timber library. Best place to initialize timber is in the Application class which will be active during the entire lifetime of the application. So, let’s create a custom application class and initialize our Timber library in it:
Creating MainActivity
Let’s now create our MainActivity by adding 4 buttons and setting on click listeners to each of them. Here is my activity_main.xml file. I’m using ConstraintLayout as my root layout and including 4 buttons each for different logging levels.
Now it’s time to set click listeners to these buttons and print a log statement every time a button is clicked. I’m using kotlin’s synthetic bindings instead of regular findViewById calls or Butterknife. Here is my MainActivity.kt file:
Notice how we didn’t need to initialize any TAG variable in our class, Timber does it automatically for you.
Customizing Timber for Debug and Release
Now, this is where Timber really shines. What we’ve done till now was nothing great, just printing the log statements on button clicks. But as you know, logging in production is not a good idea, so now we will write code to disable the logs for production while keeping them enabled during debug mode.
We’ll write a if block to check if our app is in debug mode and enable logging for that, if not, then we want to initialize Timber using a custom tree.
Here’s the modified MainApplication.kt class:
As you can see, we’ve initialized timber using a custom ReleaseTree when in release mode. Now let’s go ahead and create our own release tree.
Creating a Custom Tree
Creating a release tree is fairly simple. Create a new Kotlin class and extend it from Timber.Tree. Implement all the abstract functions and you’re good to go.
Here’s my ReleaseTree.kt:
As you can see, whenever there is an error, we can send the log to an online service such as Firebase CrashAnalytics or Crashlytics and not logging out on production.
Result
Benefits of using Timber vs Android Logging
Let’s look at some of the benefits of using Timber library instead of the default Log utility by android sdk.
- No need to worry about TAGS: Timber generates the TAGs automatically for you so you don’t have to worry about including a global TAG in every class.
- No need to manually remove Log statements: As already shown, it’s really easy to disable Logging for release apps. Hence, you no more have to go through your entire code and manually remove all the logs.
- Customized behavior on production: In production versions you don’t want to log, although you definitely want to log any crashes that might occur. You can implement this by using a custom debug tree (as shown above) which instead of logging to the logcat, sends the logs to your crashlytics service.
- Customized Meta-Data: You can include customized meta data with your log statements. For example: I’ve added class name, line number and method name from which the log statement is getting printedi n the implementation above. Having this data at your disposal can make debugging easier.
- Lightweight: Does’t not increase your app size/method count by much. Really lightweight library as it is just a wrapper over the already existing log utility.
Conclusion
For long I had ignored the use of log statements and printing out better logs, but as my code got bigger and problems got complex, I realized I needed to adopt better and more efficient debugging routines and hence, using Timber is one step in the right direction.
*Important*: I’ve created a SLACK workspace for mobile developers where we can share our learnings about everything latest in Tech, especially in Android Development, RxJava, Kotlin, Flutter, and overall mobile development in general.
Like what you read? Don’t forget to share this post on Facebook, Whatsapp, and LinkedIn.
You can follow me on LinkedIn, Quora, Twitter, and Instagram where I answer questions related to Mobile Development, especially Android and Flutter.
If you want to stay updated with all the latest articles, subscribe to the weekly newsletter by entering your email address in the form on the top right section of this page.
Источник
Mobile File Logging in Android with Timber
“Every time you log in production, a puppy dies.” — Jake Wharton
As I wrote about in my 4 Rules to Picking Android Libraries post some months ago, Jake Wharton’s Timber library is one of the first that goes into any Android application I write.
Replacing the Android Log might seem like a waste of time, but once you’ve a) stopped needing to make those ridiculous static final TAG constants in your classes, and b) enjoy a logger that has sane defaults, and can be turned on/off with one line of code — you’ll see the light.
What’s really cool about it is that it’s very extensible, and just by ‘Plant’ing a new Tree, you can create another log output. The natural example is a crash logger in Release mode (e.g. tied into Crashlytics/Flurry/etc) — with a different log ’volume’ than the vanilla debug logger.
Why Bother?
Sometimes there is just no replacement for getting logs from the field.
I ran into an issue recently where a tablet communicates with a hardware sensor over USB. As of a few days ago, a strange problem started occurring in the field (after months of problem-free operation). No crashes, but just some sort of inconsistent behaviour that would come and go. I couldn’t come close to replicating it myself, but when it happened again in the field — we had the logs to show the problem.
Turns out it was an environmental issue dealing with humidity where the sensor was used sometimes. Whack.
File Logging
Writing a file logging utility is a waste of time, given that there are dozens or hundreds already written out there — some of which are stable, mature, and well tuned. Also, writing your own new one can be problem-prone… I inherited a project where the original developer wrote their own file logging tools, and the logger was responsible for about 10% of crashes in the field.
For this project, I used Logback Android — which uses Logback and the SLF4J API.
I configured Logback using an XML file to generate HTML (more verbose, but easier for my client to dig through). I also set it up to roll logs when either the day changed, or a log file exceeds 5MB (and cap the number of log files at 30):
File logging is as simple as:
2 Loggers Sucks!
Agreed… I refuse to have to make two calls to two loggers inside my code.
In many other mobile projects I’ve come into, where there is a traditional developer-centric console log, and a file logger, it’s often that there are two completely separate APIs — one for the file logger, one for the console logger. This makes no sense to me 95% of the time. Also, what happens when someone new joins the team, and doesn’t realize that they need to call 2 loggers and 2 log APIs to correctly save data. Ridiculous.
My solution to this was pretty simple. I created another Timber Tree, which implemented my file logging, and every call to Timber.(logVolume) would immediately call my DebugTree to print to the console AND go straight into my FileLogger — so that my console log would actually be cloned down into a file — which makes debugging much easier.
Note: I was a bit lazy, as I inherited from DebugTree so that I could use the already-written tag code.
Now, wherever you initialized Timber in the first place, use these lines:
And you’re off to the races!
Update: November 23, 2016
In case you’re wondering, this is an example of how to switch the XML to code. The problem with the XML is that you need to specify an absolute log directory, which is a little bit brittle. Also, as of Android Marshmallow, you also need to request run-time permissions to access the external storage.
Here is an example of logging to the Android internal files directory.
Источник
Передаем Android логи через интернет с Timber и Node.JS
Многабукаф, не читал: я напилил очень простую реализацию удаленного логгинга. Может быть полезно, когда у вашего клиента (или, например, тестировщика) выскакивает непонятная ошибка, а вам хочется видеть сиюсекундно, что происходит в приложении. Заинтересованных прошу ниже.
Часть 1. Проблема
Вообще проблема появилась так: у тестировщика баг воспроизводился, а у меня — нет. Надо было глянуть логи, по adb подключиться было нельзя (потому что тестировщик в другмо городе и доступа к админке роутера не имел), а перекидываться файликами — это какой-то отстой.
Часть 2. Описываем проблему
Есть такая штука — Timber. Для тех — кто не знает: это библиотека, которая расширяет стандартные возможности Android’овского класса Log. При логгинге библиотека автоматически добавляет в качестве TAG название класса и название метода. Но что для нас еще важнее — там можно оверрайднуть метод логгинга и что-то сделать еще внутри.
План такой: пишем отправку сообщения на сервер со стороны Android, а потом пишем сервер для приемки сообщений.
Часть 3. Пишем для Android
В build.gradle кладем вещи: одна — что у нас DEBUG режим, вторая — SERVER_LOGGING.
Подключение логгера будет выглядеть вот так (этот код надо вызвать в Application):
Как у нас вообще выглядит отправка лога? У лога есть приоритет, сообщение, тэг, дата. И урл, куда его отправлять, в случае удаленного логгинга. Все это дело возвращает Completable.
Нам надо отправлять это все на сервер с помощью, например, Retrofit’a:
Теперь давайте напишем саму отправку.
Теперь давайте посмотрим на наш класс ServerLoggingTree. Там мы оверрайдим метод логгинга и вызываем в нем метод отправки на сервер.
На этом, собственно, часть для Android закончена.
Часть 4. Пишем сервер
Писать будем на Node.JS, но вообще можно на чем угодно.
Для логгинга мы используем библиотеку Bunyan, потому что она, во-первых, поддерживает запись в файл, а во-вторых, она позволяет выводить сообщения красиво раскрашенными.
Давайте напишем штуку, которая отвечает за логгинг. Пишем, что у нас под каждый тип послания свой файлик.
Теперь напишем метод для приема логов от Android’a. Константы, отвечающие за приорити, были определены опытным путем.
Вот это мы примерно пишем в app.js, дабы подключить нашу штучку для логгинга.
Но вообще тут два пути: если сделать так, как описано выше (без https), то в Android придется вкатывать network_security_config, разрешающий CLEARTEXT коммуникацию. Поэтому по-хорошему надо сделать вот что: на своем роутере сделать DDNS, потом получить для этого домена сертификат (через letsencrypt), ну и поднимать сервак уже с сертификатом.
Часть 5. Заключение
Всем спасибо за прочтение, надеюсь, я кому-то помог.
Источник