openhab-docs/v2.2/developers/development/logging.html

323 lines
20 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--<link rel="shortcut icon" href="https://www.openhab.org/favicon.png"></link>-->
<title>Logging - openHAB 2 - Empowering the Smart Home</title>
<!-- CSS -->
<link type="text/css" rel="stylesheet" href="/v2.2/css/materialize.css" media="screen,projection" />
<link type="text/css" rel="stylesheet" href="/v2.2/css/pygments-jekyll-style.css" />
<link type="text/css" rel="stylesheet" href="/v2.2/css/styles.css" />
<link type="text/css" rel="stylesheet" href="/v2.2/css/openhab.css" />
<link type="text/css" rel="stylesheet" href="/v2.2/css/collapsible.css" />
<!-- Font -->
<link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:300,400,700" />
<link rel="canonical" href="https://docs.openhab.org/developers/development/logging.html" />
<script type="text/javascript">var gaProperty = 'UA-47717934-3';var disableStr = 'ga-disable-' + gaProperty;if (document.cookie.indexOf(disableStr + '=true') > -1) {window[disableStr] = true;}</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-47717934-3', 'auto');
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');
</script>
</head>
<body class="documentation">
<div id="header" class="navbar-fixed">
<nav role="navigation">
<div class="container">
<div class="nav-wrapper">
<a href="/v2.2/index.html"><img id="logo" src="/images/logo.png" /></a>
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
<ul class="right hide-on-med-and-down">
<li><a href="/tutorials/index.html">Tutorials</a></li>
<li><a href="/v2.2/introduction.html">User Manual</a></li>
<li><a href="/developers/index.html">Developer Guide</a></li>
<li><a target="_blank" href="https://community.openhab.org">Community Forum</a></li>
<li><a target="_blank" href="https://github.com/openhab">GitHub</a></li>
<li class="search"><i class="material-icons">search</i></li>
<li class="search">
<form method="GET" id="searchform" class="search-form" action="/search">
<input id="query" name="q" type="text" class="search-form-input" placeholder="search" />
</form>
</li>
</ul>
<ul id="nav-mobile" class="side-nav">
<li><a href="/v2.2/index.html">Home</a></li>
<li><a href="/tutorials/index.html">Tutorials</a></li>
<li><a href="/v2.2/introduction.html">User Manual</a></li>
<li><a href="/developers/index.html">Developer Guide</a></li>
<li><a target="_blank" href="https://community.openhab.org">Community Forum</a></li>
<li><a target="_blank" href="https://github.com/openhab">GitHub</a></li>
<li class="search">
<form method="GET" id="searchformmob" class="search-form" action="/search">
<input id="querymob" name="q" type="text" class="search-form-input" placeholder="search" />
</form>
</li>
</ul>
</div>
</div>
</nav>
</div>
<section id="documentation" class="text content-wrapper">
<div class="container">
<div class="side-nav-wrapper">
<ul class="nav">
<li><a href="/v2.2/developers">Overview</a></li>
<li><a href="/v2.2/developers/contributing/contributing">Contributing</a></li>
<li><a href="/v2.2/developers/prerequisites/osgi.html">Prerequisites</a>
<ul>
<li><a href="/v2.2/developers/prerequisites/osgi.html">OSGi</a>
<ul>
<li><a href="/v2.2/developers/prerequisites/osgi.html">Overview</a></li>
<li><a href="/v2.2/developers/prerequisites/osgids.html">Declarative Services</a></li>
<li><a href="/v2.2/developers/prerequisites/configadmin.html">Configuration Admin</a></li>
<li><a href="/v2.2/developers/prerequisites/osgitasks.html">Coding tasks</a></li>
<li><a href="/v2.2/developers/prerequisites/eventadmin.html">Event Admin</a></li>
</ul>
</li>
<li><a href="/v2.2/developers/prerequisites/tycho.html">Tycho</a></li>
<li><a href="/v2.2/developers/prerequisites/equinox.html">Equinox</a></li>
<li><a href="/v2.2/developers/prerequisites/targetplatform.html">Target Platform</a></li>
</ul>
</li>
<li><a href="/v2.2/developers/development/ide.html">Basics</a>
<ul>
<li><a href="/v2.2/developers/development/ide.html">IDE Setup</a></li>
<li><a href="/v2.2/developers/development/guidelines.html">Code Guidelines</a></li>
<li><a href="/v2.2/developers/development/bindings.html">Developing Bindings</a></li>
<li><a href="/v2.2/developers/development/logging.html">Logging</a></li>
</ul>
</li>
<li><a href="/v2.2/developers/development/evolution.html">Migration from 1.x</a>
<ul>
<li><a href="/v2.2/developers/development/evolution.html">Technical Differences</a></li>
<li><a href="/v2.2/developers/development/compatibilitylayer.html">Compatibility Layer</a></li>
</ul>
</li>
</ul>
</div>
<div class="content">
<h1 id="logging">Logging</h1>
<h2 id="introduction">Introduction</h2>
<p>During development you might want to change the logging configuration in order to debug your application and the underlying framework or services.</p>
<p>openHAB is using a combination of the Simple Logging Facade for Java (<a href="http://www.slf4j.org/">slf4j</a>) and a <a href="http://logback.qos.ch/">logback</a> implementation. In this page we will give a few tips on how you can use and configure the logger to suit your needs.</p>
<h2 id="set-up-logging">Set up Logging</h2>
<p>In order to enable logging in your run configuration, you have to add the following bundles to the runtime configuration:</p>
<ul>
<li>org.slf4j.api;</li>
<li>ch.qos.logback.classic;</li>
<li>ch.qos.logback.core;</li>
<li>ch.qos.logback.slf4j.</li>
</ul>
<p>In your bundle, you will depend only on the <code class="highlighter-rouge">org.slf4j</code> package, so add it as a dependency in the <code class="highlighter-rouge">Import-Package</code> header of the <code class="highlighter-rouge">MANIFEST.MF</code> file.</p>
<p>You can use a logger the following way:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">org.slf4j.Logger</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.slf4j.LoggerFactory</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span>
<span class="kd">static</span> <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="k">this</span><span class="o">.</span><span class="na">getClass</span><span class="o">());</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Hello World"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="logback-configuration-file">Logback Configuration File</h2>
<p>If we have setup the logging by just adding the bundles above we will end up in a logging with default configuration. In order to define custom logging configuration we can prepare a logging configuration file.</p>
<p>The configuration file for openHAB is placed in the <a href="https://github.com/openhab/openhab-distro/blob/fa20ddb3555873ea98fe9fc5a5c0c28bf33003d5/launch/home/logback_debug.xml">openhab-distro/lauch/home/logback_debug.xml</a> file. We have added a few comments on this file in order to attract your attention on some significant points:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;configuration</span> <span class="na">scan=</span><span class="s">"true"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- This is the appender that displays the logging on the console --&gt;</span>
<span class="nt">&lt;appender</span> <span class="na">name=</span><span class="s">"STDOUT"</span> <span class="na">class=</span><span class="s">"ch.qos.logback.core.ConsoleAppender"</span><span class="nt">&gt;</span>
<span class="nt">&lt;encoder&gt;</span>
<span class="c">&lt;!-- This pattern will display the time, the log level, the name of the logger and the log message --&gt;</span>
<span class="nt">&lt;pattern&gt;</span>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%-30.30logger{36}:%-5line] - %msg%ex{10}%n<span class="nt">&lt;/pattern&gt;</span>
<span class="nt">&lt;/encoder&gt;</span>
<span class="nt">&lt;/appender&gt;</span>
<span class="c">&lt;!-- Another appender that logs into a file --&gt;</span>
<span class="nt">&lt;appender</span> <span class="na">name=</span><span class="s">"FILE"</span> <span class="na">class=</span><span class="s">"ch.qos.logback.core.FileAppender"</span><span class="nt">&gt;</span>
<span class="nt">&lt;file&gt;</span>${openhab.logdir:-userdata/logs}/openhab.log<span class="nt">&lt;/file&gt;</span>
<span class="nt">&lt;encoder&gt;</span>
<span class="nt">&lt;pattern&gt;</span>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%-30.30logger{36}:%-5line] - %msg%ex{10}%n<span class="nt">&lt;/pattern&gt;</span>
<span class="nt">&lt;/encoder&gt;</span>
<span class="nt">&lt;/appender&gt;</span>
<span class="c">&lt;!-- We have removed part of the original file in this example --&gt;</span>
...
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"smarthome.event"</span> <span class="na">level=</span><span class="s">"INFO"</span> <span class="na">additivity=</span><span class="s">"false"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- The element &lt;logger&gt; may contain zero or more &lt;appender-ref&gt; elements --&gt;</span>
<span class="nt">&lt;appender-ref</span> <span class="na">ref=</span><span class="s">"EVENTFILE"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;appender-ref</span> <span class="na">ref=</span><span class="s">"STDOUT"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/logger&gt;</span>
<span class="c">&lt;!-- Logback uses inheritance to determine the log level.
If a given logger is NOT assigned a level it inherits one from the its closest ancestor --&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"org.openhab"</span> <span class="na">level=</span><span class="s">"DEBUG"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"org.eclipse.smarthome"</span> <span class="na">level=</span><span class="s">"DEBUG"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"org.eclipse.jetty"</span> <span class="na">level=</span><span class="s">"INFO"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"org.jupnp"</span> <span class="na">level=</span><span class="s">"ERROR"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"javax.jmdns"</span> <span class="na">level=</span><span class="s">"OFF"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"javax.jmdns.impl"</span> <span class="na">level=</span><span class="s">"OFF"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"javax.jmdns.impl.constants"</span> <span class="na">level=</span><span class="s">"OFF"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"tuwien.auto.calimero"</span> <span class="na">level=</span><span class="s">"WARN"</span> <span class="nt">/&gt;</span>
<span class="c">&lt;!-- The root logger is at the top of the logger hierarchy.
All loggers inherit its level, if there are no ancestors
between the root and the logger --&gt;</span>
<span class="nt">&lt;root</span> <span class="na">level=</span><span class="s">"INFO"</span><span class="nt">&gt;</span>
<span class="nt">&lt;appender-ref</span> <span class="na">ref=</span><span class="s">"FILE"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;appender-ref</span> <span class="na">ref=</span><span class="s">"STDOUT"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/root&gt;</span>
<span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"OSGi"</span> <span class="na">level=</span><span class="s">"OFF"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/configuration&gt;</span>
</code></pre></div></div>
<p>If you are not aware of the different <a href="http://logback.qos.ch/manual/architecture.html#effectiveLevel">log levels</a>, <a href="http://logback.qos.ch/manual/appenders.html">appenders</a> and <a href="http://logback.qos.ch/manual/configuration.html#loggerElement">logger elements</a>, you might want to take a look at the links to the the logback documentation.</p>
<p>If you want to change the loggers configuration, you might change the content of this file, but a better approach will be to make a copy of this file and apply the changes in the new file.</p>
<p>The path to the logging file is passed as an argument to the JVM, so if you want to use different configuration file, you have to change the property <code class="highlighter-rouge">-Dlogback.configurationFile</code> with the path to the new file in the run configuration that you are using.</p>
<h2 id="configuration">Configuration</h2>
<p>There are several things, that you might want to change in the configuration:</p>
<ul>
<li>the log level for a logger;</li>
<li>the pattern of an appender;</li>
<li>redirect the log to a text file.</li>
</ul>
<h3 id="setting-up-the-log-level">Setting up the Log Level</h3>
<p>As you can see from the example configuration file above, the level for jUPnP is set to ERROR. If you develop a binding that is using jUPnP, you might want to see more logs on your console. You can simply change the log level to TRACE or DEBUG:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"org.jupnp"</span> <span class="na">level=</span><span class="s">"TRACE"</span><span class="nt">/&gt;</span>
</code></pre></div></div>
<h3 id="changing-the-pattern-of-an-appender">Changing the Pattern of an Appender</h3>
<p>Another useful option is to change the pattern of an appender. This pattern defines what information will be logged. The logback logger provides many <a href="http://logback.qos.ch/manual/layouts.html#conversionWord">predefined conversation words</a> for the most common use cases. Use the most appropriate ones for your specific case. For the purpose of exploring and debugging multi threaded applications you might need to see which thread has generated certain log event. In order to see this in the logs, you have to add the conversion word <code class="highlighter-rouge">t</code> to the pattern above:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;pattern&gt;</span>%t %d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%-30.30logger{36}:%-5line] - %msg%ex{10}%n<span class="nt">&lt;/pattern&gt;</span>
</code></pre></div></div>
<h3 id="redirect-the-log-to-a-text-file">Redirect the Log to a Text File</h3>
<p>You might want to redirect your log to a text file. This gives you the flexibility to search easier for a specific log or to save your logs. If you have looked at the <a href="#logback-configuration-file">default configuration file</a> you might have noticed that several appenders are listed there. The process of redirecting the log to a text file is as simple as :</p>
<ul>
<li>adding a new <code class="highlighter-rouge">FileAppender</code> and specifying the path of the output file:</li>
</ul>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;appender</span> <span class="na">name=</span><span class="s">"YOUR_APPENDER_NAME"</span> <span class="na">class=</span><span class="s">"ch.qos.logback.core.FileAppender"</span><span class="nt">&gt;</span>
<span class="nt">&lt;file&gt;</span>relative/path/to/file.log<span class="nt">&lt;/file&gt;</span>
<span class="nt">&lt;encoder&gt;</span>
<span class="c">&lt;!--Pick up a pattern that will log the information taht you will need --&gt;</span>
<span class="nt">&lt;pattern&gt;</span>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%-30.30logger{36}:%-5line] - %msg%ex{10}%n<span class="nt">&lt;/pattern&gt;</span>
<span class="nt">&lt;/encoder&gt;</span>
<span class="nt">&lt;/appender&gt;</span>
</code></pre></div></div>
<ul>
<li>adding your logger, setting up the log level and adding <code class="highlighter-rouge">appender-ref</code> element to the logger element. For this example we will assume that you want to add the following logger with the name <code class="highlighter-rouge">com.logger.example</code>:</li>
</ul>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;logger</span> <span class="na">name=</span><span class="s">"com.logger.example"</span> <span class="na">level=</span><span class="s">"INFO"</span><span class="nt">&gt;</span>
<span class="nt">&lt;appender-ref</span> <span class="na">ref=</span><span class="s">"YOUR_APPENDER_NAME"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/logger&gt;</span>
</code></pre></div></div>
<h2 id="further-reading">Further Reading</h2>
<ul>
<li><a href="http://www.slf4j.org/">http://www.slf4j.org/</a></li>
<li><a href="http://logback.qos.ch/">http://logback.qos.ch/</a></li>
<li><a href="http://www.slf4j.org/manual.html">http://www.slf4j.org/manual.html</a></li>
<li><a href="http://stackoverflow.com/questions/6699537/how-to-use-multiple-configurations-with-logback-in-a-single-project">http://stackoverflow.com/questions/6699537/how-to-use-multiple-configurations-with-logback-in-a-single-project</a></li>
</ul>
</div>
</div>
</section>
<footer>
<div class="container">
<div class="row">
<div class="col s12 m7">
Copyright &copy; 2017 by the <a href="https://github.com/openhab">openHAB Community</a> and the <a href="http://www.openhabfoundation.org/">openHAB&nbsp;Foundation&nbsp;e.V.</a>
</div>
<div class="col s12 m5">
<ul class="list-inline right-align">
<li><a href="/imprint.html">Imprint</a></li>
<li><a href="/privacy.html">Privacy Policy</a></li>
<li><a href="http://www.openhab.org">openHAB Website</a></li>
<li><a href=# onclick="printPage()">Print This Page</a></li>
</ul>
</div>
</div>
</div>
</footer>
<script src="/v2.2/js/jquery.min.js"></script>
<script src="/v2.2/js/jquery.scrollme.min.js"></script>
<script src="/v2.2/js/jquery.sticky.js"></script>
<script src="/v2.2/js/materialize.min.js"></script>
<script src="/v2.2/js/init.js"></script>
<script src="/v2.2/js/functions.js"></script>
</body>
</html>
<script>
var host = "docs.openhab.org";
if (!(window.location.host.startsWith("127.0.0.1")) && (host == window.location.host) && (window.location.protocol != "https:"))
window.location.protocol = "https";
</script>