- Documenting LocLogger and co.

This commit is contained in:
Ceki Gulcu 2009-09-04 19:50:15 +02:00
parent a9ff32e4b7
commit e69cd9fa61
14 changed files with 265 additions and 84 deletions

View File

@ -80,7 +80,7 @@
<dependency>
<groupId>ch.qos.cal10n</groupId>
<artifactId>cal10n-api</artifactId>
<version>0.5.1</version>
<version>0.7</version>
</dependency>
</dependencies>

View File

@ -21,8 +21,6 @@
*/
package org.slf4j.cal10n;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
@ -30,7 +28,6 @@ import org.slf4j.ext.LoggerWrapper;
import org.slf4j.spi.LocationAwareLogger;
import ch.qos.cal10n.IMessageConveyor;
import ch.qos.cal10n.MessageConveyor;
import ch.qos.cal10n.MessageParameterObj;
/**
@ -50,13 +47,14 @@ public class LocLogger extends LoggerWrapper implements Logger {
*/
static Marker LOCALIZED = MarkerFactory.getMarker("LOCALIZED");
final Locale locale;
final IMessageConveyor imc;
public LocLogger(Logger logger, Locale locale) {
public LocLogger(Logger logger, IMessageConveyor imc) {
super(logger, LoggerWrapper.class.getName());
this.locale = locale;
imc = new MessageConveyor(locale);
if(imc == null) {
throw new IllegalArgumentException("IMessageConveyor cannot be null");
}
this.imc = imc;
}
/**

View File

@ -21,11 +21,11 @@
*/
package org.slf4j.cal10n;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.cal10n.IMessageConveyor;
/**
*
* This class is essentially a wrapper around an {@link LoggerFactory} producing
@ -34,19 +34,19 @@ import org.slf4j.LoggerFactory;
* <p>
* Contrary to {@link LoggerFactory#getLogger(String)} method of
* {@link LoggerFactory}, each call to {@link getLocLogger} produces a new
* instance of {@link LocLogger}. This should not matter because an XLogger
* instance does have any state beyond that of the {@link Logger} instance
* it wraps and its locale.
* instance of {@link LocLogger}. This should not matter because a LocLogger
* instance does have any state beyond that of the {@link Logger} in stance it
* wraps and its message conveyor.
*
* @author Ceki Gulcu
* @author Ceki G&uuml;c&uuml;
*
*/
public class LocLoggerFactory {
final Locale locale;
final IMessageConveyor imc;
public LocLoggerFactory(Locale locale) {
this.locale = locale;
public LocLoggerFactory(IMessageConveyor imc) {
this.imc = imc;
}
/**
@ -56,7 +56,7 @@ public class LocLoggerFactory {
* @return
*/
public LocLogger getLocLogger(String name) {
return new LocLogger(LoggerFactory.getLogger(name), locale);
return new LocLogger(LoggerFactory.getLogger(name), imc);
}
/**

View File

@ -32,12 +32,16 @@ import org.slf4j.cal10n.LocLogger;
import org.slf4j.cal10n.LocLoggerFactory;
import org.slf4j.dummyExt.ListAppender;
import ch.qos.cal10n.IMessageConveyor;
import ch.qos.cal10n.MessageConveyor;
public class LocLoggerTest extends TestCase {
ListAppender listAppender;
org.apache.log4j.Logger log4jRoot;
LocLoggerFactory llFactory_uk = new LocLoggerFactory(Locale.UK);
IMessageConveyor imc = new MessageConveyor(Locale.UK);
LocLoggerFactory llFactory_uk = new LocLoggerFactory(imc);
final static String EXPECTED_FILE_NAME = "LocLoggerTest.java";

View File

@ -1,8 +1,8 @@
package org.slf4j.cal10n_dummy;
import ch.qos.cal10n.ResourceBundleName;
import ch.qos.cal10n.BaseName;
@ResourceBundleName("months")
@BaseName("months")
public enum Months {
JAN, FEB, MAR, APR, MAY, JUN;

View File

@ -0,0 +1,32 @@
package org.slf4j.cal10n_dummy;
import java.util.Locale;
import org.slf4j.cal10n.LocLogger;
import org.slf4j.cal10n.LocLoggerFactory;
import ch.qos.cal10n.IMessageConveyor;
import ch.qos.cal10n.MessageConveyor;
public class MyApplication {
// create a message conveyor for a given locale
IMessageConveyor messageConveyor = new MessageConveyor(Locale.UK);
// create the LogLoggerFactory
LocLoggerFactory llFactory_uk = new LocLoggerFactory(messageConveyor);
// create a locLogger
LocLogger locLogger = llFactory_uk.getLocLogger(this.getClass());
public void applicationStart() {
locLogger.info(Production.APPLICATION_STARTED);
// ..
}
public void applicationStop() {
locLogger.info(Production.APPLICATION_STOPPED);
// ...
}
}

View File

@ -0,0 +1,12 @@
package org.slf4j.cal10n_dummy;
import junit.framework.*;
public class PackageTest extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(LocLoggerTest.class);
return suite;
}
}

View File

@ -0,0 +1,14 @@
package org.slf4j.cal10n_dummy;
import ch.qos.cal10n.LocaleData;
import ch.qos.cal10n.Locale;
import ch.qos.cal10n.BaseName;
@BaseName("production")
@LocaleData( { @Locale("en_UK"), @Locale("fr") })
public enum Production {
APPLICATION_STARTED,
APPLICATION_STOPPED,
DB_CONNECTION,
DB_CONNECTION_FAILURE;
}

View File

@ -29,6 +29,9 @@
<li><a href="legacy.html">Bridging legacy APIs</a></li>
<li><a href="migrator.html">SLF4J migrator</a></li>
<li><a href="extensions.html">SLF4J extensions</a></li>
<li><a href="localization.html">Localization/Internalization support</a></li>
<li><a href="apidocs/index.html">javadocs</a></li>
<li>
<a href="xref/index.html">sources</a>,

View File

@ -24,6 +24,16 @@
<p>Download version ${project.version} including <i>full source code</i>,
class files and documentation in ZIP or TAR.GZ format: </p>
<p>Stable version</p>
<ul>
<li><a href="dist/slf4j-1.5.8.tar.gz"><b>slf4j-1.5.8.tar.gz</b></a> </li>
<li><a href="dist/slf4j-1.5.8.zip"><b>slf4j-1.5.8.zip</b></a> </li>
</ul>
<p>Release candidate</p>
<ul>
<li><a href="dist/slf4j-${project.version}.tar.gz"><b>slf4j-${project.version}.tar.gz</b></a> </li>
<li><a href="dist/slf4j-${project.version}.zip"><b>slf4j-${project.version}.zip</b></a> </li>

View File

@ -7,10 +7,11 @@
<title>SLF4J extensions</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/site.css" />
<link rel="stylesheet" type="text/css" href="css/prettify.css" />
</head>
<body>
<body onload="prettyPrint()">
<script type="text/javascript">prefix='';</script>
<script type="text/javascript" src="js/prettify.js"></script>
<script src="templates/header.js" type="text/javascript"></script>
<div id="left">
<script src="templates/left.js" type="text/javascript"></script>
@ -56,7 +57,7 @@
<em>Example: Using the profiler: <a
href="xref-test/org/slf4j/profiler/BasicProfilerDemo.html">BasicProfilerDemo</a></em>
<p class="source">[omitted]
<pre class="prettyprint source">[omitted]
32 public class BasicProfilerDemo {
33
34 public static void main(String[] args) {
@ -72,7 +73,7 @@
44 doOther();
45 <b>profiler.stop().print();</b>
46 }
[omitted]</p>
[omitted]</pre>
<p>Running the above example will output the following output.</p>
@ -119,7 +120,7 @@
href="xref-test/org/slf4j/profiler/NestedProfilerDemo.html">NestedProfilerDemo</a>
</em>
<p class="source">33 public class NestedProfilerDemo {
<pre class="prettyprint source">33 public class NestedProfilerDemo {
34
35 public static void main(String[] args) {
36 // create a profiler called "DEMO"
@ -148,14 +149,14 @@
59 // stop and print the "DEMO" printer
60 profiler.stop().print();
61 }
62 }</p>
62 }</pre>
<p>Here is the relevant excerpt from the <a
href="xref-test/org/slf4j/profiler/SortAndPruneComposites.html">SortAndPruneComposites</a>
class.
</p>
<p class="source">[omitted]
<pre class="prettyprint source">[omitted]
6 public class SortAndPruneComposites {
7
8 static String NESTED_PROFILER_NAME = "SORT_AND_PRUNE";
@ -183,7 +184,7 @@
30
31 return result;
32 }
[omitted] </p>
[omitted] </pre>
<p>On a Dual-Core Intel CPU clocked at 3.2 GHz, running the
@ -229,7 +230,7 @@
href="xref-test/org/slf4j/profiler/NestedProfilerDemo2.html">NestedProfilerDemo2</a>
</em>
<p class="source">[omitted]
<pre class="prettyprint source">[omitted]
17 public class NestedProfilerDemo2 {
18
19 static Logger logger = LoggerFactory.getLogger(NestedProfilerDemo2.class);
@ -255,7 +256,7 @@
39 // stop and log
40 profiler.stop().<b>log()</b>;
41 }
42 } </p>
42 } </pre>
<p>The output generated by this example will depend on the logging
environment, but should be very similar to the output generated by
@ -276,7 +277,7 @@
<em>logback configuration disabling logging from profilers, and only
profilers</em>
<p class="source">&lt;configuration>
<pre class="prettyprint source">&lt;configuration>
<b>&lt;turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
&lt;Marker>PROFILER&lt;/Marker>
@ -294,7 +295,7 @@
&lt;level value="DEBUG" />
&lt;appender-ref ref="STDOUT" />
&lt;/root>
&lt;/configuration> </p>
&lt;/configuration> </pre>
<!-- .............................................................. -->
@ -398,7 +399,7 @@
not handled.
</p>
<p class="source">package com.test;
<pre class="prettyprint source">package com.test;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
@ -449,13 +450,13 @@ public class TestService {
logger.exit(key);
return key;
}
}</p>
}</pre>
<p>This test application uses the preceding service to generate
logging events.
</p>
<p class="source">package com.test;
<pre class="prettyprint source">package com.test;
public class App {
public static void main( String[] args ) {
@ -464,7 +465,7 @@ public class App {
service.retrieveMessage();
service.exampleException();
}
} </p>
} </pre>
<p>The configuration below will cause all output to be routed to
target/test.log. The pattern for the FileAppender includes the
@ -472,7 +473,7 @@ public class App {
pattern are critical for the log to be of value.
</p>
<p class="source">&lt;?xml version='1.0' encoding='UTF-8'?>
<pre class="prettyprint source">&lt;?xml version='1.0' encoding='UTF-8'?>
&lt;configuration&gt;
&lt;appender name="console" class="ch.qos.logback.core.ConsoleAppender"&gt;
&lt;filter class="ch.qos.logback.classic.filter.LevelFilter"&gt;
@ -497,7 +498,7 @@ public class App {
&lt;appender-ref ref="log" /&gt;
&lt;/root&gt;
&lt;/configuration&gt;
</p>
</pre>
<p>
Here is the output that results from the Java classes and configuration above.
</p>
@ -596,7 +597,7 @@ java.lang.ArrayIndexOutOfBoundsException: 3
occurs an EventData object should be created and populated. Then call EventLogger.logEvent(data)
where data is a reference to the EventData object.</p>
<p class="source">import org.slf4j.MDC;
<pre class="prettyprint source">import org.slf4j.MDC;
import org.apache.commons.lang.time.DateUtils;
import javax.servlet.Filter;
@ -666,10 +667,10 @@ public class RequestFilter implements Filter
public void destroy() {
}
}
</p>
} </pre>
<p>Sample class that uses EventLogger.</p>
<p class="source">import org.slf4j.ext.EventData;
<pre class="prettyprint source">import org.slf4j.ext.EventData;
import org.slf4j.ext.EventLogger;
import java.util.Date;
@ -691,11 +692,11 @@ public class MyApp {
EventLogger.logEvent(data);
return confirm;
}
}
</p>
} </pre>
<p>The EventLogger class uses a Logger named "EventLogger". EventLogger uses a logging level
of INFO. The following shows a configuraton using Logback.</p>
<p class="source">&lt;configuration&gt;
<pre class="prettyprint source">&lt;configuration&gt;
&lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"&gt;
&lt;layout class="ch.qos.logback.classic.PatternLayout"&gt;
&lt;Pattern&gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/Pattern&gt;
@ -717,8 +718,7 @@ public class MyApp {
&lt;appender-ref ref="STDOUT" /&gt;
&lt;/root&gt;
&lt;/configuration&gt;
</p>
&lt;/configuration&gt; </pre>
<!-- .............................................................. -->
@ -761,15 +761,15 @@ public class MyApp {
<p>Given the well-known "Hello World" example:</p>
<p class="source">public class HelloWorld {
<pre class="prettyprint source">public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World");
}
}</p>
}</pre>
<p>a typical transformation would be similar to: (imports omitted)</p>
<p class="source">public class LoggingHelloWorld {
<pre class="prettyprint source">public class LoggingHelloWorld {
final static Logger _log = LoggerFactory.getLogger(LoggingHelloWorld.class.getName());
public static void main(String args[]) {
@ -781,7 +781,7 @@ public class MyApp {
_log.info("&lt; main()");
}
}
}</p>
}</pre>
<p>which in turn produces the following result when run similar to
"java LoggingHelloWorld 1 2 3 4":

View File

@ -935,33 +935,12 @@ logger.debug("The new entry is {}.", entry);</pre>
</dt>
<dd>
<p>No. SLF4J does not offer any particular support for
I18N. However, nothing prevents you from implementing i18n
support around the SLF4J API.</p>
<p>As suggested by Sebastien Davids in <a
href="http://bugzilla.slf4j.org/show_bug.cgi?id=50">bug report
50</a>, a possible pattern might be:</p>
<pre class="prettyprint source">class MyClass {
ResourceBundle bundle = ResourceBundle.getBundle("my.package.messages");
Logger logger = LoggerFactory.getLogger(MyClass.class);
void method() {
if (logger.isWarnEnabled()) {
MessageFormat format = new MessageFormat(bundle.getString("<b>my_message_key</b>"));
logger.warn(format.format(new Object[] { new Date(), 1 }));
}
}
}</pre>
<p>Where <code>my_message_key</code> is defined as</p>
<pre class="prettyprint source"><b>my_message_key</b>=my text to be i18n {1,date,short} {0,number,00}</pre>
<p>Yes, as of version 1.5.9, SLF4J ships with a package called
<code>org.slf4j.cal10n</code> which adds <a
href="localization.html">localized/internationalized logging</a>
support as a thin layer built upon the <a
href="http://cal10n.qos.ch">CAL10N API</a>.</p>
</dd>
</dl>

View File

@ -0,0 +1,122 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>Localization</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/site.css" />
<link rel="stylesheet" type="text/css" href="css/prettify.css" />
</head>
<body onload="prettyPrint()">
<script type="text/javascript">prefix='';</script>
<script type="text/javascript" src="js/prettify.js"></script>
<script src="templates/header.js" type="text/javascript"></script>
<div id="left">
<noscript>Please turn on Javascript to view this menu</noscript>
<script src="templates/left.js" type="text/javascript"></script>
</div>
<div id="content">
<h1>Localization support</h1>
<p>A <a
href="http://markmail.org/thread/drcabfc6z42sijdo">discussion</a>
on the slf4j-dev mailing list spawned an open-source project
called <a href="http://cal10n.qos.ch"><b>CAL10N or Compiler
Assisted Localization</b></a>. As its name indicates, CAL10N
focuses on the issue of localization/internationalization in Java
applications.
</p>
<p>The <code>org.slf4j.cal10n</code> package which ships with
<em>slf4j-ext-${project.version}.jar</em> adds an extremely thin
layer on top of CALI0N to offer localized logging.</p>
<p>Once you have a handle on an <a
href="http://cal10n.qos.ch/apidocs/ch/qos/cal10n/IMessageConveyor.html">IMessageConveyor</a>
instance, you can create a <a
href="xref/org/slf4j/cal10n/LocLoggerFactory.html">LocLoggerFactory</a>,
which in turn can create a <a
href="xref/org/slf4j/cal10n/LocLogger.html">LocLogger</a>
instances capable of doing localized logging.
</p>
<p>Let assume that you have defined localized message your
application. In accordance with the CAL10N's philopshopy, you have
the declared the keys for those messages in the enum type
<code>Production</code>.</p>
<pre class="prettyprint source">import ch.qos.cal10n.LocaleData;
import ch.qos.cal10n.Locale;
import ch.qos.cal10n.BaseName;
@BaseName("production")
@LocaleData( { @Locale("en_UK"), @Locale("ja_JP") })
public enum Production {
APPLICATION_STARTED,
APPLICATION_STOPPED,
...
DB_CONNECTION,
DB_CONNECTION_FAILURE;
}</pre>
<p>It is assumed that you have created appropriate bundle file for
the various locales "en_UK" and "ja_JP" as appropriate. Then, you
can instantiate a <code>IMessageCoveyor</code>, inject it into a
<code>LogLoggerFactory</code>, retreive multiple
<code>LogLogger</code> instances by name and log away, as the next
sample code illustrates.
</p>
<pre class="prettyprint source">import java.util.Locale;
import org.slf4j.cal10n.LocLogger;
import org.slf4j.cal10n.LocLoggerFactory;
import ch.qos.cal10n.IMessageConveyor;
import ch.qos.cal10n.MessageConveyor;
public class MyApplication {
// create a message conveyor for a given locale
IMessageConveyor messageConveyor = new MessageConveyor(Locale.JAPAN);
// create the LogLoggerFactory
LocLoggerFactory llFactory_uk = new LocLoggerFactory(messageConveyor);
// create a locLogger
LocLogger locLogger = llFactory_uk.getLocLogger(this.getClass());
public void applicationStart() {
locLogger.info(Production.APPLICATION_STARTED);
// ..
}
public void applicationStop() {
locLogger.info(Production.APPLICATION_STOPPED);
// ...
}
}</pre>
<p>Assuming the resource bundle <em>production_jp.properties</em>
exists, and the underlying logging framework is enabled for the
info level, log messages in Japenese will be output.
</p>
<p>Note that a <code>LogLogger</code> is a regular SLF4J logger
with additional methods supporting localization.</p>
<script src="templates/footer.js" type="text/javascript"></script>
</div>
</body>
</html>

View File

@ -27,15 +27,20 @@
<hr noshade="noshade" size="1"/>
<h3>XX, 2009 - Release of SLF4J 1.5.9</h3>
<h3>XX, 2009 - Release of SLF4J 1.5.9-RC0</h3>
<p>SLF4J version 1.5.9 consist of bug fixes and minor
enhancements. It is totally backward compatible with SLF4J version
1.5.8. However, based on the <a href="http://cal10n.qos.ch/">CAL10N
project</a> support for internationalization was added to the
slf4j-ext module.</p>
1.5.8. However, the slf4j-ext module ships with a new package called
<code>org.slf4j.cal10n</code> which adds <a
href="localization.html">localized/internationalized logging</a>
support as a thin layer built upon the <a
href="http://cal10n.qos.ch">CAL10N API</a>.</p>
<p>Added <a href="localization.html">localized/internationalized
logging</a> support as a thin layer built upon the <a
href="http://cal10n.qos.ch">CAL10N API</a>.</p>
<p>In log4j-over-slf4j, added missing log(...) methods. These were
requested by Zoltan Szel in <a
@ -56,6 +61,8 @@
href="http://bugzilla.slf4j.org/show_bug.cgi?id=146">bug report
146</a> by Dapeng Ni.</p>
<hr noshade="noshade" size="1"/>
<h3>June 11th, 2009 - Release of SLF4J 1.5.8</h3>