You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bu...@apache.org on 2013/11/17 15:50:11 UTC
svn commit: r886967 - in /websites/staging/sling/trunk/content: ./
documentation/development/logging-new.html
Author: buildbot
Date: Sun Nov 17 14:50:11 2013
New Revision: 886967
Log:
Staging update by buildbot for sling
Modified:
websites/staging/sling/trunk/content/ (props changed)
websites/staging/sling/trunk/content/documentation/development/logging-new.html
Propchange: websites/staging/sling/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Sun Nov 17 14:50:11 2013
@@ -1 +1 @@
-1542739
+1542740
Modified: websites/staging/sling/trunk/content/documentation/development/logging-new.html
==============================================================================
--- websites/staging/sling/trunk/content/documentation/development/logging-new.html (original)
+++ websites/staging/sling/trunk/content/documentation/development/logging-new.html Sun Nov 17 14:50:11 2013
@@ -107,186 +107,6 @@ features</p>
<li>Configures logging through Logback which is integrated with the OSGi environment</li>
<li>Logging can be configured both via editing Logback xml or via OSGi Configurations</li>
</ul>
-<h2 id="logback-integration">Logback Integration</h2>
-<p>Logback integration provides following features</p>
-<ul>
-<li>LogBack configuration can be provided via Logback config xml</li>
-<li>Supports Appenders registered as OSGi Services</li>
-<li>Supports Filters and TurboFilters registered as OSGi Services</li>
-<li>Support providing Logback config as fragments through OSGi Service Registry</li>
-<li>Support for referring to Appenders registered as OSGi services from with Logback
- config</li>
-<li>Exposing Logback runtime state through Felix WebConsole Plugin</li>
-</ul>
-<p>Following sections would provide more details around these features</p>
-<h3 id="turbofilters-as-osgi-service">TurboFilters as OSGi Service</h3>
-<p><a href="http://logback.qos.ch/manual/filters.html#TurboFilter">Logback TurboFilter</a> operate globally and invoked for every Logback call. To register a <code>TurboFilter</code> as OSGi service
-the bundle just need to register a service against <code>ch.qos.logback.classic.turbo.TurboFilter</code> class</p>
-<div class="codehilite"><pre><span class="kn">import</span> <span class="nn">import</span> <span class="n">ch</span><span class="o">.</span><span class="na">qos</span><span class="o">.</span><span class="na">logback</span><span class="o">.</span><span class="na">classic</span><span class="o">.</span><span class="na">turbo</span><span class="o">.</span><span class="na">MatchingFilter</span><span class="o">;</span>
-
-<span class="n">SimpleTurboFilter</span> <span class="n">stf</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimpleTurboFilter</span><span class="o">();</span>
-<span class="n">ServiceRegistration</span> <span class="n">sr</span> <span class="o">=</span> <span class="n">bundleContext</span><span class="o">.</span><span class="na">registerService</span><span class="o">(</span><span class="n">TurboFilter</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span> <span class="n">stf</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
-
-<span class="kd">private</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">SimpleTurboFilter</span> <span class="kd">extends</span> <span class="n">MatchingFilter</span> <span class="o">{</span>
- <span class="nd">@Override</span>
- <span class="kd">public</span> <span class="n">FilterReply</span> <span class="nf">decide</span><span class="o">(</span><span class="n">Marker</span> <span class="n">marker</span><span class="o">,</span> <span class="n">Logger</span> <span class="n">logger</span><span class="o">,</span> <span class="n">Level</span> <span class="n">level</span><span class="o">,</span> <span class="n">String</span> <span class="n">format</span><span class="o">,</span>
- <span class="n">Object</span><span class="o">[]</span> <span class="n">params</span><span class="o">,</span> <span class="n">Throwable</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
- <span class="k">if</span><span class="o">(</span><span class="n">logger</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">"turbofilter.foo.bar"</span><span class="o">)){</span>
- <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">DENY</span><span class="o">;</span>
- <span class="o">}</span>
- <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">NEUTRAL</span><span class="o">;</span>
- <span class="o">}</span>
-<span class="o">}</span>
-</pre></div>
-
-
-<p>As these filters are invoked for every call they must not take much time to execute.</p>
-<h3 id="filter-as-osgi-service">Filter as OSGi service</h3>
-<p><a href="http://logback.qos.ch/manual/filters.html">Logback Filters</a> are attached to appenders and are used to determine if any LoggingEvent needs to
-be passed to the appender. When registering a filter the bundle needs to configure a service property
-<code>appenders</code> which refers to list of appender names to which the Filter must be attached</p>
-<div class="codehilite"><pre><span class="kn">import</span> <span class="nn">ch.qos.logback.core.filter.Filter</span><span class="o">;</span>
-
-<span class="n">SimpleFilter</span> <span class="n">stf</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimpleFilter</span><span class="o">();</span>
-<span class="n">Dictionary</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="n">props</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Hashtable</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">>();</span>
-<span class="n">props</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"appenders"</span><span class="o">,</span> <span class="s">"TestAppender"</span><span class="o">);</span>
-<span class="n">ServiceRegistration</span> <span class="n">sr</span> <span class="o">=</span> <span class="n">bundleContext</span><span class="o">.</span><span class="na">registerService</span><span class="o">(</span><span class="n">Filter</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span> <span class="n">stf</span><span class="o">,</span> <span class="n">props</span><span class="o">);</span>
-
-<span class="kd">private</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">SimpleFilter</span> <span class="kd">extends</span> <span class="n">Filter</span><span class="o"><</span><span class="n">ILoggingEvent</span><span class="o">></span> <span class="o">{</span>
-
- <span class="nd">@Override</span>
- <span class="kd">public</span> <span class="n">FilterReply</span> <span class="nf">decide</span><span class="o">(</span><span class="n">ILoggingEvent</span> <span class="n">event</span><span class="o">)</span> <span class="o">{</span>
- <span class="k">if</span><span class="o">(</span><span class="n">event</span><span class="o">.</span><span class="na">getLoggerName</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">"filter.foo.bar"</span><span class="o">)){</span>
- <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">DENY</span><span class="o">;</span>
- <span class="o">}</span>
- <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">NEUTRAL</span><span class="o">;</span>
- <span class="o">}</span>
-<span class="o">}</span>
-</pre></div>
-
-
-<h3 id="appenders-as-osgi-service">Appenders as OSGi service</h3>
-<p><a href="http://logback.qos.ch/manual/appenders.html">Logback Appenders</a> handle the logging events produced by Logback. To register an <code>Appender</code> as OSGi service
-the bundle just need to register a service against <code>ch.qos.logback.core.Appender</code> class. When registering an
-appender the bundle needs to configure a service property <code>loggers</code> which refers to list of logger names to which
-the Appender must be attached</p>
-<div class="codehilite"><pre><span class="n">Dictionary</span><span class="o"><</span><span class="n">String</span><span class="o">,</span><span class="n">Object</span><span class="o">></span> <span class="n">props</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Hashtable</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">>();</span>
-
-<span class="n">String</span><span class="o">[]</span> <span class="n">loggers</span> <span class="o">=</span> <span class="o">{</span>
- <span class="s">"foo.bar:DEBUG"</span><span class="o">,</span>
- <span class="s">"foo.bar.zoo:INFO"</span><span class="o">,</span>
-<span class="o">};</span>
-
-<span class="n">props</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"loggers"</span><span class="o">,</span><span class="n">loggers</span><span class="o">);</span>
-<span class="n">sr</span> <span class="o">=</span> <span class="n">bundleContext</span><span class="o">.</span><span class="na">registerService</span><span class="o">(</span><span class="n">Appender</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span><span class="k">this</span><span class="o">,</span><span class="n">props</span><span class="o">);</span>
-</pre></div>
-
-
-<h3 id="logback-config-fragment-support">Logback Config Fragment Support</h3>
-<p>Logback supports including parts of a configuration file from another file (See <a href="http://logback.qos.ch/manual/configuration.html#fileInclusion">File Inclusion</a>). This module
-extends that support by allowing other bundles to provide config fragments. There are two ways to achieve that</p>
-<h4 id="exposing-fragment-as-string-objects">Exposing fragment as String objects</h4>
-<p>If you have the config as string then you can register that String instance as a service with property <code>logbackConfig</code>
-set to true. Sling Logback Extension would monitor such objects and pass them to logback</p>
-<div class="codehilite"><pre>Properties props = new Properties();
-props.setProperty("logbackConfig","true");
-
-String config = "<span class="nt"><included></span>\n" +
- " <span class="nt"><appender</span> <span class="na">name=</span><span class="s">\"FOOFILE\"</span> <span class="na">class=</span><span class="s">\"ch.qos.logback.core.FileAppender\"</span><span class="nt">></span>\n" +
- " <span class="nt"><file></span><span class="cp">${</span><span class="n">sling</span><span class="o">.</span><span class="n">home</span><span class="cp">}</span>/logs/foo.log<span class="nt"></file></span>\n" +
- " <span class="nt"><encoder></span>\n" +
- " <span class="nt"><pattern></span>%d %-5level %logger{35} - %msg %n<span class="nt"></pattern></span>\n" +
- " <span class="nt"></encoder></span>\n" +
- " <span class="nt"></appender></span>\n" +
- "\n" +
- " <span class="nt"><logger</span> <span class="na">name=</span><span class="s">\"foo.bar.include\"</span> <span class="na">level=</span><span class="s">\"INFO\"</span><span class="nt">></span>\n" +
- " <span class="nt"><appender</span><span class="err">-ref</span> <span class="na">ref=</span><span class="s">\"FOOFILE\"</span> <span class="nt">/></span>\n" +
- " <span class="nt"></logger></span>\n" +
- "\n" +
- "<span class="nt"></included></span>";
-
-registration = context.registerService(String.class.getName(),config,props);
-</pre></div>
-
-
-<p>If the config needs to be updated just re-register the service and change would be picked up</p>
-<h4 id="exposing-fragment-as-configprovider-instance">Exposing fragment as ConfigProvider instance</h4>
-<p>Another way to provide config fragment is by providing an implementation of <code>org.apache.sling.commons.log.logback.ConfigProvider</code></p>
-<div class="codehilite"><pre><span class="p">@</span><span class="n">Component</span>
-<span class="p">@</span><span class="n">Service</span>
-<span class="n">public</span> <span class="n">class</span> <span class="n">ConfigProviderExample</span> <span class="n">implements</span> <span class="n">ConfigProvider</span> <span class="p">{</span>
- <span class="n">public</span> <span class="n">InputSource</span> <span class="n">getConfigSource</span><span class="p">()</span> <span class="p">{</span>
- <span class="k">return</span> <span class="n">new</span> <span class="n">InputSource</span><span class="p">(</span><span class="n">getClass</span><span class="p">().</span><span class="n">getClassLoader</span><span class="p">().</span><span class="n">getResourceAsStream</span><span class="p">(</span>"<span class="n">foo</span><span class="o">-</span><span class="n">config</span><span class="p">.</span><span class="n">xml</span>"<span class="p">));</span>
- <span class="p">}</span>
-<span class="p">}</span>
-</pre></div>
-
-
-<p>If the config changes then sending an event to <code>org/apache/sling/commons/log/RESET</code> would reset the Logback runtime</p>
-<div class="codehilite"><pre><span class="n">eventAdmin</span><span class="p">.</span><span class="n">sendEvent</span><span class="p">(</span><span class="n">new</span> <span class="n">Event</span><span class="p">(</span>"<span class="n">org</span><span class="o">/</span><span class="n">apache</span><span class="o">/</span><span class="n">sling</span><span class="o">/</span><span class="n">commons</span><span class="o">/</span><span class="nb">log</span><span class="o">/</span><span class="n">RESET</span>"<span class="p">,</span><span class="n">new</span> <span class="n">Properties</span><span class="p">()));</span>
-</pre></div>
-
-
-<h3 id="external-config-file">External Config File</h3>
-<p>Logback can be configured with an external file. The file name can be specified through</p>
-<ol>
-<li>OSGi config - Look for config with name <code>Apache Sling Logging Configuration</code> and specify the path for
- config file property</li>
-<li>OSGi Framework Properties - Logback supports also looks for file name with property name
- <code>org.apache.sling.commons.log.configurationFile</code></li>
-</ol>
-<p>If you are providing an external config file then to support OSGi integration you would need to add following
-action entry</p>
-<div class="codehilite"><pre><span class="nt"><newRule</span> <span class="na">pattern=</span><span class="s">"*/configuration/osgi"</span>
- <span class="na">actionClass=</span><span class="s">"org.apache.sling.commons.log.logback.OsgiAction"</span><span class="nt">/></span>
-<span class="nt"><newRule</span> <span class="na">pattern=</span><span class="s">"*/configuration/appender-ref-osgi"</span>
- <span class="na">actionClass=</span><span class="s">"org.apache.sling.commons.log.logback.OsgiAppenderRefAction"</span><span class="nt">/></span>
-<span class="nt"><osgi/></span>
-</pre></div>
-
-
-<p>The <code>osgi</code> element enables the OSGi integration support</p>
-<h3 id="java-util-logging-jul-integration">Java Util Logging (JUL) Integration</h3>
-<p>The bundle also support <a href="http://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html">SLF4JBridgeHandler</a>. To enable JUL integration following two steps
-needs to be done. This features allows routing logging messages from JUL to the Logbback appenders</p>
-<ol>
-<li>Set framework property <code>org.apache.sling.commons.log.julenabled</code> to true</li>
-<li>
-<p>Set the <a href="http://logback.qos.ch/manual/configuration.html#LevelChangePropagator">LevelChangePropagator</a> in LogbackConfig</p>
-<p>:::xml
-<configuration>
- <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
- ...
-</configuration></p>
-</li>
-</ol>
-<h3 id="wzxhzdk11wzxhzdk12configuring-osgi-based-appenders-in-logback-config"><a name="config-override"></a>Configuring OSGi based appenders in Logback Config</h3>
-<p>So far Sling used to configure the appenders based on OSGi config. That mode only provide a very limited
-set to configuration options. To make use of other Logback features you can override the OSGi config
-from within the Logback config file. OSGi config based appenders are named based on the file name</p>
-<p>For example for following OSGi config</p>
-<div class="codehilite"><pre><span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">file</span><span class="p">=</span>"<span class="n">logs</span><span class="o">/</span><span class="n">error</span><span class="p">.</span><span class="nb">log</span>"
-<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">level</span><span class="p">=</span>"<span class="n">info</span>"
-<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">file</span><span class="p">.</span><span class="nb">size</span><span class="p">=</span>"<span class="s">'.'</span><span class="n">yyyy</span><span class="o">-</span><span class="n">MM</span><span class="o">-</span><span class="n">dd</span>"
-<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">file</span><span class="p">.</span><span class="n">number</span><span class="p">=</span><span class="n">I</span>"7"
-<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">pattern</span><span class="p">=</span>"<span class="p">{</span>0<span class="p">,</span><span class="n">date</span><span class="p">,</span><span class="n">dd</span><span class="p">.</span><span class="n">MM</span><span class="p">.</span><span class="n">yyyy</span> <span class="n">HH</span><span class="p">:</span><span class="n">mm</span><span class="p">:</span><span class="n">ss</span><span class="p">.</span><span class="n">SSS</span><span class="p">}</span> <span class="o">*</span><span class="p">{</span>4<span class="p">}</span><span class="o">*</span> <span class="p">[{</span>2<span class="p">}]</span> <span class="p">{</span>3<span class="p">}</span> <span class="p">{</span>5<span class="p">}</span>&quo
t;
-</pre></div>
-
-
-<p>The Logback appender would be named as <code>logs/error.log</code>. To extend/override the config in Logback config
-create an appender with name <code>logs/error.log</code></p>
-<div class="codehilite"><pre><span class="nt"><appender</span> <span class="na">name=</span><span class="s">"/logs/error.log"</span> <span class="na">class=</span><span class="s">"ch.qos.logback.core.FileAppender"</span><span class="nt">></span>
- <span class="nt"><file></span>${sling.home}/logs/error.log<span class="nt"></file></span>
- <span class="nt"><encoder></span>
- <span class="nt"><pattern></span>%d %-5level %X{sling.userId:-NA} [%thread] %logger{30} %marker- %msg %n<span class="nt"></pattern></span>
- <span class="nt"><immediateFlush></span>true<span class="nt"></immediateFlush></span>
- <span class="nt"></encoder></span>
-<span class="nt"></appender></span>
-</pre></div>
-
-
-<p>In this case then Log module would create appender based on Logback config instead of OSGi config. This can
-be used to move the application from OSGi based config to Logback based config easily</p>
<h2 id="initial-configuration">Initial Configuration</h2>
<p>The <code>org.apache.sling.commons.log</code> bundle gets the initial configuration from the following <code>BundleContext</code> properties:</p>
<table>
@@ -483,6 +303,186 @@ is ignored and the meaning is probably o
<p>When using Size Rotation, the <code>org.apache.sling.commons.log.file.number</code> defines the number of old log file generations
to keep. For example to keep 5 old log files indexed by 0 through 4, set the <code>org.apache.sling.commons.log.file.number</code>
to <code>5</code> (which happens to be the default).</p>
+<h2 id="logback-integration">Logback Integration</h2>
+<p>Logback integration provides following features</p>
+<ul>
+<li>LogBack configuration can be provided via Logback config xml</li>
+<li>Supports Appenders registered as OSGi Services</li>
+<li>Supports Filters and TurboFilters registered as OSGi Services</li>
+<li>Support providing Logback config as fragments through OSGi Service Registry</li>
+<li>Support for referring to Appenders registered as OSGi services from with Logback
+ config</li>
+<li>Exposing Logback runtime state through Felix WebConsole Plugin</li>
+</ul>
+<p>Following sections would provide more details around these features</p>
+<h3 id="turbofilters-as-osgi-service">TurboFilters as OSGi Service</h3>
+<p><a href="http://logback.qos.ch/manual/filters.html#TurboFilter">Logback TurboFilter</a> operate globally and invoked for every Logback call. To register a <code>TurboFilter</code> as OSGi service
+the bundle just need to register a service against <code>ch.qos.logback.classic.turbo.TurboFilter</code> class</p>
+<div class="codehilite"><pre><span class="kn">import</span> <span class="nn">import</span> <span class="n">ch</span><span class="o">.</span><span class="na">qos</span><span class="o">.</span><span class="na">logback</span><span class="o">.</span><span class="na">classic</span><span class="o">.</span><span class="na">turbo</span><span class="o">.</span><span class="na">MatchingFilter</span><span class="o">;</span>
+
+<span class="n">SimpleTurboFilter</span> <span class="n">stf</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimpleTurboFilter</span><span class="o">();</span>
+<span class="n">ServiceRegistration</span> <span class="n">sr</span> <span class="o">=</span> <span class="n">bundleContext</span><span class="o">.</span><span class="na">registerService</span><span class="o">(</span><span class="n">TurboFilter</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span> <span class="n">stf</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
+
+<span class="kd">private</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">SimpleTurboFilter</span> <span class="kd">extends</span> <span class="n">MatchingFilter</span> <span class="o">{</span>
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="n">FilterReply</span> <span class="nf">decide</span><span class="o">(</span><span class="n">Marker</span> <span class="n">marker</span><span class="o">,</span> <span class="n">Logger</span> <span class="n">logger</span><span class="o">,</span> <span class="n">Level</span> <span class="n">level</span><span class="o">,</span> <span class="n">String</span> <span class="n">format</span><span class="o">,</span>
+ <span class="n">Object</span><span class="o">[]</span> <span class="n">params</span><span class="o">,</span> <span class="n">Throwable</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span>
+ <span class="k">if</span><span class="o">(</span><span class="n">logger</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">"turbofilter.foo.bar"</span><span class="o">)){</span>
+ <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">DENY</span><span class="o">;</span>
+ <span class="o">}</span>
+ <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">NEUTRAL</span><span class="o">;</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<p>As these filters are invoked for every call they must not take much time to execute.</p>
+<h3 id="filter-as-osgi-service">Filter as OSGi service</h3>
+<p><a href="http://logback.qos.ch/manual/filters.html">Logback Filters</a> are attached to appenders and are used to determine if any LoggingEvent needs to
+be passed to the appender. When registering a filter the bundle needs to configure a service property
+<code>appenders</code> which refers to list of appender names to which the Filter must be attached</p>
+<div class="codehilite"><pre><span class="kn">import</span> <span class="nn">ch.qos.logback.core.filter.Filter</span><span class="o">;</span>
+
+<span class="n">SimpleFilter</span> <span class="n">stf</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimpleFilter</span><span class="o">();</span>
+<span class="n">Dictionary</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="n">props</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Hashtable</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">>();</span>
+<span class="n">props</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"appenders"</span><span class="o">,</span> <span class="s">"TestAppender"</span><span class="o">);</span>
+<span class="n">ServiceRegistration</span> <span class="n">sr</span> <span class="o">=</span> <span class="n">bundleContext</span><span class="o">.</span><span class="na">registerService</span><span class="o">(</span><span class="n">Filter</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span> <span class="n">stf</span><span class="o">,</span> <span class="n">props</span><span class="o">);</span>
+
+<span class="kd">private</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">SimpleFilter</span> <span class="kd">extends</span> <span class="n">Filter</span><span class="o"><</span><span class="n">ILoggingEvent</span><span class="o">></span> <span class="o">{</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="n">FilterReply</span> <span class="nf">decide</span><span class="o">(</span><span class="n">ILoggingEvent</span> <span class="n">event</span><span class="o">)</span> <span class="o">{</span>
+ <span class="k">if</span><span class="o">(</span><span class="n">event</span><span class="o">.</span><span class="na">getLoggerName</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">"filter.foo.bar"</span><span class="o">)){</span>
+ <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">DENY</span><span class="o">;</span>
+ <span class="o">}</span>
+ <span class="k">return</span> <span class="n">FilterReply</span><span class="o">.</span><span class="na">NEUTRAL</span><span class="o">;</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<h3 id="appenders-as-osgi-service">Appenders as OSGi service</h3>
+<p><a href="http://logback.qos.ch/manual/appenders.html">Logback Appenders</a> handle the logging events produced by Logback. To register an <code>Appender</code> as OSGi service
+the bundle just need to register a service against <code>ch.qos.logback.core.Appender</code> class. When registering an
+appender the bundle needs to configure a service property <code>loggers</code> which refers to list of logger names to which
+the Appender must be attached</p>
+<div class="codehilite"><pre><span class="n">Dictionary</span><span class="o"><</span><span class="n">String</span><span class="o">,</span><span class="n">Object</span><span class="o">></span> <span class="n">props</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Hashtable</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">>();</span>
+
+<span class="n">String</span><span class="o">[]</span> <span class="n">loggers</span> <span class="o">=</span> <span class="o">{</span>
+ <span class="s">"foo.bar:DEBUG"</span><span class="o">,</span>
+ <span class="s">"foo.bar.zoo:INFO"</span><span class="o">,</span>
+<span class="o">};</span>
+
+<span class="n">props</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"loggers"</span><span class="o">,</span><span class="n">loggers</span><span class="o">);</span>
+<span class="n">sr</span> <span class="o">=</span> <span class="n">bundleContext</span><span class="o">.</span><span class="na">registerService</span><span class="o">(</span><span class="n">Appender</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span><span class="k">this</span><span class="o">,</span><span class="n">props</span><span class="o">);</span>
+</pre></div>
+
+
+<h3 id="logback-config-fragment-support">Logback Config Fragment Support</h3>
+<p>Logback supports including parts of a configuration file from another file (See <a href="http://logback.qos.ch/manual/configuration.html#fileInclusion">File Inclusion</a>). This module
+extends that support by allowing other bundles to provide config fragments. There are two ways to achieve that</p>
+<h4 id="exposing-fragment-as-string-objects">Exposing fragment as String objects</h4>
+<p>If you have the config as string then you can register that String instance as a service with property <code>logbackConfig</code>
+set to true. Sling Logback Extension would monitor such objects and pass them to logback</p>
+<div class="codehilite"><pre><span class="n">Properties</span> <span class="n">props</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Properties</span><span class="o">();</span>
+<span class="n">props</span><span class="o">.</span><span class="na">setProperty</span><span class="o">(</span><span class="s">"logbackConfig"</span><span class="o">,</span><span class="s">"true"</span><span class="o">);</span>
+
+<span class="n">String</span> <span class="n">config</span> <span class="o">=</span> <span class="s">"<included>\n"</span> <span class="o">+</span>
+ <span class="s">" <appender name=\"FOOFILE\" class=\"ch.qos.logback.core.FileAppender\">\n"</span> <span class="o">+</span>
+ <span class="s">" <file>${sling.home}/logs/foo.log</file>\n"</span> <span class="o">+</span>
+ <span class="s">" <encoder>\n"</span> <span class="o">+</span>
+ <span class="s">" <pattern>%d %-5level %logger{35} - %msg %n</pattern>\n"</span> <span class="o">+</span>
+ <span class="s">" </encoder>\n"</span> <span class="o">+</span>
+ <span class="s">" </appender>\n"</span> <span class="o">+</span>
+ <span class="s">"\n"</span> <span class="o">+</span>
+ <span class="s">" <logger name=\"foo.bar.include\" level=\"INFO\">\n"</span> <span class="o">+</span>
+ <span class="s">" <appender-ref ref=\"FOOFILE\" />\n"</span> <span class="o">+</span>
+ <span class="s">" </logger>\n"</span> <span class="o">+</span>
+ <span class="s">"\n"</span> <span class="o">+</span>
+ <span class="s">"</included>"</span><span class="o">;</span>
+
+<span class="n">registration</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">registerService</span><span class="o">(</span><span class="n">String</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span><span class="n">config</span><span class="o">,</span><span class="n">props</span><span class="o">);</span>
+</pre></div>
+
+
+<p>If the config needs to be updated just re-register the service and change would be picked up</p>
+<h4 id="exposing-fragment-as-configprovider-instance">Exposing fragment as ConfigProvider instance</h4>
+<p>Another way to provide config fragment is by providing an implementation of <code>org.apache.sling.commons.log.logback.ConfigProvider</code></p>
+<div class="codehilite"><pre><span class="nd">@Component</span>
+<span class="nd">@Service</span>
+<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ConfigProviderExample</span> <span class="kd">implements</span> <span class="n">ConfigProvider</span> <span class="o">{</span>
+ <span class="kd">public</span> <span class="n">InputSource</span> <span class="nf">getConfigSource</span><span class="o">()</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="k">new</span> <span class="nf">InputSource</span><span class="o">(</span><span class="n">getClass</span><span class="o">().</span><span class="na">getClassLoader</span><span class="o">().</span><span class="na">getResourceAsStream</span><span class="o">(</span><span class="s">"foo-config.xml"</span><span class="o">));</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<p>If the config changes then sending an event to <code>org/apache/sling/commons/log/RESET</code> would reset the Logback runtime</p>
+<div class="codehilite"><pre><span class="n">eventAdmin</span><span class="o">.</span><span class="na">sendEvent</span><span class="o">(</span><span class="k">new</span> <span class="n">Event</span><span class="o">(</span><span class="s">"org/apache/sling/commons/log/RESET"</span><span class="o">,</span><span class="k">new</span> <span class="n">Properties</span><span class="o">()));</span>
+</pre></div>
+
+
+<h3 id="external-config-file">External Config File</h3>
+<p>Logback can be configured with an external file. The file name can be specified through</p>
+<ol>
+<li>OSGi config - Look for config with name <code>Apache Sling Logging Configuration</code> and specify the path for
+ config file property</li>
+<li>OSGi Framework Properties - Logback supports also looks for file name with property name
+ <code>org.apache.sling.commons.log.configurationFile</code></li>
+</ol>
+<p>If you are providing an external config file then to support OSGi integration you would need to add following
+action entry</p>
+<div class="codehilite"><pre><span class="nt"><newRule</span> <span class="na">pattern=</span><span class="s">"*/configuration/osgi"</span>
+ <span class="na">actionClass=</span><span class="s">"org.apache.sling.commons.log.logback.OsgiAction"</span><span class="nt">/></span>
+<span class="nt"><newRule</span> <span class="na">pattern=</span><span class="s">"*/configuration/appender-ref-osgi"</span>
+ <span class="na">actionClass=</span><span class="s">"org.apache.sling.commons.log.logback.OsgiAppenderRefAction"</span><span class="nt">/></span>
+<span class="nt"><osgi/></span>
+</pre></div>
+
+
+<p>The <code>osgi</code> element enables the OSGi integration support</p>
+<h3 id="java-util-logging-jul-integration">Java Util Logging (JUL) Integration</h3>
+<p>The bundle also support <a href="http://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html">SLF4JBridgeHandler</a>. To enable JUL integration following two steps
+needs to be done. This features allows routing logging messages from JUL to the Logbback appenders</p>
+<ol>
+<li>Set framework property <code>org.apache.sling.commons.log.julenabled</code> to true</li>
+<li>
+<p>Set the <a href="http://logback.qos.ch/manual/configuration.html#LevelChangePropagator">LevelChangePropagator</a> in LogbackConfig</p>
+<p>:::xml
+<configuration>
+ <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
+ ...
+</configuration></p>
+</li>
+</ol>
+<h3 id="wzxhzdk11wzxhzdk12configuring-osgi-based-appenders-in-logback-config"><a name="config-override"></a>Configuring OSGi based appenders in Logback Config</h3>
+<p>So far Sling used to configure the appenders based on OSGi config. That mode only provide a very limited
+set to configuration options. To make use of other Logback features you can override the OSGi config
+from within the Logback config file. OSGi config based appenders are named based on the file name</p>
+<p>For example for following OSGi config</p>
+<div class="codehilite"><pre><span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">file</span><span class="p">=</span>"<span class="n">logs</span><span class="o">/</span><span class="n">error</span><span class="p">.</span><span class="nb">log</span>"
+<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">level</span><span class="p">=</span>"<span class="n">info</span>"
+<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">file</span><span class="p">.</span><span class="nb">size</span><span class="p">=</span>"<span class="s">'.'</span><span class="n">yyyy</span><span class="o">-</span><span class="n">MM</span><span class="o">-</span><span class="n">dd</span>"
+<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">file</span><span class="p">.</span><span class="n">number</span><span class="p">=</span><span class="n">I</span>"7"
+<span class="n">org</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">sling</span><span class="p">.</span><span class="n">commons</span><span class="p">.</span><span class="nb">log</span><span class="p">.</span><span class="n">pattern</span><span class="p">=</span>"<span class="p">{</span>0<span class="p">,</span><span class="n">date</span><span class="p">,</span><span class="n">dd</span><span class="p">.</span><span class="n">MM</span><span class="p">.</span><span class="n">yyyy</span> <span class="n">HH</span><span class="p">:</span><span class="n">mm</span><span class="p">:</span><span class="n">ss</span><span class="p">.</span><span class="n">SSS</span><span class="p">}</span> <span class="o">*</span><span class="p">{</span>4<span class="p">}</span><span class="o">*</span> <span class="p">[{</span>2<span class="p">}]</span> <span class="p">{</span>3<span class="p">}</span> <span class="p">{</span>5<span class="p">}</span>&quo
t;
+</pre></div>
+
+
+<p>The Logback appender would be named as <code>logs/error.log</code>. To extend/override the config in Logback config
+create an appender with name <code>logs/error.log</code></p>
+<div class="codehilite"><pre><span class="nt"><appender</span> <span class="na">name=</span><span class="s">"/logs/error.log"</span> <span class="na">class=</span><span class="s">"ch.qos.logback.core.FileAppender"</span><span class="nt">></span>
+ <span class="nt"><file></span>${sling.home}/logs/error.log<span class="nt"></file></span>
+ <span class="nt"><encoder></span>
+ <span class="nt"><pattern></span>%d %-5level %X{sling.userId:-NA} [%thread] %logger{30} %marker- %msg %n<span class="nt"></pattern></span>
+ <span class="nt"><immediateFlush></span>true<span class="nt"></immediateFlush></span>
+ <span class="nt"></encoder></span>
+<span class="nt"></appender></span>
+</pre></div>
+
+
+<p>In this case then Log module would create appender based on Logback config instead of OSGi config. This can
+be used to move the application from OSGi based config to Logback based config easily</p>
<h2 id="webconsole-plugin-enhancements">WebConsole Plugin enhancements</h2>
<p>The web Console Plugin supports following features</p>
<ul>
@@ -494,7 +494,7 @@ to <code>5</code> (which happens to be t
</ul>
<p><img src="sling-log-support.png" /></p>
<div class="timestamp" style="margin-top: 30px; font-size: 80%; text-align: right;">
- Rev. 1542739 by chetanm on Sun, 17 Nov 2013 14:43:57 +0000
+ Rev. 1542740 by chetanm on Sun, 17 Nov 2013 14:50:04 +0000
</div>
<div class="trademarkFooter">
Apache Sling, Sling, Apache, the Apache feather logo, and the Apache Sling project