Any application to some extent is using the logging system. And we are not an exception. We log a lot of information in our Android and iOS applications as well as in our backend server application. But what logs give us, after all, they are not contributing to the application functionality? They might be a part of user requirements, but why would anyone want to invest money and time for the feature that is not used by a user? Let’s explore the purpose of logs in software development and practices developers are applying.
Here are some of the cases where we are using logging in our applications:
- during development to make it easier and faster spot a bug along the
- @NonNull and other annotations and code inspection tool Lint
- unit and integration tests, where we try to cover most of the code execution paths and integrations points. (And I already wrote how we approached the testing in our project)
we use logs that show as the trace of actions and values that led to a particular bug. But before we started to use logs we had to answer the following questions:
- where to put log statements on
- what information to log
Since a lot of our code is covered by unit tests then there is little reason to log our own code for debugging and test purposes, but where we don’t have control over the values we are processing is:
- framework lifecycle methods, like onCreate, on ViewCreate, onResume, onPause in Android application. If our code is using the arguments provided by lifecycle method we log these values and assert the expected value if it is possible
- to click listeners and other event handlers
- third party library methods and their returned results. For example, for network calls we are using Retrofit and we always log the network requests and responses in debug build variant. Another example calls to the database. Since we are using Room in Android application, we want to see SQL code sent to the database
So once we log enough information we can spot the bug just by going through logs and skipping the process of starting the app again with attached debugger and stepping through the code. And we don’t have to worry much about the performance as well since Android logging system is taking care of debug log statements and skip them at runtime.
- in production:
to monitor, on the back end server the logs are used to monitor the normal business logic functionality. We log every request. If the request is successful we log it as info, in case request ends up we log error. When the error is reported on the back end service, the gathered logs are of great value. Very often they allow to spot the problem without further investigation.
- we log fatal errors, that caused the application stop. On the backend server, we catch the exceptions as early as possible and when the exception is caught it is logged and an email is sent to an administrator. We don’t experience many exceptions outside of our app on the back end part, because the only reason that can lead to such exception is a malformed request and not the back end code itself, and since the request is formed by third party library it is very rear that it is malformed. A different story is with uncaught exceptions on the client – Android or iOS app. It is not possible to catch all the exceptions so they leak and cause the app to crash. To log these kinds of exceptions we use Fabric Crashlytics (Firebase). These logs later help us a lot to find a cause of a crash.
Visit our website and join the mailing list! Our app is coming soon: