-
Notifications
You must be signed in to change notification settings - Fork 0
Usage
LogBlock.class is a core class of block-logger package. It's used to create a log block.
2018-04-25 15:45:31,379 [main ] INFO [+] authenticate (id=100, user_name=SIDSSIDS)
2018-04-25 15:45:31,379 [main ] INFO checking password
2018-04-25 15:45:31,383 [main ] WARN [-] authenticate (PT0.008S): wrong password
2018-04-25 15:45:31,384 [main ] INFO [+] authenticate (id=100, user_name=SIDSSIDS)
2018-04-25 15:45:31,384 [main ] INFO checking password
2018-04-25 15:45:31,384 [main ] INFO generating sessionId
2018-04-25 15:45:31,390 [main ] INFO [-] authenticate (PT0.006S): sessionId=1df8fedc-d884-4131-a9e1-77f1c0ebc17d
- The block is started with
[+]followed by the block title with parameters:authenticate (id=100, user_name=SIDSSIDS). - Any message within the body of the block will be printed with an indent.
- The block ends with
[-]followed by the block title, duration(PT0.017S)and a result:sessionId=4a60a850-9948-4ac2-aa6d-1683ce859035. -
Duration is a time difference between block creation and
close()method invocation. - Result is a optional message, giving some information about result of the block invocation.
CLICK HERE to see the source code for the example above
public static void main(String[] args) {
Main m = new Main();
m.authenticate(100L, "SIDSSIDS", "1111111111");
m.authenticate(100L, "SIDSSIDS", "1234567890");
}
private void authenticate(Long id, String username, String password) {
try (LogBlock log = LogBlockFactory.info(Main.class, "authenticate", "id=%s, user_name=%s", id, username)) {
log.info("checking password");
if (checkPassword(password)) {
log.info("generating sessionId");
log.reportSuccess("sessionId=%s", UUID.randomUUID());
} else {
log.reportWarning("wrong password");
}
}
}
private boolean checkPassword(String password) {
return "1234567890".equals(password);
}LogBlock is created via static methods of LogBlockFactory (trace, debug, info, warn, error). You should specify a block title and some parameters (optional).
LogBlock log = LogBlockFactory.info(Main.class, "authenticate", "id=%s, user_name=%s", id, username);
/// some code
log.close();LogBlock implements java.io.Closeable interface, so it's convenient to use it in with try-with-resources:
try (LogBlock log = LogBlockFactory.info(Main.class, "authenticate", "id=%s, user_name=%s", id, username)) {
/// some code
}LogBlock implements org.slf4j.Logger interface. You can use it like a usual Logger.
try (LogBlock log = LogBlock.info(Main.class, "authenticate", "id=%s, user_name=%s", id, username)) {
log.error("unknown user: {}", username); // org.slf4j.Logger method
}NOTE: Unlike most implementations of org.slf4j.Logger, the LogBlock instance is NOT thread-safe. You should not share it between different threads.
When the block is closing, it can print some additional information, so-called report.
There are several methods to specify report:
-
reportSuccess*methods.
These methods will use the log level of the block to print report.
try (LogBlock log = LogBlockFactory.info(Main.class, "authenticate", "id=%s, user_name=%s", id, username)) {
// ...
log.reportSuccess("sessionId=%s", sessionId);
}Output:
2018-04-25 16:46:46,051 [main ] INFO [+] authenticate (id=100, user_name=SIDSSIDS)
...
2018-04-25 16:46:46,059 [main ] INFO [-] authenticate (PT0.008S): sessionId=c0ea7dc7-1103-4a56-941a-498c9ecd7599
-
reportTrace*,reportDebug*,reportInfo*,reportWarning*,reportError*methods.
These methods will use the specified log level to print report.
try (LogBlock log = LogBlockFactory.info(Main.class, "authenticate", "id=%s, user_name=%s", id, username)) {
// ...
log.reportWarning("wrong password");
}Output:
2018-04-25 16:46:46,046 [main ] INFO [+] authenticate (id=100, user_name=SIDSSIDS)
...
2018-04-25 16:46:46,050 [main ] WARN [-] authenticate (PT0.01S): wrong password
Method withException(Throwable ex) can be used to report exception. For example:
private void getFileSize(String filename) {
try (LogBlock log = LogBlockFactory.info(Main.class, "get file size", "filename=%s", filename)) {
try {
long size = Files.size(Paths.get(filename));
log.reportSuccess("size=%s", size);
} catch (IOException e) {
log.withException(e) // handle exception
.reportError("Unable to get file size");
}
}
}
// ...
getFileSize("unknown_file");Output:
2018-04-25 17:01:44,797 [main ] INFO [+] get file size (filename=unknown_file)
2018-04-25 17:01:44,811 [main ] ERROR [-] get file size (PT0.012S): Unable to get file size; Exception: java.nio.file.NoSuchFileException: unknown_file
java.nio.file.NoSuchFileException: unknown_file
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55)
at sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:144)
at sun.nio.fs.LinuxFileSystemProvider.readAttributes(LinuxFileSystemProvider.java:99)
at java.nio.file.Files.readAttributes(Files.java:1737)
at java.nio.file.Files.size(Files.java:2332)
at com.github.sidssids.test.Main.getFileSize(Main.java:16)
at com.github.sidssids.test.Main.main(Main.java:26)
You can use standard SL4J Logger within a block, even from other threads, and log messages will be indented according to the block level.
Simple example:
Logger logger = LoggerFactory.getLogger(Main.class);
try (LogBlock log = LogBlockFactory.info(Main.class, "block")) {
logger.info("inside the block");
}
logger.info("outside the block");Output:
2018-04-25 17:33:25,954 [main ] INFO [+] block
2018-04-25 17:33:25,961 [main ] INFO inside the block
2018-04-25 17:33:25,963 [main ] INFO [-] block (PT0.009S)
2018-04-25 17:33:25,963 [main ] INFO outside the block
When you start a thread within a block, the indention of the block is 'copied' to the thread, and all log messages, generated from the new thread, will be indented according to this value.
Logger logger = LoggerFactory.getLogger(Main.class);
try (LogBlock log = LogBlockFactory.info(Main.class, "block")) {
logger.info("inside the block");
Thread t = new Thread(() -> logger.info("inside thread"));
t.start();
t.join();
}
logger.info("outside the block");Output:
2018-04-25 17:45:44,299 [main ] INFO [+] block
2018-04-25 17:45:44,306 [main ] INFO inside the block
2018-04-25 17:45:44,307 [Thread-0 ] INFO inside thread
2018-04-25 17:45:44,310 [main ] INFO [-] block (PT0.01S)
2018-04-25 17:45:44,310 [main ] INFO outside the block
Do not use many LogBlock's in high-load methods. Unlike SL4J Logger, LogBlock instance is created per itch invocation. Also String.format is used in the implementation, which is quite slow compared to StringBuilder for example.