OLD | NEW |
1 ## Logging ## | 1 ## Logging ## |
2 | 2 |
3 Logging used to be done using Android's [android.util.Log] | 3 Logging used to be done using Android's [android.util.Log] |
4 (http://developer.android.com/reference/android/util/Log.html). | 4 (http://developer.android.com/reference/android/util/Log.html). |
5 | 5 |
6 A wrapper on that is now available: org.chromium.base.Log. It is designed to wri
te logs as | 6 A wrapper on that is now available: org.chromium.base.Log. It is designed to wri
te logs as |
7 belonging to logical groups going beyond single classes, and to make it easy to
switch logging on | 7 belonging to logical groups going beyond single classes, and to make it easy to
switch logging on |
8 or off for individual groups. | 8 or off for individual groups. |
9 | 9 |
10 Usage: | 10 Usage: |
(...skipping 25 matching lines...) Expand all Loading... |
36 | 36 |
37 * By default, Verbose and Debug logs are not enabled, see guarding: | 37 * By default, Verbose and Debug logs are not enabled, see guarding: |
38 | 38 |
39 ### Log calls are guarded: Tag groups can be enabled or disabled using ADB ### | 39 ### Log calls are guarded: Tag groups can be enabled or disabled using ADB ### |
40 | 40 |
41 adb shell setprop log.tag.cr.YourModuleTag <LEVEL> | 41 adb shell setprop log.tag.cr.YourModuleTag <LEVEL> |
42 | 42 |
43 Level here is either `VERBOSE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `ASSERT`, or `
SUPPRESS` | 43 Level here is either `VERBOSE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `ASSERT`, or `
SUPPRESS` |
44 By default, the level for all tags is `INFO`. | 44 By default, the level for all tags is `INFO`. |
45 | 45 |
| 46 ### An exception trace is printed when the exception is the last parameter ### |
| 47 |
| 48 As with `java.util.Log`, putting a throwable as last parameter will dump the cor
responding stack |
| 49 trace: |
| 50 |
| 51 Log.i(TAG, "An error happened: %s", e) |
| 52 |
| 53 I/cr.YourModuleTag: ( 999): An error happened: This is the exception's messa
ge |
| 54 I/cr.YourModuleTag: ( 999): java.lang.Exception: This is the exception's mes
sage |
| 55 I/cr.YourModuleTag: ( 999): at foo.bar.MyClass.test(MyClass.java:42) |
| 56 I/cr.YourModuleTag: ( 999): ... |
| 57 |
| 58 Having the exception as last parameter doesn't prevent it from being used for st
ring formatting. |
| 59 |
46 ### Logging Best Practices | 60 ### Logging Best Practices |
47 | 61 |
48 #### Rule #1: Never log PII (Personal Identification Information): | 62 #### Rule #1: Never log PII (Personal Identification Information): |
49 | 63 |
50 This is a huge concern, because other applications can access the log and extrac
t a lot of data | 64 This is a huge concern, because other applications can access the log and extrac
t a lot of data |
51 from your own by doing so. Even if JellyBean restricted this, people are going t
o run your | 65 from your own by doing so. Even if JellyBean restricted this, people are going t
o run your |
52 application on rooted devices and allow some apps to access it. Also anyone with
USB access to the | 66 application on rooted devices and allow some apps to access it. Also anyone with
USB access to the |
53 device can use ADB to get the full logcat and get the same data right now. | 67 device can use ADB to get the full logcat and get the same data right now. |
54 | 68 |
55 If you really need to print something , print a series of Xs instead (e.g. "XXXX
XX"), or print a | 69 If you really need to print something , print a series of Xs instead (e.g. "XXXX
XX"), or print a |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 if (DEBUG) { | 118 if (DEBUG) { |
105 Log.i(TAG, createThatExpensiveLogMessage(activity)) | 119 Log.i(TAG, createThatExpensiveLogMessage(activity)) |
106 } | 120 } |
107 | 121 |
108 Because the variable is a `static final` that can be evaluated at compile ti
me, the Java | 122 Because the variable is a `static final` that can be evaluated at compile ti
me, the Java |
109 compiler will optimize out all guarded calls from the generated `.class` fil
e. Changing it | 123 compiler will optimize out all guarded calls from the generated `.class` fil
e. Changing it |
110 however requires editing each of the files for which debug should be enabled
and recompiling, | 124 however requires editing each of the files for which debug should be enabled
and recompiling, |
111 while the previous method can enable or disable debugging for a whole featur
e without changing | 125 while the previous method can enable or disable debugging for a whole featur
e without changing |
112 any source file. | 126 any source file. |
113 | 127 |
114 - Annotate debug functions with the `@NoSideEffects` annotation. | 128 - Annotate debug functions with the `@RemovableInRelease` annotation. |
115 | 129 |
116 That annotation tells Proguard to assume that a given function has no side e
ffects, and is | 130 That annotation tells Proguard to assume that a given function has no side e
ffects, and is |
117 called only for its returned value. If this value is unused, the call will b
e removed. If the | 131 called only for its returned value. If this value is unused, the call will b
e removed. If the |
118 function is not called at all, it will also be removed. Since Proguard is al
ready used to | 132 function is not called at all, it will also be removed. Since Proguard is al
ready used to |
119 strip debug and verbose calls out of release builds, this annotation allows
it to have a | 133 strip debug and verbose calls out of release builds, this annotation allows
it to have a |
120 deeper action by removing also function calls used to generate the log call'
s arguments. | 134 deeper action by removing also function calls used to generate the log call'
s arguments. |
121 | 135 |
122 /* If that function is only used in Log.d calls, proguard should complet
ely remove it from | 136 /* If that function is only used in Log.d calls, proguard should complet
ely remove it from |
123 * the release builds. */ | 137 * the release builds. */ |
124 @NoSideEffects | 138 @RemovableInRelease |
125 private static String getSomeDebugLogString(Thing[] things) { | 139 private static String getSomeDebugLogString(Thing[] things) { |
126 /* Still needs to be guarded to avoid impacting debug builds, or in ca
se it's used for | 140 /* Still needs to be guarded to avoid impacting debug builds, or in ca
se it's used for |
127 * some other log levels. But at least it is done only once, inside th
e function. */ | 141 * some other log levels. But at least it is done only once, inside th
e function. */ |
128 if (!Log.isLoggable(TAG, Log.DEBUG)) return null; | 142 if (!Log.isLoggable(TAG, Log.DEBUG)) return null; |
129 | 143 |
130 StringBuilder sb = new StringBuilder("Reporting " + thing.length + " t
hings:"); | 144 StringBuilder sb = new StringBuilder("Reporting " + thing.length + " t
hings:"); |
131 for (Thing thing : things) { | 145 for (Thing thing : things) { |
132 sb.append('\n').append(thing.id).append(' ').append(report.foo); | 146 sb.append('\n').append(thing.id).append(' ').append(report.foo); |
133 } | 147 } |
134 return sb.toString(); | 148 return sb.toString(); |
(...skipping 23 matching lines...) Expand all Loading... |
158 | 172 |
159 Instead, write this as: | 173 Instead, write this as: |
160 | 174 |
161 Log.d(TAG, "field1 = %s, field2 = %s, field3 = %s", value1, value2, value3); | 175 Log.d(TAG, "field1 = %s, field2 = %s, field3 = %s", value1, value2, value3); |
162 | 176 |
163 That doesn't seem to be much different if you count overall character counts, bu
t each independent | 177 That doesn't seem to be much different if you count overall character counts, bu
t each independent |
164 log entry also implies a small, but non-trivial header, in the kernel log buffer
. | 178 log entry also implies a small, but non-trivial header, in the kernel log buffer
. |
165 And since every byte count, you can also try something even shorter, as in: | 179 And since every byte count, you can also try something even shorter, as in: |
166 | 180 |
167 Log.d(TAG, "fields [%s,%s,%s]", value1, value2, value3); | 181 Log.d(TAG, "fields [%s,%s,%s]", value1, value2, value3); |
OLD | NEW |