Last active
June 16, 2017 21:30
-
-
Save davideas/e32911d770084490b086841c3426500a to your computer and use it in GitHub Desktop.
Log class that simplifies the use of android.util.Log
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2017 Davide Steduto | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package eu.davidea.flexibleadapter.utils; | |
import android.support.annotation.IntDef; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import static eu.davidea.flexibleadapter.utils.Log.Level.DEBUG; | |
import static eu.davidea.flexibleadapter.utils.Log.Level.ERROR; | |
import static eu.davidea.flexibleadapter.utils.Log.Level.INFO; | |
import static eu.davidea.flexibleadapter.utils.Log.Level.SUPPRESS; | |
import static eu.davidea.flexibleadapter.utils.Log.Level.VERBOSE; | |
import static eu.davidea.flexibleadapter.utils.Log.Level.WARN; | |
/** | |
* Utility class that simplifies the use of {@link android.util.Log} by improving the call | |
* to all log methods by supplying arguments as parameters instead of creating a string. This | |
* avoids useless memory allocations when not requested: the StringBuilder itself, the buffer | |
* and the String object. The new methods check in advance if the level is enabled and only | |
* after creates the string message with arguments. | |
* <p>Others features are:</p> | |
* <ul> | |
* <li>Automatic TAG corresponding to the caller class name.</li> | |
* <li>Runtime log level without the need of props file (useful for libraries).</li> | |
* <li>Method name with line number.</li> | |
* </ul> | |
* <p>Use {@link Level#SUPPRESS} to disable all logs. For instance:</p> | |
* <pre> | |
* if (BuildConfig.DEBUG) { | |
* Log.setLevel(Level.INFO); | |
* } else { | |
* Log.setLevel(Level.SUPPRESS); | |
* } | |
* </pre> | |
* | |
* @author Davide Steduto | |
* @since 02/06/2017 | |
*/ | |
public class Log { | |
private static final String SOURCE_FILE = "SourceFile"; | |
private static int LEVEL = SUPPRESS; | |
private static boolean withMethodName; | |
private static boolean withLineNumber; | |
private Log() { | |
} | |
/** | |
* Annotation interface for log level: | |
* {@link #VERBOSE}, {@link #DEBUG}, {@link #INFO}, | |
* {@link #WARN}, {@link #ERROR}, {@link #SUPPRESS} | |
*/ | |
@IntDef({VERBOSE, DEBUG, INFO, WARN, ERROR, SUPPRESS}) | |
@Retention(RetentionPolicy.SOURCE) | |
public @interface Level { | |
int VERBOSE = android.util.Log.VERBOSE; | |
int DEBUG = android.util.Log.DEBUG; | |
int INFO = android.util.Log.INFO; | |
int WARN = android.util.Log.WARN; | |
int ERROR = android.util.Log.ERROR; | |
int SUPPRESS = 10; | |
} | |
public static void setLevel(@Level int level) { | |
LEVEL = level; | |
} | |
/** | |
* Allows to log method name and line number from where the log is called. | |
* <p>- With method name: {@code [method] msg}. | |
* <br>- With line number: {@code [method:line] msg}.</p> | |
* <b>Note:</b> Line number needs method name enabled. | |
* | |
* @param method true to print method name at the beginning of the message, false otherwise | |
* @param line true to print line number after the method name, false otherwise | |
*/ | |
public static void logMethodName(boolean method, boolean line) { | |
withMethodName = method; | |
withLineNumber = line; | |
} | |
public static boolean isVerboseEnabled() { | |
return LEVEL <= VERBOSE; | |
} | |
public static boolean isDebugEnabled() { | |
return LEVEL <= DEBUG; | |
} | |
public static boolean isInfoEnabled() { | |
return LEVEL <= INFO; | |
} | |
public static boolean isWarnEnabled() { | |
return LEVEL <= WARN; | |
} | |
public static boolean isErrorEnabled() { | |
return LEVEL <= ERROR; | |
} | |
/** | |
* Sends a {@link Level#VERBOSE} log message. | |
* | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void v(String msg, Object... args) { | |
if (isVerboseEnabled()) { | |
android.util.Log.v(getTag(), formatMessage(msg, args)); | |
} | |
} | |
/** | |
* Sends a {@link Level#DEBUG} log message. | |
* | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void d(String msg, Object... args) { | |
if (isDebugEnabled()) { | |
android.util.Log.d(getTag(), formatMessage(msg, args)); | |
} | |
} | |
/** | |
* Sends an {@link Level#INFO} log message. | |
* | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void i(String msg, Object... args) { | |
if (isInfoEnabled()) { | |
android.util.Log.i(getTag(), formatMessage(msg, args)); | |
} | |
} | |
/** | |
* As {@link #i(String, Object...)} but with custom tag for one call only. | |
* | |
* @param tag custom tag, used to identify the source of a log message | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void iTag(String tag, String msg, Object... args) { | |
if (isInfoEnabled()) { | |
android.util.Log.i(tag, formatMessage(msg, args)); | |
} | |
} | |
/** | |
* Sends a {@link Level#WARN} log message. | |
* | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void w(String msg, Object... args) { | |
if (isWarnEnabled()) { | |
android.util.Log.w(getTag(), formatMessage(msg, args)); | |
} | |
} | |
/** | |
* Sends a {@link Level#WARN} log message with the Exception at the end of the message. | |
* | |
* @param t The exception to log | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void w(Throwable t, String msg, Object... args) { | |
if (isWarnEnabled()) { | |
android.util.Log.w(getTag(), formatMessage(msg, args), t); | |
} | |
} | |
/** | |
* Sends an {@link Level#ERROR} log message. | |
* | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void e(String msg, Object... args) { | |
if (isErrorEnabled()) { | |
android.util.Log.e(getTag(), formatMessage(msg, args)); | |
} | |
} | |
/** | |
* Sends an {@link Level#ERROR} log message with the Exception at the end of the message. | |
* | |
* @param t The exception to log | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void e(Throwable t, String msg, Object... args) { | |
if (isErrorEnabled()) { | |
android.util.Log.e(getTag(), formatMessage(msg, args), t); | |
} | |
} | |
/** | |
* What a Terrible Failure: Report a condition that should never happen. | |
* | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void wtf(String msg, Object... args) { | |
if (isErrorEnabled()) { | |
android.util.Log.wtf(getTag(), formatMessage(msg, args)); | |
} | |
} | |
/** | |
* What a Terrible Failure: Report a condition that should never happen with the Exception | |
* at the end of the message. | |
* | |
* @param t The exception to log | |
* @param msg the message you would like logged | |
* @param args the extra arguments for the message | |
*/ | |
public static void wtf(Throwable t, String msg, Object... args) { | |
if (isErrorEnabled()) { | |
android.util.Log.wtf(getTag(), formatMessage(msg, args), t); | |
} | |
} | |
private static String getTag() { | |
StackTraceElement traceElement = new Throwable().getStackTrace()[2]; | |
String fileName = traceElement.getFileName(); | |
if (fileName == null) return SOURCE_FILE; | |
return fileName.split("[.]")[0]; | |
} | |
private static String formatMessage(String msg, Object... args) { | |
// In order to have the "null" values logged we need to pass args when null to the formatter | |
// (This can still break depending on conversion of the formatter, see String.format) | |
// else if there is no args, we return the message as-is, otherwise we pass args to formatting normally. | |
return createLog(args != null && args.length == 0 ? msg : String.format(msg, args)); | |
} | |
private static String createLog(String log) { | |
if (withMethodName) { | |
StackTraceElement traceElement = new Throwable().getStackTrace()[3]; | |
if (withLineNumber) { | |
return String.format("[%s:%s] %s", traceElement.getMethodName(), traceElement.getLineNumber(), log); | |
} else { | |
return String.format("[%s] %s", traceElement.getMethodName(), log); | |
} | |
} | |
return log; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment