Getting started with Java LanguageInheritanceStreamsExceptions and exception handlingCollectionsLambda ExpressionsGenericsFile I/OArraysInterfacesMapsStringsInputStreams and OutputStreamsDefault MethodsClasses and ObjectsBasic Control StructuresConcurrent Programming (Threads)Console I/OSingletonsVisibility (controlling access to members of a class)Regular ExpressionsAutoboxingDocumenting Java CodeExecutor, ExecutorService and Thread poolsObject Class Methods and ConstructorJAXBPrimitive Data TypesNetworkingOptionalEnumsHttpURLConnectionAnnotationsAudioDate ClassCalendar and its SubclassesNashorn JavaScript engineJava Native InterfaceRemote Method Invocation (RMI)Iterator and IterableOperatorsAssertingScannerProperties ClassPreferencesReflection APIConstructorsByteBufferSerializationJSON in JavaRandom Number GenerationRecursionPolymorphismStringBuilderReference Data TypesBit ManipulationJava AgentsEncapsulationType ConversionBigIntegerBigDecimalRSA EncryptionVarargs (Variable Argument)ThreadLocalLogging (java.util.logging)Using the static keywordDisassembling and DecompilingResources (on classpath)log4j / log4j2JVM FlagsOracle Official Code StandardCharacter encodingJava Memory ManagementImmutable ObjectsObject CloningAlternative CollectionsListsBufferedWriterLocalTimeSetsComparable and ComparatorJVM Tool InterfaceNested and Inner ClassesApache Commons LangGetters and SettersThe ClasspathBytecode ModificationXML Parsing using the JAXP APIsReference TypesLocalization and InternationalizationJAX-WSXML XPath EvaluationJava Performance TuningParallel programming with Fork/Join frameworkCommon Java PitfallsNon-Access ModifiersJava Compiler - 'javac'XJCProcessInstalling Java (Standard Edition)Command line Argument ProcessingDates and Time (java.time.*)Fluent InterfaceXOM - XML Object ModelJust in Time (JIT) compilerFTP (File Transfer Protocol)Java Native AccessModulesJava Pitfalls - Exception usageJava Pitfalls - Language syntaxServiceLoaderClassloadersObject ReferencesJava Pitfalls - Performance IssuesCreating Images ProgrammaticallyAppletsNIO - NetworkingNew File I/OSecure objectsJava Pitfalls - Threads and ConcurrencySplitting a string into fixed length partsJava Pitfalls - Nulls and NullPointerExceptionSecurityManagerJNDIsuper keywordThe java.util.Objects ClassThe Java Command - 'java' and 'javaw'Atomic TypesJava Floating Point OperationsConverting to and from Stringssun.misc.UnsafeJava Memory ModelJava deploymentJava plugin system implementationsQueues and DequesRuntime CommandsNumberFormatSecurity & CryptographyJava Virtual Machine (JVM)Unit TestingJavaBeanExpressionsLiteralsJava SE 8 FeaturesJava SE 7 FeaturesPackagesCurrency and MoneyConcurrent CollectionsUsing ThreadPoolExecutor in MultiThreaded applications.Java Editions, Versions, Releases and DistributionsDynamic Method DispatchJMXSecurity & CryptographyGenerating Java CodeJShellBenchmarksCollection Factory MethodsMulti-Release JAR FilesStack-Walking APITreeMap and TreeSetSocketsJava SocketsUsing Other Scripting Languages in JavaFunctional InterfacesList vs SET2D Graphics in JavaClass - Java ReflectionDequeue InterfaceEnum MapEnumSet classLocal Inner ClassJava Print ServiceImmutable ClassString TokenizerFileUpload to AWSAppDynamics and TIBCO BusinessWorks Instrumentation for Easy IntegrationReaders and WritersHashtableEnum starting with numberSortedMapWeakHashMapLinkedHashMapStringBufferChoosing CollectionsC++ ComparisonCompletableFuture

Logging (java.util.logging)

Other topics

Using the default logger

This example shows how to use the default logging api.

import java.util.logging.Level;
import java.util.logging.Logger;

public class MyClass {
    
    // retrieve the logger for the current class
    private static final Logger LOG = Logger.getLogger(MyClass.class.getName());
    
    public void foo() {
        LOG.info("A log message");
        LOG.log(Level.INFO, "Another log message");

        LOG.fine("A fine message");
    
        // logging an exception
        try {
            // code might throw an exception
        } catch (SomeException ex) {
            // log a warning printing "Something went wrong"
            // together with the exception message and stacktrace
            LOG.log(Level.WARNING, "Something went wrong", ex);
        }

        String s = "Hello World!";

        // logging an object
        LOG.log(Level.FINER, "String s: {0}", s);

        // logging several objects
        LOG.log(Level.FINEST, "String s: {0} has length {1}", new Object[]{s, s.length()});
    }

}

Logging levels

Java Logging Api has 7 levels. The levels in descending order are:

  • SEVERE (highest value)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (lowest value)

The default level is INFO (but this depends on the system and used a virtual machine).

Note: There are also levels OFF (can be used to turn logging off) and ALL (the oposite of OFF).

Code example for this:

import java.util.logging.Logger;

public class Levels {
    private static final Logger logger = Logger.getLogger(Levels.class.getName());

    public static void main(String[] args) {

        logger.severe("Message logged by SEVERE");
        logger.warning("Message logged by WARNING");
        logger.info("Message logged by INFO");
        logger.config("Message logged by CONFIG");
        logger.fine("Message logged by FINE");
        logger.finer("Message logged by FINER");
        logger.finest("Message logged by FINEST");

        // All of above methods are really just shortcut for
        // public void log(Level level, String msg):
        logger.log(Level.FINEST, "Message logged by FINEST");
    }
}

By default running this class will output only messages with level higher then CONFIG:

Jul 23, 2016 9:16:11 PM LevelsExample main
SEVERE: Message logged by SEVERE
Jul 23, 2016 9:16:11 PM LevelsExample main
WARNING: Message logged by WARNING
Jul 23, 2016 9:16:11 PM LevelsExample main
INFO: Message logged by INFO

Logging complex messages (efficiently)

Let's look at a sample of logging which you can see in many programs:

public class LoggingComplex {
    
    private static final Logger logger = 
        Logger.getLogger(LoggingComplex.class.getName());

    private int total = 50, orders = 20;
    private String username = "Bob";

    public void takeOrder() {
        // (...) making some stuff
        logger.fine(String.format("User %s ordered %d things (%d in total)", 
                                  username, orders, total));
        // (...) some other stuff
    }

    // some other methods and calculations
}

The above example looks perfectly fine, but many programmers forgets that Java VM is stack machine. This means that all method's parameters are calculated before executing the method.

This fact is crucial for logging in Java, especially for logging something in low levels like FINE, FINER, FINEST which are disabled by default. Let's look at Java bytecode for the takeOrder() method.

The result for javap -c LoggingComplex.class is something like this:

public void takeOrder();
    Code:
       0: getstatic     #27 // Field logger:Ljava/util/logging/Logger;
       3: ldc           #45 // String User %s ordered %d things (%d in total)
       5: iconst_3
       6: anewarray     #3  // class java/lang/Object
       9: dup
      10: iconst_0
      11: aload_0
      12: getfield      #40 // Field username:Ljava/lang/String;
      15: aastore
      16: dup
      17: iconst_1
      18: aload_0
      19: getfield      #36 // Field orders:I
      22: invokestatic  #47 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      25: aastore
      26: dup
      27: iconst_2
      28: aload_0
      29: getfield      #34 // Field total:I
      32: invokestatic  #47 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      35: aastore
      36: invokestatic  #53 // Method java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
      39: invokevirtual #59 // Method java/util/logging/Logger.fine:(Ljava/lang/String;)V
      42: return

Line 39 runs the actual logging. All of the previous work (loading variables, creating new objects, concatenating Strings in format method) can be for nothing if logging level is set higher then FINE (and by default it is). Such logging can be very inefficient, consuming unnecessary memory and processor resources.

That's why you should ask if the level you want to use is enabled.

The right way should be:

public void takeOrder() {
    // making some stuff
    if (logger.isLoggable(Level.FINE)) {
        // no action taken when there's no need for it
        logger.fine(String.format("User %s ordered %d things (%d in total)",
                                  username, orders, total));
    }
    // some other stuff
}

Since Java 8:

The Logger class has additional methods that take a Supplier<String> as parameter, which can simply be provided by a lambda:

public void takeOrder() {
    // making some stuff
    logger.fine(() -> String.format("User %s ordered %d things (%d in total)",
            username, orders, total));
    // some other stuff
}

The Suppliers get()method - in this case the lambda - is only called when the corresponding level is enabled and so the ifconstruction is not needed anymore.

Contributors

Topic Id: 2010

Example Ids: 6579,11357,13648

This site is not affiliated with any of the contributors.