Logging in Squirrel Our first program will demonstrate logging in Java. Here’s the full source code with explanations:
import java.util.logging.* ;
import java.io.* ;
public class LoggingExample {
public static void main ( String [] args ) throws IOException {
// Simply invoking methods like info() from the Logger class uses the
// standard logger, which is already pre-configured for reasonable
// logging output to the console.
Logger . getGlobal (). info ( "standard logger" );
// Loggers can be configured with handlers and formatters to set
// their output format. We can change its format to emit time with
// millisecond accuracy, for example.
Logger logger = Logger . getLogger ( "MyLogger" );
ConsoleHandler handler = new ConsoleHandler ();
handler . setFormatter ( new SimpleFormatter () {
private static final String format = "[%1$tF %1$tT.%1$tL] %2$s %3$s%n" ;
@Override
public synchronized String format ( LogRecord lr ) {
return String . format ( format ,
lr . getMillis (),
lr . getLevel (). getLocalizedName (),
lr . getMessage ()
);
}
});
logger . setUseParentHandlers ( false );
logger . addHandler ( handler );
logger . info ( "with milliseconds" );
// It also supports emitting the class name and
// line from which the log method is called.
logger . logp ( Level . INFO , "LoggingExample" , "main" , "with class/method" );
// It may be useful to create a custom logger and
// pass it around. When creating a new logger, we
// can set a name to distinguish its output
// from other loggers.
Logger mylog = Logger . getLogger ( "MyCustomLogger" );
mylog . info ( "from mylog" );
// We can set the level on existing loggers
mylog . setLevel ( Level . FINE );
mylog . fine ( "fine message from mylog" );
// Loggers can have custom output targets;
// any OutputStream works.
ByteArrayOutputStream buf = new ByteArrayOutputStream ();
Handler bufHandler = new StreamHandler ( buf , new SimpleFormatter ());
Logger buflog = Logger . getLogger ( "BufferLogger" );
buflog . setUseParentHandlers ( false );
buflog . addHandler ( bufHandler );
// This call writes the log output into buf.
buflog . info ( "hello" );
bufHandler . flush ();
// This will actually show it on standard output.
System . out . print ( "from buflog:" + buf . toString ());
// For structured logging, we can use a third-party library like SLF4J
// with Logback. Here's a basic example using java.util.logging:
Logger structLog = Logger . getLogger ( "StructuredLogger" );
structLog . info ( "hi there" );
structLog . log ( Level . INFO , "hello again" , new Object [] { "key" , "val" , "age" , 25 });
}
}
To run the program, compile and execute it:
$ javac LoggingExample.java
$ java LoggingExample
Sample output; the date and time emitted will depend on when the example ran:
Aug 22, 2023 10:45:16 AM LoggingExample main
INFO: standard logger
[2023-08-22 10:45:16.904] INFO with milliseconds
[2023-08-22 10:45:16.905] INFO with class/method
Aug 22, 2023 10:45:16 AM LoggingExample main
INFO: from mylog
Aug 22, 2023 10:45:16 AM LoggingExample main
FINE: fine message from mylog
from buflog:Aug 22, 2023 10:45:16 AM BufferLogger info
INFO: hello
Aug 22, 2023 10:45:16 AM LoggingExample main
INFO: hi there
Aug 22, 2023 10:45:16 AM LoggingExample main
INFO: hello again
Note that Java’s built-in logging framework doesn’t have native support for structured logging like Go’s slog
. For more advanced logging features, including structured logging, consider using third-party libraries like SLF4J with Logback or Log4j2.