Logging strategy - android

I'm about to finish my Android application. In the end I have found that I've been using bunch of logging statements, like:
Log.d(TAG, "Blah-blah");
The question is: for production release what should I do with them?
Just comment/stripe log statements
Do something else more sophisticated? Like as I used to do with Log4J properties or so
Please share your experience.

You can remove the logging statements in build time using an obfuscation tool. See here for details.

There is a new project, which enables log4j on android. Using lo4gj over slf4j is possible. It also provides an appender for LogCat. See project android-logging-log4j or log4j support in android

I have created a library for this specific purpose. It can be found here - LumberJack. You can install it using Jitpack and gradle (Please check README.md).
After installing, you'll have to change all Log calls to LumberJack calls (eg. LumberJack.d() instead of Log.d() etc.)
Tags are optional and by default set to "LumberJack". You can choose to set the default tag yourself.
You can change the filtering anytime using LumberJack.setLogLevel() method. To remove all the logs, you can just set the LogLevel to LogLevel.None.
LumberJack.setLogLevel(LogLevel.None);
So if you just want to remove all the logcat spamming logs, you will just have to set the log level filter.
Optionally you can choose to log into a text file instead of logcat with same filtering mechanism.

I do it like this, making the compiler remove all logging if DEBUG is false:
if (Constant.DEBUG) Log.d(TAG, "mein gott, state is roflcopter");

Depends. If you expect the application to crash often then include one of the crash reporting libraries for example but whatever you decide to do just don't release it with the Log.d() methods.

I've not experience on Android specifically but I'd just leave the logging staements in the code and turn off logging in the log4j properties file. You might even want to leave some logging turned on so that your app will generate useful logs in the event of a crash.
If you are worried about the log statement generation being too computational intensive (e.g. calling toString on a big collection) then you can use this pattern.
if (Log.isDebugEnabled()) {
Log.Debug(bigCollection.toString());
}

If you do not want to log something in Android release version, you can use automatically generated BuildConfig. See more about it here: https://developer.android.com/studio/build/gradle-tips.html. You can also read more information in this question: BuildConfig file in android - Purpose and Possibilities.
So in your code you simply write something like this:
if (BuildConfig.DEBUG) {
//your code just for development goes here
}

Related

Is it possible to redirect debug logs in ObjectBox?

I have a user who I've diagnosed to have object-box-related issues. I can send him debug builds with the ObjectBox debug flags (debugFlags(), debugRelations(), etc...) turned on. However, I would like to redirect the object box logs to a callback where I can collect the data and save to a file. Is this possible in ObjectBox?
Logs are currently created from native (C++) code, so there is no way to redirect them. But I agree a custom logger is a good idea (e.g. to log to an error report file on production builds).
If you have time, please create a feature issue for it at https://github.com/objectbox/objectbox-java/issues.

What is the best practice using Android Logger

I am new to Android. Please help me to know about the best practice of using Android Logger. Do I need to keep a file somewhere in android and keep on writing logs into it, or writing of logs into file is not necessary. What could be the best practice.
My real intention is this.
Once we go live, if our customers come back and tell us that something crashed or does not work in their android , then how do we debug ?
In the web application, I would ask my server administrator to provide the log files. What do we do with the android application when there is no server error, but something failed in the phone. Is there a way to get logs from the phone.
Thanks
Ravi
Depends on what you need, you need logging for semi debugging your application than you can easily use the buildin Log functionality. Via Logcat you can easiliy see the logs.
http://www.vogella.com/tutorials/AndroidLogging/article.html
//Declare a tag
String TAG= "SomeActivity";
//Log
Log.d(TAG, "Hello World"); //debug
Log.e(TAG, "Hello World"); //error
If you want to have logging of multiple devices when you have released your app. Use a dedicated Log Framework (e.g. Log4J) and upload it to a server.
One tip (if you are using Eclipse, and not directly related to question) - Eclipse is very unreliable for viewing logs. For apparently no reason it completely stops displaying logs every now and then. A simple solution is to use command line tools for viewing logs. On Linux you can do :
$adb logcat MyTag:D *:S
If you want to capture logs to a file you can do:
$adb logcat -d > logcat.txt.
Hope this helps!
If you are planning to publish/distribute your application then storing logs in a file is possible but as per my opinion better not a better solution. You can configure online tools from your app.
Catch all sever exceptions and sending all the details regarding that exception. And configure any one logging tool into you application.
You can see log4j http://logging.apache.org/log4j/2.x/ or ACRA http://acra.ch/ or http://www.crittercism.com/
The Android logger's (android.util.Log) output goes to a console that you don't have to maintain. You don't actually have to manage files, just outputs.
You have 5 categories of log:
verbose: use Log.v(tag, message)
debug: use Log.d(tag, message)
info: use Log.i(tag, message)
warning: use Log.w(tag, message)
error: use Log.e(tag, message)
For example:
Log.e("MyActivity", "Oops... caught this exception: " + exception.getMessage());
The LogCat console (this is its name) allows you filtering by log level. This is a ceil filtering. For example, if you filter by 'warnings', you will see all warnings and errors, but not verbose, debug and info messages.
You'll find more details here in the official documentation.
My real intention is this.
Once we go live, if our customers come back and tell us that something crashed or does not work in their android , then how do we debug ?
In the web application, I would ask my server administrator to provide the log files. What do we do with the android application when there is no server error, but something failed in the phone. Is there a way to get logs from the phone.
If you use file for storage logs - it possible problem with performance if the file become big. So you need clean file in time.
As for me best solution use firebase or https://fabric.io/.
We use fabric.io.
Also you can use some wrapper for default Log class. This one https://github.com/JakeWharton/hugo for example

Disable GoogleAnalytics from Android App when testing or developing

I'm using EasyTracker in my Android App and I need a way to disable Analytics tracking when the app is in "development" or "testing" mode (I have a flag in a constants file to discriminate).
What's the best way to do so?
Thanks!
I believe the correct way to do this with Version 4 of Analytics is with the Opt Out method
GoogleAnalytics.getInstance(this).setAppOptOut(true);
You could set that method to be set if you build in debug mode. ie.
GoogleAnalytics.getInstance(this).setAppOptOut(BuildConfig.DEBUG);
I am using something similiar to allow users to opt-out of analytics.
I found this information at he following link: https://developers.google.com/analytics/devguides/collection/android/v4/advanced
Edit: Just saw the date of the original question, but thought I would add this answer anyway as it was something I was looking for.
UPDATE: With release of Google Analytics v3 for Android,
The SDK provides a dryRun flag that when set, prevents any data from
being sent to Google Analytics. The dryRun flag should be set whenever
you are testing or debugging an implementation and do not want test
data to appear in your Google Analytics reports.
To set the dry run flag:
// When dry run is set, hits will not be dispatched, but will still be
logged as though they were dispatched.
GoogeAnalytics.getInstance(this).setDryRun(true);
+++ My old answer +++
Just comment the following line in your analytics.xml file while you are in development mode.
<string name="ga_trackingId">UA-****</string>
Google Analytics wouldn't be able to find any tracking id, so EasyTracker won't be able to do its job.
When you are building the app for release, uncomment the line and you're good to go.
If you are building a standalone app(not a library), this will be the easiest way to do it, let the build system figure out if it is a debug build or not.
if(BuildConfig.DEBUG){
GoogleAnalytics.getInstance(this).setDryRun(true);
}
I see on the web that this method does not work well for library projects as there is bug in the build tools which does not set the BuildConfig.DEBUG flag correctly for libraries. Not sure if this issue is fixed now.
You can use a class with a static boolean value let's say DEBUG like this :
public final class BuildMode {
public final static boolean DEBUG = true;
}
In code, just use :
if (BuildMode.DEBUG) ...
This is a solution working on all android SDK versions!
Newest version from firebase has this method that can be put inside App class:
FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(!BuildConfig.DEBUG);
What I'm doing is disabling periodic dispatching, by setting a negative period, in analytics.xml:
<integer name="ga_dispatchPeriod">-60</integer>
or you can do it programmatically, using your flag:
if (testingMode) {
GAServiceManager.getInstance().setDispatchPeriod(-1);
} else {
GAServiceManager.getInstance().setDispatchPeriod(60);
}
That way hits are not sent unless you do it manually.
That should work if you are using only periodic dispatching (never calling .dispatch() manually). Hits not sent before 4 a.m. of the following day are somehow discarded, I guess, as they are not appearing in the reports anyway.
See in Google Analytics Developer Guide:
Note: Data must be dispatched and received by 4 a.m. of the following day,
in the local timezone of each profile. Any data received later
than that will not appear in reports.
More info: https://developers.google.com/analytics/devguides/collection/android/v2/dispatch
My technique is to change the android:versionName in Android Manifest until release time.
For example, 1.0.0.ALPHA until time to build a release APK, at which point you could change to 1.0.0. This way you can still see all of your crash reports later, but they will grouped in analytics.
This SO ticket talks about using the BuildConfig.DEBUG flag to conditionally configure analytics and Atul Goyal's answer references the dryRun flag in v3. Those two things could be a nice setup if you don't care about seeing crash reports during debug in the future, and assuming that the BuildConfig.DEBUG flag works correctly.
I have a different approach to this issue. Sometimes you still want to test that analytics is working correctly, but want to just filter test data out in production reports. My solution to that is to create a custom session-scoped dimension (i.e. AppBuild), in GA for the property which tracks if you are running a debug or production build of the app. In your code after you create the Tracker, put:
// replace 1 with the correct dimension number if you have other dimensions defined
tracker.set("&cd1", BuildConfig.DEBUG ? "debug" : "production");
Then create or modify your GA view to add a filter on AppBuild, excluding debug. This should filter out all debug data from your GA view. You can also add a new view to show debug data.

Android: Make the app logs my logging statements "only"

I am planning on signing an apk and releasing it (through Export Eclipse tool). Then upload it to the market. I know that debuggable is set to false by default when signing it so that means that no logs will be captured. At the same time, if I set debuggable to true and release the apk then I will get all the logs.
What I am really interested in is the last debug statement that are added by me only. Currently, I am using the Log.i statement to add info logs. Is there a way to have my app logging only the Info logs (i.e. my logs only). Mybe if I disable the log and have system.out.print it would work?
The reason I am doing this is becuase I want to send the last 100 lines of log when a crash happens and I am only interested in my log statments.
Please help me out
Thanks
I believe what you need to do is take advantage of ACRA's built in filtering functionality:
In the Advanced Usage wiki you can see that you can set your logcat arguments in your config.
In your logging, tag your custom log messages with a specific tag and debug level, then in the logcat arguments, then set a parameter:
logcatArguments = { "-t", "100", "-v", "long", "ActivityManager:I", "MyApp:D", "*:S" }
add one in the form of
"YourCustomTag:<YOUR_DEBUG_LEVEL>"
and take out the ones you don't want to be logged (probably MyApp:D in this case.)
You will have to put a wrapper on top of Log where you can put functionality to control the log levels.
This type of functionality is already implemented by the ACRA Android library. The library detects crashes, and send the crash information to either a Google Docs spreadsheet, or your own destination. You can add additional information like the past 100 lines of your log using the method shown here.

Ways to dynamically enable/disable debug features in an APK

I'm developing an APK. I'd like to be able to set and unset various options for debugging purposes. For example:
Enable a time profile trace
Enable some experimental feature
Enable very verbose output to logcat
...
Currently, we do this by creating a flag in our code for each feature and set/unsetting it. However:
is time consuming because of the need to rebuild, upload and relaunch the APK
runs the risk of people accidentally checking things in in a debug mode state
requires a rebuild of the APK -- we can't ask our customers to enable a debugging feature and report the results.
Is there a pattern that Android developers follow solve this kind of problem?
In the past, we've used environment variables for this purpose.
You may use the debugging permission SET_DEBUG_APP in your apk. Create a new class called
class MYLog {
i(String Tag, String msg) {
if(LOG_ENABLED){
Log.i(TAG, msg);
}
You may call the MyLog.i instead of Log.i(). You may get the LOG_ENABLED value from the server to enable/disable logging.
I'd consider doing it one of two ways, depending on how much of this feature you want to expose to your users:
Key the debug features off of SharedPreference values, and expose them in a preferences/debug menu in the UI.
Use the presence/contents of a file in external storage where you can email the file to & instruct an end user where to place it to enable the debug features.
Option 2 is not much different a notion than using environment variables.

Categories

Resources