Welcome to pformat ...(small but good!) |
![]() |
pformat stands for printf-format and is Java library that comes with a small but powerful formatter for the java.util.logging framework.
Standard formatter of java.util.logging framework are fixed in their behaviour and do not offer much control to user without any programming. The formatter provided by this library uses the printf formatting style of the Java API in order to format log records.
To use the printf-formatter download the archive from here and extract it. Simply add the formatter to the handlers in the logging properties file after that. An example is given below
handlers=java.util.logging.FileHandler |
In this example only one file handler is used, that will create 5 log files at maximum. The file handler will use the PrintfFormatter writing the log records according to the format string given. The resulting output might look like
SEVERE|2011.06.13 21:39:47.973|1307993987973| 10|Severe message |
The library must be added to the classpath of a Java
application to make use of its printf-style formatter.
For a standalone Java application simply add pformat.jar file to the
classpath, create or edit a logging properties file and start
the application with the logging config file system property.
For example
Windows syntax: | java -Djava-util.logging.config.file=logging.properties -cp pformat.jar;<list of your jars> MyMainClass |
Unix syntax: | java -Djava-util.logging.config.file=logging.properties -cp pformat.jar:<list of your jars> MyMainClass |
where <list of your jars> is a list of your application
jar files.
´For Tomcat java.util.logging
is usually the standard logging implementation. In order to use
the formatter edit the logging properties under
$TOMCAT_HOME/conf/logging.properties
Often ConsoleHandler and JuliFileHandler are used, to which the
PrintfFormatter can be applied (note the bold lines):
handlers = 1catalina.org.apache.juli.FileHandler,
2localhost.org.apache.juli.FileHandler,
3manager.org.apache.juli.FileHandler,
4host-manager.org.apache.juli.FileHandler,
java.util.logging.ConsoleHandler .handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler ############################################################ # Handler specific properties. # Describes specific configuration info for Handlers. ############################################################ 1catalina.org.apache.juli.FileHandler.level = FINE 1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs 1catalina.org.apache.juli.FileHandler.prefix = catalina. 1catalina.org.apache.juli.FileHandler.formatter=de.softquadrat.logging.PrintfFormatter 1catalina.de.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te %2$tH:%2$tM:%2$tS.%2$tL|%3$6d|%10$s 2localhost.org.apache.juli.FileHandler.level = FINE 2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs 2localhost.org.apache.juli.FileHandler.prefix = localhost. 2localhost.org.apache.juli.FileHandler.formatter=de.softquadrat.logging.PrintfFormatter 2localhost.de.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te %2$tH:%2$tM:%2$tS.%2$tL|%3$6d|%10$s 3manager.org.apache.juli.FileHandler.level = FINE 3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs 3manager.org.apache.juli.FileHandler.prefix = manager. 3manager.org.apache.juli.FileHandler.formatter=de.softquadrat.logging.PrintfFormatter 3manager.de.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te %2$tH:%2$tM:%2$tS.%2$tL|%3$6d|%10$s 4host-manager.org.apache.juli.FileHandler.level = FINE 4host-manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs 4host-manager.org.apache.juli.FileHandler.prefix = host-manager. 4host-manager.org.apache.juli.FileHandler.formatter=de.softquadrat.logging.PrintfFormatter 4host-managerde.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te %2$tH:%2$tM:%2$tS.%2$tL|%3$6d|%10$s java.util.logging.ConsoleHandler.level = FINE java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.formatter=de.softquadrat.logging.PrintfFormatter de.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te %2$tH:%2$tM:%2$tS.%2$tL|%3$6d|%10$s |
To add the library to the classpath create an environment
file and add a corresponding entry with the classpath
Windows | Unix |
$TOMCAT_HOME/bin/setenv.bat set CLASSPATH=pformat.jar |
$TOMCAT_HOME/bin/setenv.sh CLASSPATH=pformat.jar |
If there is already an environment file with a classpath entry
extend this and add pformat.jar.
Restart Tomcat after that and the formatter should come into
place.
The fine tuning of the format and the options of the printf
formatter are given in this section. Find below explanations and
examples for the formatter properties
The log message format is given by the property de.softquadrat.logging.PrintfFormatter.format.
It defines the string conversion of the log entries using java
formatter string syntax, for details see here.
Easily spoken formatting is done for each log record and its
parameter as follows:
A format instruction consists of a starting '%' followed by a parameter number and a format string (for instance %1$7s advices the formatter to take parameter 1 (1$) and formats it as a string with 7 characters (7s)). Find below a list of available log record parameters, their index number and their datatypes
Some examples of formats with their corresponding output are
given below:
Format: de.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te
%2$tH:%2$tM:%2$tS.%2$tL|%3$6d|%10$s
Description: Small
format with level, time stamp, thread id, thread name and log
message.
Output:
SEVERE|2011.06.14 12:33:00.607| 10|Severe message |
Format: de.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te
%2$tH:%2$tM:%2$tS.%2$tL|%2$13d|%3$6d|%4$s#%5$s|%6$s|%7$d|%8$s|%9$s|%10$s
Description: Full format
with all possible parameters.
Output:
SEVERE|2011.06.14 14:35:21.728|1308054921728| 10|de.softquadrat.logging.Test#test|de.softquadrat.logging.Test|0|null|null|Severe message |
If no format is provided in the logging properties file the default given below is used
de.softquadrat.logging.PrintfFormatter.format=%1$7.7s|%2$tY.%2$tm.%2$te %2$tH:%2$tM:%2$tS.%2$tL|%3$6d|%10$s
The boolean property
de.softquadrat.logging.PrintfFormatter.stripLineBreaks
if set to true will escape all line terminators in the log
message thus keeping the log message in one line (defaults to
false). Example
de.softquadrat.logging.PrintfFormatter.stripLineBreaks=false
INFO|2011.06.14 14:50:14.885| 10|Long message |
de.softquadrat.logging.PrintfFormatter.stripLineBreaks=true
INFO|2011.06.14 14:55:45.661| 10|Long message\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt\nut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi\nut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore\neu fugiat nulla pariatur. |
Note the '\n' in the line instead of the line terminator.
The boolean property
de.softquadrat.logging.PrintfFormatter.appendStackTrace
is used to control logging of exception stacktraces. If set to
'true' full stacktraces
will be appended to the log, if set to 'false' they will be suppressed. The default
value of this property is 'true'
thus logging all stacktraces.
There are three properties available to control searching and
replacing using regular expressions in order to change the
resulting format of the log messages:
Several regular expressions can be defined with numbering
starting from 1 (replace # by the number) like
Evaluation of regular expressions will contine until the first
missing pattern is encountered.
The property regexpPattern.#
can be used to define a regular search expression. For every
match of the pattern against the log message a replacement will
be done using the string defined by property regexpReplacement.#. The
search process can be fine controlled using the (optional)
property regexpFlags.#.
The regular expression pattern syntax can be found in the Java API here. The replacement string can use groups from the pattern by group numbers or group names. Have a look to the section called "Groups and capturing" at the same location in the Java API.
The flags regexpFlags
allows control over the regular expression process. These flags
and there values can also be found in the Java
API as well.
Examples:
1. Remove leading zeros from all numbers
Example: result1=012345, result2=00009747.033, result3=000.0 -> result1=12345, result2=9747.033, result3=0.0
2. Anonymize all urls in log messages starting with "http://www" and ending with a space and replace them by 'http://www.*':
Example: The url http://www.softquadrat.de/datasqill is cool. -> The url http://www.* is cool.
3. Replace all '.' by ',' and all '$' by '€' (text replacement
without regular expression syntax in literal mode)
Example: 3124.24 $ -> 3124,24 €
The library is distributed as public domain, feel free to use it, modify it, sell it, whatever you like.
The Source code can be found inside the Jar archive together with the compiled classes.
I have set the config file system property programmatically but
it is not used. Instead the Java default logging properties is
read and all output is going to console. What might be wrong?
Answer
This is often caused by the problem, that an attempt is made to
set the property after (!) setup of java.util.logging has been
completed. For example in the class below
package de.softquadrat.logging; |
Java2html |
the main method will be reached after the java.util.logging framework
has been initialized. The reason lies in the constant LOGGER, that is
instantiated when the class is loaded and before (!) main is called. In absence
of the system property for the logging config file in that
moment the default config file is read from jre/lib directory instead.
Set the logging config file property from command line with "-Djava.util.logging.config.file=..."
to solve this problem.
Why are there no thread names available to be logged?
Answer
This is a restriction of the java.util.logging framework. The thread id
available in the log records is unique id generated inside the
logging framework that has no relations to the thread ids inside
the JVM. By this there is no way to map the thread ids to thread
name.
What is the performance impact of the formatter and did you do
any performance optimization.
Answer
Currently we did not investigate on performance figures and no
optimization was done. If you think you can provide valuable
experience please let us know and joins us.