OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.base; |
| 6 |
| 7 import org.chromium.base.annotations.NoSideEffects; |
| 8 |
| 9 import java.util.Locale; |
| 10 |
| 11 /** |
| 12 * Utility class for Logging. |
| 13 * |
| 14 * <p> |
| 15 * Defines logging access points for each feature. They format and forward the l
ogs to |
| 16 * {@link android.util.Log}, allowing to standardize the output, to make it easy
to identify |
| 17 * the origin of logs, and enable or disable logging in different parts of the c
ode. |
| 18 * </p> |
| 19 * <p> |
| 20 * Please make use of the formatting capability of the logging methods rather th
an doing |
| 21 * concatenations in the calling code. In the release builds of Chrome, debug an
d verbose log |
| 22 * calls will be stripped out of the binary. Concatenations and method calls how
ever will still |
| 23 * remain and be executed. If they can't be avoided, use {@link Log#isEnabled(in
t)} to guard |
| 24 * such calls. Another possibility is to annotate methods to be called with {@li
nk NoSideEffects}. |
| 25 * </p> |
| 26 * |
| 27 * Usage: |
| 28 * <pre> |
| 29 * Log.FEATURE.d("MyTag", "My %s message", awesome); |
| 30 * </pre> |
| 31 * |
| 32 * Logcat output: |
| 33 * <pre> |
| 34 * D/chromium.Feature (999): [MyTag] My awesome message |
| 35 * </pre> |
| 36 * |
| 37 * Set the log level for a given feature: |
| 38 * <pre> |
| 39 * adb shell setprop log.tag.chromium:Feature VERBOSE |
| 40 * </pre> |
| 41 * |
| 42 *<p> |
| 43 *<b>Notes:</b> |
| 44 * <ul> |
| 45 * <li>For loggers configured to log the origin of debug calls (see {@link #Log(
String, boolean)}, |
| 46 * the tag provided for debug and verbose calls will be ignored and replaced in
the log with |
| 47 * the file name and the line number.</li> |
| 48 * <li>New features or features not having a dedicated logger: please make a new
one rather |
| 49 * than using {@link #ROOT}.</li> |
| 50 * </ul> |
| 51 * </p> |
| 52 */ |
| 53 public class Log { |
| 54 private static final String BASE_TAG = "chromium"; |
| 55 |
| 56 /** |
| 57 * Maximum length for the feature tag. |
| 58 * |
| 59 * A complete tag will look like <code>chromium:FooFeature</code>. Because o
f the 23 characters |
| 60 * limit on log tags, feature tags have to be restricted to fit. |
| 61 */ |
| 62 private static final int MAX_FEATURE_TAG_LENGTH = 23 - 1 - BASE_TAG.length()
; |
| 63 |
| 64 /** |
| 65 * Logger for the "chromium" tag. |
| 66 * Note: Disabling logging for that one will not disable the others. |
| 67 */ |
| 68 public static final Log ROOT = new Log(null, true); |
| 69 |
| 70 @VisibleForTesting |
| 71 final String mTag; |
| 72 private final boolean mDebugWithStack; |
| 73 |
| 74 /** |
| 75 * Creates a new logging access point for the given tag. |
| 76 * @param featureTag The complete log tag will be displayed as "chromium.fea
tureTag". |
| 77 * If <code>null</code>, it will only be "chromium". |
| 78 * @param debugWithStack Whether to replace the secondary tag name with the
file name and line |
| 79 * number of the origin of the call for debug and verb
ose logs. |
| 80 * @throws IllegalArgumentException If <code>featureTag</code> is too long.
The complete |
| 81 * tag has to fit within 23 characters. |
| 82 */ |
| 83 protected Log(String featureTag, boolean debugWithStack) { |
| 84 mDebugWithStack = debugWithStack; |
| 85 if (featureTag == null) { |
| 86 mTag = BASE_TAG; |
| 87 return; |
| 88 } else if (featureTag.length() > MAX_FEATURE_TAG_LENGTH) { |
| 89 throw new IllegalArgumentException( |
| 90 "The feature tag can be at most " + MAX_FEATURE_TAG_LENGTH +
" characters."); |
| 91 } else { |
| 92 mTag = BASE_TAG + "." + featureTag; |
| 93 } |
| 94 } |
| 95 |
| 96 /** Returns whether this logger is currently allowed to send logs.*/ |
| 97 public boolean isEnabled(int level) { |
| 98 return android.util.Log.isLoggable(mTag, level); |
| 99 } |
| 100 |
| 101 /** Returns a formatted log message, using the supplied format and arguments
.*/ |
| 102 @VisibleForTesting |
| 103 protected String formatLog(String secondaryTag, String messageTemplate, Obje
ct... params) { |
| 104 if (params != null && params.length != 0) { |
| 105 messageTemplate = String.format(Locale.US, messageTemplate, params); |
| 106 } |
| 107 |
| 108 return "[" + secondaryTag + "] " + messageTemplate; |
| 109 } |
| 110 |
| 111 /** |
| 112 * Sends a {@link android.util.Log#VERBOSE} log message. |
| 113 * |
| 114 * For optimization purposes, only the fixed parameters versions are visible
. If you need more |
| 115 * than 7 parameters, consider building your log message using a function an
notated with |
| 116 * {@link NoSideEffects}. |
| 117 * |
| 118 * @param secondaryTag Used to identify the source of a log message. It usua
lly identifies the |
| 119 * class where the log call occurs. If the logger is con
figured to log the |
| 120 * call's origin (see {@link #Log(String, boolean)}, thi
s parameter is |
| 121 * unused and will be replaced in the log message with t
he file name and |
| 122 * the line number. |
| 123 * @param messageTemplate The message you would like logged. It is to be spe
cified as a format |
| 124 * string. |
| 125 * @param args Arguments referenced by the format specifiers in the format s
tring. |
| 126 */ |
| 127 private void verbose(String secondaryTag, String messageTemplate, Object...
args) { |
| 128 if (isEnabled(android.util.Log.VERBOSE)) { |
| 129 if (mDebugWithStack) secondaryTag = getCallOrigin(); |
| 130 android.util.Log.v(mTag, formatLog(secondaryTag, messageTemplate, ar
gs)); |
| 131 } |
| 132 } |
| 133 |
| 134 /** Sends a {@link android.util.Log#VERBOSE} log message. 0 arg version. */ |
| 135 public void v(String secondaryTag, String message) { |
| 136 verbose(secondaryTag, message); |
| 137 } |
| 138 |
| 139 /** Sends a {@link android.util.Log#VERBOSE} log message. 1 arg version. */ |
| 140 public void v(String secondaryTag, String messageTemplate, Object arg1) { |
| 141 verbose(secondaryTag, messageTemplate, arg1); |
| 142 } |
| 143 |
| 144 /** Sends a {@link android.util.Log#VERBOSE} log message. 2 args version */ |
| 145 public void v(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2) { |
| 146 verbose(secondaryTag, messageTemplate, arg1, arg2); |
| 147 } |
| 148 |
| 149 /** Sends a {@link android.util.Log#VERBOSE} log message. 3 args version */ |
| 150 public void v( |
| 151 String secondaryTag, String messageTemplate, Object arg1, Object arg
2, Object arg3) { |
| 152 verbose(secondaryTag, messageTemplate, arg1, arg2, arg3); |
| 153 } |
| 154 |
| 155 /** Sends a {@link android.util.Log#VERBOSE} log message. 4 args version */ |
| 156 public void v(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 157 Object arg3, Object arg4) { |
| 158 verbose(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4); |
| 159 } |
| 160 |
| 161 /** Sends a {@link android.util.Log#VERBOSE} log message. 5 args version */ |
| 162 public void v(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 163 Object arg3, Object arg4, Object arg5) { |
| 164 verbose(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4, arg5); |
| 165 } |
| 166 |
| 167 /** Sends a {@link android.util.Log#VERBOSE} log message. 6 args version */ |
| 168 public void v(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 169 Object arg3, Object arg4, Object arg5, Object arg6) { |
| 170 verbose(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg
6); |
| 171 } |
| 172 |
| 173 /** Sends a {@link android.util.Log#VERBOSE} log message. 7 args version */ |
| 174 public void v(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 175 Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { |
| 176 verbose(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg
6, arg7); |
| 177 } |
| 178 |
| 179 /** |
| 180 * Sends a {@link android.util.Log#DEBUG} log message. |
| 181 * |
| 182 * For optimization purposes, only the fixed parameters versions are visible
. If you need more |
| 183 * than 7 parameters, consider building your log message using a function an
notated with |
| 184 * {@link NoSideEffects}. |
| 185 * |
| 186 * @param secondaryTag Used to identify the source of a log message. It usua
lly identifies the |
| 187 * class where the log call occurs. If the logger is con
figured to log the |
| 188 * call's origin (see {@link #Log(String, boolean)}, thi
s parameter is |
| 189 * unused and will be replaced in the log message with t
he file name and |
| 190 * the line number. |
| 191 * @param messageTemplate The message you would like logged. It is to be spe
cified as a format |
| 192 * string. |
| 193 * @param args Arguments referenced by the format specifiers in the format s
tring. |
| 194 */ |
| 195 private void debug(String secondaryTag, String messageTemplate, Object... ar
gs) { |
| 196 if (isEnabled(android.util.Log.DEBUG)) { |
| 197 if (mDebugWithStack) secondaryTag = getCallOrigin(); |
| 198 android.util.Log.d(mTag, formatLog(secondaryTag, messageTemplate, ar
gs)); |
| 199 } |
| 200 } |
| 201 |
| 202 /** Sends a {@link android.util.Log#DEBUG} log message. 0 arg version. */ |
| 203 public void d(String secondaryTag, String message) { |
| 204 debug(secondaryTag, message); |
| 205 } |
| 206 |
| 207 /** Sends a {@link android.util.Log#DEBUG} log message. 1 arg version. */ |
| 208 public void d(String secondaryTag, String messageTemplate, Object arg1) { |
| 209 debug(secondaryTag, messageTemplate, arg1); |
| 210 } |
| 211 /** Sends a {@link android.util.Log#DEBUG} log message. 2 args version */ |
| 212 public void d(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2) { |
| 213 debug(secondaryTag, messageTemplate, arg1, arg2); |
| 214 } |
| 215 /** Sends a {@link android.util.Log#DEBUG} log message. 3 args version */ |
| 216 public void d( |
| 217 String secondaryTag, String messageTemplate, Object arg1, Object arg
2, Object arg3) { |
| 218 debug(secondaryTag, messageTemplate, arg1, arg2, arg3); |
| 219 } |
| 220 |
| 221 /** Sends a {@link android.util.Log#DEBUG} log message. 4 args version */ |
| 222 public void d(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 223 Object arg3, Object arg4) { |
| 224 debug(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4); |
| 225 } |
| 226 |
| 227 /** Sends a {@link android.util.Log#DEBUG} log message. 5 args version */ |
| 228 public void d(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 229 Object arg3, Object arg4, Object arg5) { |
| 230 debug(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4, arg5); |
| 231 } |
| 232 |
| 233 /** Sends a {@link android.util.Log#DEBUG} log message. 6 args version */ |
| 234 public void d(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 235 Object arg3, Object arg4, Object arg5, Object arg6) { |
| 236 debug(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6)
; |
| 237 } |
| 238 |
| 239 /** Sends a {@link android.util.Log#DEBUG} log message. 7 args version */ |
| 240 public void d(String secondaryTag, String messageTemplate, Object arg1, Obje
ct arg2, |
| 241 Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { |
| 242 debug(secondaryTag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6,
arg7); |
| 243 } |
| 244 |
| 245 /** |
| 246 * Sends an {@link android.util.Log#INFO} log message. |
| 247 * |
| 248 * @param secondaryTag Used to identify the source of a log message. It usua
lly identifies the |
| 249 * class where the log call occurs. |
| 250 * @param messageTemplate The message you would like logged. It is to be spe
cified as a format |
| 251 * string. |
| 252 * @param args Arguments referenced by the format specifiers in the format s
tring. |
| 253 */ |
| 254 public void i(String secondaryTag, String messageTemplate, Object... args) { |
| 255 if (isEnabled(android.util.Log.INFO)) { |
| 256 android.util.Log.i(mTag, formatLog(secondaryTag, messageTemplate, ar
gs)); |
| 257 } |
| 258 } |
| 259 |
| 260 /** |
| 261 * Sends a {@link android.util.Log#WARN} log message. |
| 262 * |
| 263 * @param secondaryTag Used to identify the source of a log message. It usua
lly identifies the |
| 264 * class where the log call occurs. |
| 265 * @param messageTemplate The message you would like logged. It is to be spe
cified as a format |
| 266 * string. |
| 267 * @param args Arguments referenced by the format specifiers in the format s
tring. |
| 268 */ |
| 269 public void w(String secondaryTag, String messageTemplate, Object... args) { |
| 270 if (isEnabled(android.util.Log.WARN)) { |
| 271 android.util.Log.w(mTag, formatLog(secondaryTag, messageTemplate, ar
gs)); |
| 272 } |
| 273 } |
| 274 |
| 275 /** |
| 276 * Sends an {@link android.util.Log#ERROR} log message. |
| 277 * |
| 278 * @param secondaryTag Used to identify the source of a log message. It usua
lly identifies the |
| 279 * class where the log call occurs. |
| 280 * @param messageTemplate The message you would like logged. It is to be spe
cified as a format |
| 281 * string. |
| 282 * @param args Arguments referenced by the format specifiers in the format s
tring. |
| 283 */ |
| 284 public void e(String secondaryTag, String messageTemplate, Object... args) { |
| 285 if (isEnabled(android.util.Log.ERROR)) { |
| 286 android.util.Log.e(mTag, formatLog(secondaryTag, messageTemplate, ar
gs)); |
| 287 } |
| 288 } |
| 289 |
| 290 /** Returns a string form of the origin of the log call, to be used as secon
dary tag.*/ |
| 291 private String getCallOrigin() { |
| 292 StackTraceElement[] st = Thread.currentThread().getStackTrace(); |
| 293 |
| 294 // The call stack should look like: |
| 295 // n [a variable number of calls depending on the vm used] |
| 296 // +0 getCallOrigin() |
| 297 // +1 privateLogFunction: verbose or debug |
| 298 // +2 logFunction: v or d |
| 299 // +3 caller |
| 300 |
| 301 int callerStackIndex; |
| 302 String logClassName = Log.class.getName(); |
| 303 for (callerStackIndex = 0; callerStackIndex < st.length; callerStackInde
x++) { |
| 304 if (st[callerStackIndex].getClassName().equals(logClassName)) { |
| 305 callerStackIndex += 3; |
| 306 break; |
| 307 } |
| 308 } |
| 309 |
| 310 return st[callerStackIndex].getFileName() + ":" + st[callerStackIndex].g
etLineNumber(); |
| 311 } |
| 312 } |
OLD | NEW |