src/share/classes/java/util/logging/Logger.java

Print this page
rev 6281 : 8005263: Logging APIs takes a Supplier<String> for message

@@ -28,10 +28,12 @@
 
 import java.util.*;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.security.*;
 import java.lang.ref.WeakReference;
+import java.util.function.Block;
+import java.util.function.Supplier;
 
 /**
  * A Logger object is used to log messages for a specific
  * system or application component.  Loggers are normally named,
  * using a hierarchical dot-separated namespace.  Logger names

@@ -94,10 +96,16 @@
  * Otherwise the original msg string is used.  Typically, formatters use
  * java.text.MessageFormat style formatting to format parameters, so
  * for example a format string "{0} {1}" would format two parameters
  * as strings.
  * <p>
+ * Since 1.8, a set of methods alternatively take a "msgSupplier" instead of
+ * a "msg" argument.  This version takes a {@link Supplier}{@code
+ * <String>} function which is invoked to construct desired log message
+ * only when the message actually to be logged after checking the effective
+ * log level thus eliminate unnecessary message construction.
+ * <p>
  * When mapping ResourceBundle names to ResourceBundles, the Logger
  * will first try to use the Thread's ContextClassLoader.  If that
  * is null it will try the SystemClassLoader instead.  As a temporary
  * transition feature in the initial implementation, if the Logger is
  * unable to locate a ResourceBundle from the ContextClassLoader or

@@ -541,10 +549,26 @@
             lr.setResourceBundle(findResourceBundle(ebname));
         }
         log(lr);
     }
 
+    // private support method for logging.
+    // message and LogRecord are only constucted when it really need to
+    // be logged
+    private void doLog(Level level, Supplier<String> msgSupplier,
+                       Block<LogRecord> staging) {
+        if (level.intValue() < levelValue || levelValue == offValue) {
+            return;
+        }
+        LogRecord lr = new LogRecord(level, msgSupplier.get());
+        if (staging != null ) {
+            staging.accept(lr);
+        }
+        // Set logger name and resource bundle
+        doLog(lr);
+    }
+
 
     //================================================================
     // Start of convenience methods WITHOUT className and methodName
     //================================================================
 

@@ -565,10 +589,27 @@
         LogRecord lr = new LogRecord(level, msg);
         doLog(lr);
     }
 
     /**
+     * Log a message, which is only to be constructed if the logging level
+     * is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the given message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   level   One of the message level identifiers, e.g., SEVERE
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     */
+    public void log(Level level, Supplier<String> msgSupplier) {
+        doLog(level, msgSupplier, null);
+    }
+
+    /**
      * Log a message, with one object parameter.
      * <p>
      * If the logger is currently enabled for the given message
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.

@@ -630,10 +671,33 @@
         LogRecord lr = new LogRecord(level, msg);
         lr.setThrown(thrown);
         doLog(lr);
     }
 
+    /**
+     * Log a in-time constructed message, with associated Throwable information.
+     * <p>
+     * If the logger is currently enabled for the given message level then the
+     * message is constructed by invoking the provided supplier function. The
+     * message and the given {@link Throwable} are then stored in a {@link
+     * LogRecord} which is forwarded to all registered output handlers.
+     * <p>
+     * Note that the thrown argument is stored in the LogRecord thrown
+     * property, rather than the LogRecord parameters property.  Thus is it
+     * processed specially by output Formatters and is not treated
+     * as a formatting parameter to the LogRecord message property.
+     * <p>
+     * @param   level   One of the message level identifiers, e.g., SEVERE
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @param   thrown  Throwable associated with log message.
+     * @since   1.8
+     */
+    public void logEx(Level level, Supplier<String> msgSupplier, Throwable thrown) {
+        doLog(level, msgSupplier, lr -> lr.setThrown(thrown));
+    }
+
     //================================================================
     // Start of convenience methods WITH className and methodName
     //================================================================
 
     /**

@@ -658,10 +722,34 @@
         lr.setSourceMethodName(sourceMethod);
         doLog(lr);
     }
 
     /**
+     * Log a in-time constructed message, specifying source class and method,
+     * with no arguments.
+     * <p>
+     * If the logger is currently enabled for the given message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   level   One of the message level identifiers, e.g., SEVERE
+     * @param   sourceClass    name of class that issued the logging request
+     * @param   sourceMethod   name of method that issued the logging request
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void logp(Level level, String sourceClass, String sourceMethod,
+                     Supplier<String> msgSupplier) {
+        doLog(level, msgSupplier, lr -> {
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+        });
+    }
+
+    /**
      * Log a message, specifying source class and method,
      * with a single object parameter to the log message.
      * <p>
      * If the logger is currently enabled for the given message
      * level then a corresponding LogRecord is created and forwarded

@@ -741,10 +829,41 @@
         lr.setSourceMethodName(sourceMethod);
         lr.setThrown(thrown);
         doLog(lr);
     }
 
+    /**
+     * Log a in-time constructed message, specifying source class and method,
+     * with associated Throwable information.
+     * <p>
+     * If the logger is currently enabled for the given message level then the
+     * message is constructed by invoking the provided supplier function. The
+     * message and the given {@link Throwable} are then stored in a {@link
+     * LogRecord} which is forwarded to all registered output handlers.
+     * <p>
+     * Note that the thrown argument is stored in the LogRecord thrown
+     * property, rather than the LogRecord parameters property.  Thus is it
+     * processed specially by output Formatters and is not treated
+     * as a formatting parameter to the LogRecord message property.
+     * <p>
+     * @param   level   One of the message level identifiers, e.g., SEVERE
+     * @param   sourceClass    name of class that issued the logging request
+     * @param   sourceMethod   name of method that issued the logging request
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @param   thrown  Throwable associated with log message.
+     * @since   1.8
+     */
+    public void logpEx(Level level, String sourceClass, String sourceMethod,
+                       Supplier<String> msgSupplier, Throwable thrown) {
+        doLog(level, msgSupplier, lr -> {
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            lr.setThrown(thrown);
+        });
+    }
+
 
     //=========================================================================
     // Start of convenience methods WITH className, methodName and bundle name.
     //=========================================================================
 

@@ -1147,10 +1266,134 @@
             return;
         }
         log(Level.FINEST, msg);
     }
 
+    //=======================================================================
+    // Start of simple convenience methods using level names as method names
+    // and use Supplier<String>
+    //=======================================================================
+
+    /**
+     * Log a SEVERE message, which is only to be constructed if the logging
+     * level is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the SEVERE message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void severe(Supplier<String> msgSupplier) {
+        log(Level.SEVERE, msgSupplier);
+    }
+
+    /**
+     * Log a WARNING message, which is only to be constructed if the logging
+     * level is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the WARNING message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void warning(Supplier<String> msgSupplier) {
+        log(Level.WARNING, msgSupplier);
+    }
+
+    /**
+     * Log a INFO message, which is only to be constructed if the logging
+     * level is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the INFO message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void info(Supplier<String> msgSupplier) {
+        log(Level.INFO, msgSupplier);
+    }
+
+    /**
+     * Log a CONFIG message, which is only to be constructed if the logging
+     * level is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the CONFIG message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void config(Supplier<String> msgSupplier) {
+        log(Level.CONFIG, msgSupplier);
+    }
+
+    /**
+     * Log a FINE message, which is only to be constructed if the logging
+     * level is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the FINE message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void fine(Supplier<String> msgSupplier) {
+        log(Level.FINE, msgSupplier);
+    }
+
+    /**
+     * Log a FINER message, which is only to be constructed if the logging
+     * level is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the FINER message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void finer(Supplier<String> msgSupplier) {
+        log(Level.FINER, msgSupplier);
+    }
+
+    /**
+     * Log a FINEST message, which is only to be constructed if the logging
+     * level is such that the message will actually be logged.
+     * <p>
+     * If the logger is currently enabled for the FINEST message
+     * level then the message is constructed by invoking the provided
+     * supplier function and forwarded to all the registered output
+     * Handler objects.
+     * <p>
+     * @param   msgSupplier   A function, which when called, produces the
+     *                        desired log message
+     * @since   1.8
+     */
+    public void finest(Supplier<String> msgSupplier) {
+        log(Level.FINEST, msgSupplier);
+    }
+
     //================================================================
     // End of convenience methods
     //================================================================
 
     /**