diff --git a/api/src/main/java/com/google/common/flogger/AbstractLogger.java b/api/src/main/java/com/google/common/flogger/AbstractLogger.java index 4ecaa515..bfc0fdce 100644 --- a/api/src/main/java/com/google/common/flogger/AbstractLogger.java +++ b/api/src/main/java/com/google/common/flogger/AbstractLogger.java @@ -49,14 +49,17 @@ protected AbstractLogger(LoggerBackend backend) { * Returns a fluent logging API appropriate for the specified log level. *
* If a logger implementation determines that logging is definitely disabled at this point then - * this method is expected to return a "no-op" implementation of the logging API, which will + * this method is expected to return a "no-op" implementation of that logging API, which will * result in all further calls made for the log statement to being silently ignored. *
- * Typically an implementation of this method in a concrete subclass would look like: + * A simple implementation of this method in a concrete subclass might look like: *
{@code - * return isLoggable(level) ? new Context(level): NO_OP; + * boolean isLoggable = isLoggable(level); + * boolean isForced = Platform.shouldForceLogging(getName(), level, isLoggable); + * return (isLoggable | isForced) ? new SubContext(level, isForced) : NO_OP; * }- * where {@code NO_OP} is a singleton, no-op instance of the logging API. + * where {@code NO_OP} is a singleton, no-op instance of the logging API whose methods do nothing + * and just {@code return noOp()}. */ public abstract API at(Level level); diff --git a/google/src/main/java/com/google/common/flogger/GoogleLogger.java b/google/src/main/java/com/google/common/flogger/GoogleLogger.java index 036ac6b8..9df3f9a8 100644 --- a/google/src/main/java/com/google/common/flogger/GoogleLogger.java +++ b/google/src/main/java/com/google/common/flogger/GoogleLogger.java @@ -69,8 +69,19 @@ public static GoogleLogger forInjectedClassName(String className) { super(loggerBackend); } + @SuppressWarnings("ShortCircuitBoolean") @Override public Api at(Level level) { + // Important: This code is the "hottest" code path in Flogger. It is called for all log + // statements or log level checks reached by user code. The overwhelming number of callers to + // this method will be non-loggable and return the singleton "no op" API. Profiling of server + // side applications shows that approximately 80% of the total CPU usage associated with this + // method is used for cases where logging will not occur, so any changes must be optimized for + // that case. In-particular no allocation should ever occur for "disabled" log statements. + // + // In systems where log statements are stripped from code at build time, this obviously + // dramatically affects the ratio of enabled to disabled log statements, but in those cases, + // the cost of this method is trivial compared to the work of actually logging. boolean isLoggable = isLoggable(level); boolean isForced = Platform.shouldForceLogging(getName(), level, isLoggable); return (isLoggable || isForced) ? new Context(level, isForced) : NO_OP;