blob: a238ece9296f0d30e93827bb40a61d8183de9056 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<head>
<title>Apache Felix - Apache Felix Log</title>
<link rel="icon" href="/res/favicon.ico">
<link rel="stylesheet" href="/res/site.css" type="text/css" media="all">
<link rel="stylesheet" href="/res/codehilite.css" type="text/css" media="all">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
<div class="title">
<div class="logo">
<a href="https://felix.apache.org/">
<img border="0" alt="Apache Felix" src="/res/logo.png">
</a>
</div>
<div class="header">
<a href="https://www.apache.org/">
<img border="0" alt="Apache" src="/res/apache.png">
</a>
</div>
</div>
<div class="menu">
<style type="text/css">
/* The following code is added by mdx_elementid.py
It was originally lifted from http://subversion.apache.org/style/site.css */
/*
* Hide class="elementid-permalink", except when an enclosing heading
* has the :hover property.
*/
.headerlink, .elementid-permalink {
visibility: hidden;
}
h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
<p><a href="/news.html">News</a> <br />
<a href="/license.html">License</a> <br />
<a href="/downloads.cgi">Downloads</a> <br />
<a href="/documentation.html">Documentation</a> <br />
<a href="/documentation/community/project-info.html">Project Info</a> <br />
<a href="/documentation/community/contributing.html">Contributing</a> <br />
<a href="/sitemap.html">Site Map</a> <br />
<a href="https://www.apache.org/">ASF</a> <br />
<a href="https://www.apache.org/security/">Security</a> <br />
<a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a> <br />
<a href="https://www.apache.org/foundation/thanks.html">Sponsors</a> </p>
<iframe
src="https://www.apache.org/ads/button.html"
style="border-width:0; float: left"
frameborder="0"
scrolling="no"
width="135"
height="135">
</iframe>
</div>
<div class="main">
<div class="breadcrump" style="font-size: 80%;">
<a href="/">Home</a>&nbsp;&raquo&nbsp;<a href="/documentation.html">Documentation</a>
</div>
<h1>Apache Felix Log</h1>
<style type="text/css">
/* The following code is added by mdx_elementid.py
It was originally lifted from http://subversion.apache.org/style/site.css */
/*
* Hide class="elementid-permalink", except when an enclosing heading
* has the :hover property.
*/
.headerlink, .elementid-permalink {
visibility: hidden;
}
h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
<p>The <a href="https://osgi.org/specification/osgi.cmpn/7.0.0/">OSGi Service Compendium specification</a> defines a general purpose <a href="https://osgi.org/specification/osgi.cmpn/7.0.0/service.log.html">Log Service</a> for the OSGi Platform. It is a very simple specification that doesn't provide all the functionality commonly available in enterprise-level logging tools, but its extensible service model can be used to build fairly sophisticated logging solutions.</p>
<p>The Log Service specification defines the following entities:</p>
<ul>
<li><em><code>org.osgi.service.log.Logger</code></em> - (<em>since 1.4</em>) interface that allows a bundle to log information, including a message, a level, an exception, and a <code>ServiceReference</code> object. The formatting style using <code>{}</code> placeholders follows the <em>slf4j</em> approach. A derivative of <code>Logger</code> called <code>FormatterLogger</code> uses the <code>java.util.Formatter</code> syntax.</li>
<li><em><code>org.osgi.service.log.LoggerFactory</code></em> - (<em>since 1.4</em>) service interface that allows a bundle to obtain a Logger. A Logger is named and associated with a <code>Bundle</code> object.</li>
<li><em><code>org.osgi.service.log.admin.LoggerContext</code></em> - (<em>since 1.4</em>) interface that allows the configuration of effective logging levels for a Bundle. The configuration can be set in Configuration Admin and via method calls.</li>
<li><em><code>org.osgi.service.log.admin.LoggerAdmin</code></em> - (<em>since 1.4</em>) interface for managing the configuration of log levels.</li>
<li><em><code>org.osgi.service.log.LogService</code></em> - <em>legacy</em> service interface that allows a bundle to log information, including a message, a level, an exception, a <code>ServiceReference</code> object, and a <code>Bundle</code> object. The methods of this service are deprecated and it is recommended to use LoggerFactory and Loggers instead.</li>
<li><em><code>org.osgi.service.log.LogReaderService</code></em> - service interface that allows access to a list of recent <code>LogEntry</code> objects, and allows the registration of a <code>LogListener</code> object that receives <code>LogEntry</code> objects as they are created.</li>
<li><em><code>org.osgi.service.log.LogEntry</code></em> - interface defining a log entry.</li>
<li><em><code>org.osgi.service.log.LogListener</code></em> - interface defining a listener for log entries, which is notified about new log entries.</li>
</ul>
<h2 id="accessing-loggers">Accessing Loggers<a class="headerlink" href="#accessing-loggers" title="Permanent link">&para;</a></h2>
<p>Loggers are obtained through the <code>LoggerFactory</code> service:</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Activator</span> <span class="kd">implements</span> <span class="n">BundleActivator</span>
<span class="o">{</span>
<span class="kd">private</span> <span class="kd">volatile</span> <span class="n">LoggerFactory</span> <span class="n">loggerFactory</span><span class="o">;</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">start</span><span class="o">(</span><span class="n">BundleContext</span> <span class="n">context</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span>
<span class="o">{</span>
<span class="n">ServiceReference</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getServiceReference</span><span class="o">(</span><span class="n">LoggerFactory</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">if</span> <span class="o">(</span><span class="n">ref</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">loggerFactory</span> <span class="o">=</span> <span class="o">(</span><span class="n">LoggerFactory</span><span class="o">)</span> <span class="n">context</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">ref</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">//..</span>
</pre></div>
<p>Elsewhere in the bundle you can then use the <code>LoggerFactory</code> to get a <code>Logger</code> for any class:</p>
<div class="codehilite"><pre><span class="n">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="n">loggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">Foo</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
</pre></div>
<p>Declarative Services (<em>since 1.4</em>) has a convenient integration which allows a component to obtain a logger specific to it's class with little effort by using a reference who's service type is <code>LoggerFactory</code> while the injection type is either <code>Logger</code> or <code>FormatterLogger</code>:</p>
<div class="codehilite"><pre><span class="nd">@Reference</span><span class="o">(</span><span class="n">service</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">Logger</span> <span class="n">logger</span><span class="o">;</span>
</pre></div>
<p>The <code>Logger</code> interface defines 6 levels of logging to coincide with most other log APIs:</p>
<ul>
<li>AUDIT</li>
<li>ERROR</li>
<li>WARN</li>
<li>INFO</li>
<li>DEBUG</li>
<li>TRACE</li>
</ul>
<p>Each level has methods on the Logger interface appropriate to that level such as <code>.info(...)</code> and <code>.isInfoEnabled()</code>.</p>
<h2 id="configuring-log-levels">Configuring Log Levels<a class="headerlink" href="#configuring-log-levels" title="Permanent link">&para;</a></h2>
<p>Since 1.4 the <strong>Log Service Specification</strong> provides the ability to manage the log levels both programatically and through <strong>Configuration Admin</strong>.</p>
<p>Programatic configuration is achieved through the <code>LoggerAdmin</code> service:</p>
<div class="codehilite"><pre><span class="n">ServiceReference</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getServiceReference</span><span class="o">(</span>
<span class="n">LoggerAdmin</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">if</span> <span class="o">(</span><span class="n">ref</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">LoggerAdmin</span> <span class="n">loggerAdmin</span> <span class="o">=</span> <span class="o">(</span><span class="n">LoggerAdmin</span><span class="o">)</span> <span class="n">context</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">ref</span><span class="o">);</span>
<span class="c1">// get the ROOT logger context</span>
<span class="n">LoggerContext</span> <span class="n">rootContext</span> <span class="o">=</span> <span class="n">loggerAdmin</span><span class="o">.</span><span class="na">getLoggerContext</span><span class="o">(</span><span class="kc">null</span><span class="o">);</span>
<span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">LogLevel</span><span class="o">&gt;</span> <span class="n">levels</span> <span class="o">=</span> <span class="n">rootContext</span><span class="o">.</span><span class="na">getLogLevels</span><span class="o">();</span>
<span class="c1">// adjust the levels</span>
<span class="n">rootContext</span><span class="o">.</span><span class="na">setLogLevels</span><span class="o">(</span><span class="n">levels</span><span class="o">);</span>
<span class="c1">// get the levels for a bundle (felix scr in this case)</span>
<span class="n">LoggerContext</span> <span class="n">scrContext</span> <span class="o">=</span> <span class="n">loggerAdmin</span><span class="o">.</span><span class="na">getLoggerContext</span><span class="o">(</span>
<span class="s">&quot;org.apache.felix.scr&quot;</span><span class="o">);</span>
<span class="c1">// set all of scr to DEBUG mode</span>
<span class="n">scrContext</span><span class="o">.</span><span class="na">setLogLevels</span><span class="o">(</span>
<span class="n">Collections</span><span class="o">.</span><span class="na">singletonMap</span><span class="o">(</span>
<span class="n">Logger</span><span class="o">.</span><span class="na">ROOT_LOGGER_NAME</span><span class="o">,</span> <span class="n">LogLevel</span><span class="o">.</span><span class="na">DEBUG</span><span class="o">));</span>
<span class="o">}</span>
</pre></div>
<p>Likewise logging configuration can be handled through <strong>Configuration Admin</strong>. Following the previous example of configuring <strong>Felix SCR</strong> for <code>DEBUG</code> mode:</p>
<ul>
<li>create a configuration object whose PID is <em><code>org.osgi.service.log.admin|org.apache.felix.scr</code></em></li>
<li>set the property <code>ROOT</code> in the configuration to <code>DEBUG</code>
e.g. <code>ROOT=DEBUG</code></li>
</ul>
<h2 id="accessing-the-log-service-legacy">Accessing the log service (legacy)<a class="headerlink" href="#accessing-the-log-service-legacy" title="Permanent link">&para;</a></h2>
<p>To access a <code>LogService</code> instance it is necessary to look it up in the OSGi service registry as demonstrated in the following code snippet:</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Activator</span> <span class="kd">implements</span> <span class="n">BundleActivator</span>
<span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">start</span><span class="o">(</span><span class="n">BundleContext</span> <span class="n">context</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span>
<span class="o">{</span>
<span class="n">ServiceReference</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getServiceReference</span><span class="o">(</span><span class="n">LogService</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">if</span> <span class="o">(</span><span class="n">ref</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">LogService</span> <span class="n">log</span> <span class="o">=</span> <span class="o">(</span><span class="n">LogService</span><span class="o">)</span> <span class="n">context</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">ref</span><span class="o">);</span>
<span class="c1">// Use the log...</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">//..</span>
</pre></div>
<p>It is possible, and advisable, to use more sophisticated service acquisition mechanisms like a Service Tracker, Declarative Services or iPOJO.</p>
<h2 id="using-the-log-service-legacy">Using the log service (legacy)<a class="headerlink" href="#using-the-log-service-legacy" title="Permanent link">&para;</a></h2>
<p>The <code>LogService</code> interface provides four methods for logging:</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">LogService</span>
<span class="o">{</span>
<span class="c1">//..</span>
<span class="c1">// Log a message specifying a log level</span>
<span class="kd">public</span> <span class="nf">log</span><span class="o">(</span><span class="kt">int</span> <span class="n">level</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">String</span> <span class="n">message</span><span class="o">)</span>
<span class="c1">// Log an exception</span>
<span class="kd">public</span> <span class="nf">log</span><span class="o">(</span><span class="kt">int</span> <span class="n">level</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">String</span> <span class="n">message</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Throwable</span> <span class="n">exception</span><span class="o">)</span>
<span class="c1">// Log a message specifying the ServiceReference that generated it</span>
<span class="kd">public</span> <span class="nf">log</span><span class="o">(</span><span class="n">ServiceReference</span> <span class="n">sr</span><span class="o">,</span> <span class="kt">int</span> <span class="n">level</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">String</span> <span class="n">message</span><span class="o">)</span>
<span class="c1">// Log a message specifying the ServiceReference and exception</span>
<span class="kd">public</span> <span class="nf">log</span><span class="o">(</span><span class="n">ServiceReference</span> <span class="n">sr</span><span class="o">,</span> <span class="kt">int</span> <span class="n">level</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">String</span> <span class="n">message</span><span class="o">,</span> <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">Throwable</span> <span class="n">exception</span><span class="o">)</span>
<span class="o">}</span>
</pre></div>
<p>Log levels are defined in the same interface:</p>
<ul>
<li><code>LogService.LOG_DEBUG</code></li>
<li><code>LogService.LOG_INFO</code></li>
<li><code>LogService.LOG_WARNING</code></li>
<li><code>LogService.LOG_ERROR</code></li>
</ul>
<h2 id="retrieving-log-entries">Retrieving log entries<a class="headerlink" href="#retrieving-log-entries" title="Permanent link">&para;</a></h2>
<p>The <code>LogReaderService</code> provides a <code>getLog()</code> method to retrieve an <code>Enumeration</code> of the latest log entries. The following code snippets demonstrates how to retrieve it from the service registry and use it:</p>
<div class="codehilite"><pre><span class="n">ServiceReference</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getServiceReference</span><span class="o">(</span><span class="n">LogReaderService</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">if</span> <span class="o">(</span><span class="n">ref</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">LogReaderService</span> <span class="n">reader</span> <span class="o">=</span> <span class="o">(</span><span class="n">LogReaderService</span><span class="o">)</span> <span class="n">context</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">ref</span><span class="o">);</span>
<span class="n">Enumeration</span><span class="o">&lt;</span><span class="n">LogEntry</span><span class="o">&gt;</span> <span class="n">latestLogs</span> <span class="o">=</span> <span class="n">reader</span><span class="o">.</span><span class="na">getLog</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<h2 id="creating-and-registering-a-loglistener">Creating and registering a <code>LogListener</code><a class="headerlink" href="#creating-and-registering-a-loglistener" title="Permanent link">&para;</a></h2>
<p>The Log Service specification doesn't define any particular entity to store, display, or write log entries; it's up to the developer to implement this functionality or to choose an available implementation capable of doing that. To create such a bundle, the first step is to create an implementation of the <code>LogListener</code> interface. The following code shows a simple implementation that echoes the log message:</p>
<div class="codehilite"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">LogWriter</span> <span class="kd">implements</span> <span class="n">LogListener</span>
<span class="o">{</span>
<span class="c1">// Invoked by the log service implementation for each log entry</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">logged</span><span class="o">(</span><span class="n">LogEntry</span> <span class="n">entry</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">entry</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>The only method to implement is <code>logged()</code> method, which is called every time a log entry is created in the associated logging service. A <code>LogListener</code> implementation must be registered with the <code>LogReaderService</code> so it can start receiving log entries, as demonstrated in the following code snippet:</p>
<div class="codehilite"><pre><span class="n">ServiceReference</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getServiceReference</span><span class="o">(</span><span class="n">LogReaderService</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">if</span> <span class="o">(</span><span class="n">ref</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="o">{</span>
<span class="n">LogReaderService</span> <span class="n">reader</span> <span class="o">=</span> <span class="o">(</span><span class="n">LogReaderService</span><span class="o">)</span> <span class="n">context</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">ref</span><span class="o">);</span>
<span class="n">reader</span><span class="o">.</span><span class="na">addLogListener</span><span class="o">(</span><span class="k">new</span> <span class="n">LogWriter</span><span class="o">());</span>
<span class="o">}</span>
</pre></div>
<h2 id="setup-of-apache-felix-log-service">Setup of Apache Felix Log Service<a class="headerlink" href="#setup-of-apache-felix-log-service" title="Permanent link">&para;</a></h2>
<p>The Apache Felix Log Service bundle doesn't have any specific dependency on Felix, so it can run on any OSGi container. For its configuration, it will use the following optional system properties:</p>
<table class="table">
<thead>
<tr>
<th>Property</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>org.apache.felix.log.maxSize</code></td>
<td>100</td>
<td>The maximum size of the log history. A value of -1 means the log has no maximum size; a value of 0 means that no historical information is maintained</td>
</tr>
<tr>
<td><code>org.apache.felix.log.storeDebug</code></td>
<td>false</td>
<td>Determines whether or not debug messages will be stored in the history</td>
</tr>
<tr>
<td><code>org.osgi.service.log.admin.loglevel</code></td>
<td><code>WARN</code></td>
<td>The default log level of the root Logger Context</td>
</tr>
</tbody>
</table>
<div class="timestamp" style="margin-top: 30px; font-size: 80%; text-align: right;">
Rev. 1835843 by rotty3000 on Fri, 13 Jul 2018 14:37:22 +0000
</div>
<div class="trademarkFooter">
Apache Felix, Felix, Apache, the Apache feather logo, and the Apache Felix project
logo are trademarks of The Apache Software Foundation. All other marks mentioned
may be trademarks or registered trademarks of their respective owners.
</div>
</div>
</body>
</html>