<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
Hi guys,<br>
<br>
All System.out calls in drools production code have been replace by
sl4j-api logging calls.<br>
The unit tests and the examples use logback (which is the standard
slf4j-api implementation) to output those calls to the console.<br>
<br>
For example:<br>
2012-08-08 21:23:41,101 [main] INFO DroolsExamplesApp started.<br>
<br>
<b>Where can I configure the logging?</b><br>
<ul>
<li>Production code (such as drools-core/src/main/java) isn't
executed directly and therefor has no logging configuration.<br>
</li>
<li>For a unit test, configure your logging desires in
src/test/resources/logback-test.xml</li>
<li>For an example application, configure your logging desires in
src/main/resources/logback.xml</li>
<li>For a war, configure your logging desires in
src/main/resources/logback.xml</li>
</ul>
<p>Notice that drools-core does not depend on logback (unlike it's
tests) or any other logging implementation:<br>
the user can easily bridge the drools logs to his favorite logging
system (for example with slf4j-jcl).<br>
</p>
<b>What can I display in my log?</b><br>
<br>
Everything that gets logged, not just from drools, but <i>also from
any other dependency</i> (*).<br>
(*) if they don't use slf4j, logging can be unified by bridges (for
example with jcl-over-slf4j).<br>
<br>
Here's an example that logs on debug level of drools and
springframework and on warn level for all other dependencies:<br>
<br>
<configuration><br>
<logger name="org.drools" level="debug"/><br>
<logger name="org.springframework" level="debug"/><br>
<logger name="org.drools.foo.bar.MyReallyVerboseDebugClass"
level="info"/><br>
<br>
<root level="warn"><br>
<appender-ref ref="consoleAppender" /><br>
</root><br>
</configuration><br>
<br>
<b>How do I use logging in my classes?</b><br>
<br>
public class MyFoo {<br>
<br>
protected static transient Logger logger =
LoggerFactory.getLogger(MyFoo.class);<br>
<br>
public void bar() {<br>
logger.trace("Something in a loop happened."); <br>
logger.debug("Something happened"); <br>
logger.info("DroolsExamplesApp started.");<br>
logger.warn("That rule is pointless.");<br>
logger.error("Don't divide by zero.", myException); // it's
probably better to only throw a RuntimeException to the user code
and let him log it<br>
}<br>
<br>
}<br>
<b><br>
How do I make logging fast?</b><br>
<br>
1) Keep the Logger a static field: that way it's creation cost is
independent of how many instances of your class are created<br>
<br>
2) Avoid String concatenating when trace is disabled:<br>
Slower:<br>
logger.trace("String a is " + a + " and string b is " + b + ".");
// slow<br>
Faster:<br>
logger.trace("String a is {} and string b is {}.", a, b);<br>
Because it checks if trace is enabled first, before concatenating
the String.<br>
When performance matters, trace logging will be very likely
disabled.<br>
<br>
3) Don't use System.out or System.err.<br>
Such an operation always synchronizes on a printstream and the user
is unable to disable that performance cost.<br>
Use logging instead, so the user can configure it to discard the
messages and their performance cost.<br>
<br>
<b>What best practices should I follow?</b><br>
<br>
1) Don't use custom flags to disable/enable logging:<br>
boolean hideWarnings = Boolean.getBoolean(
"drools.schema.hidewarnings" );<br>
if ( !hideWarnings ) {<br>
System.out.println( "Your SAX parser is not
JAXP 1.2 compliant - turning off validation." );<br>
}<br>
Just do this instead:<br>
logger.warn( "Your SAX parser is not JAXP 1.2 compliant -
turning off validation." );<br>
which outputs as for example:<br>
... org.drools.MySaxParserClass WARN Your SAX parser is not JAXP
1.2 compliant - turning off validation.<br>
Now, the user can easily hide that warning in the typical log
configuration way:<br>
<logger name="org.drools.MySaxParserClass" level="error"/><br>
Instead of having to learn about "drools.schema.hidewarnings" and
set that parameter somewhere.<br>
<br>
2) Prefer logger.debug() (or logger.trace()) instead of
logger.info().<br>
Most log messages are not interesting enough to get the level info.
Fight verbosity.<br>
A good rule of thumb: Running your code for an hour should not
output more than 10 info messages if nothing failed.<br>
<br>
<b>The logging is too big for my console</b><br>
<br>
Use a fileAppender temporary for yourself, but don't add it to the
default logback-test.xml configuration:<br>
<br>
<appender name="fileAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender"><br>
<file>local/log/drools.log</file><br>
<rollingPolicy
class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"><br>
<fileNamePattern>local/log/drools.%i.log.zip</fileNamePattern><br>
<minIndex>1</minIndex><br>
<maxIndex>3</maxIndex><br>
</rollingPolicy><br>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><br>
<maxFileSize>5MB</maxFileSize><br>
</triggeringPolicy><br>
<encoder><br>
<pattern>%d [%t] %-5p %m%n</pattern><br>
</encoder><br>
</appender><br>
<br>
<root level="warn"><br>
<appender-ref ref="consoleAppender" /><br>
<appender-ref ref="fileAppender" /><br>
</root><br>
<pre class="moz-signature" cols="72">--
With kind regards,
Geoffrey De Smet</pre>
</body>
</html>