<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jayway Team Blog &#187; logging</title>
	<atom:link href="http://blog.jayway.com/tag/logging/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jayway.com</link>
	<description>Sharing Experience</description>
	<lastBuildDate>Sat, 11 Feb 2012 10:33:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A nice, basic log4net setup</title>
		<link>http://blog.jayway.com/2011/06/13/a-nice-basic-log4net-setup/</link>
		<comments>http://blog.jayway.com/2011/06/13/a-nice-basic-log4net-setup/#comments</comments>
		<pubDate>Mon, 13 Jun 2011 21:26:26 +0000</pubDate>
		<dc:creator>Andreas Hammar</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[log4net]]></category>
		<category><![CDATA[logging]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=8768</guid>
		<description><![CDATA[In my current project I have need for quite a bit of logging. I’ve never used log4net before so I thought it was about time. Log4net has been around for ages, and is very well documented in the log4net documentation, and explained very nicely in e.g. Jim Christopher’s log4net tutorials. What I plan to show [...]]]></description>
			<content:encoded><![CDATA[<p>In my current project I have need for quite a bit of logging. I’ve never used log4net before so I thought it was about time. Log4net has been around for ages, and is very well documented in the <a href="http://logging.apache.org/log4net/index.html">log4net documentation</a>, and explained very nicely in e.g. <a href="http://www.beefycode.com/?tag=/log4net">Jim Christopher’s log4net tutorials</a>. What I plan to show you here is my findings in setting up my logging solution. What I wanted was couple of different log files for different severity levels, and here’s my story how I did it. I’m sure you can do more clever tricks that what I’ve done here, please contact me or share your knowledge in the comments if you have tips or thoughts on improvements.</p>
<h2></h2>
<h2>Summary</h2>
<p>I used…</p>
<ul>
<li>FileAppender+MinimalLock to be able to read the log file while the system is running </li>
<li>three Appenders one each for minimum LogLevel: debug, info and warning </li>
<li>one logger per class – gave me a readable “tag” on each log item, but filtering problems with nhibernate </li>
<li>an LoggerMatchFilter for nhibernate with AcceptOnMatch=false to reject messages </li>
</ul>
<p>&#160;</p>
<h2>Getting started</h2>
<p>To get any logging at all, you need to create a logger and configure it. The code for doing this and writing something to the log looks like this:</p>
<pre class="brush: csharp;">log4net.Config.XmlConfigurator.Configure();
var log = log4net.LogManager.GetLogger(this.GetType());
log.Debug(“debug message”);</pre>
<p>(Yes, it’s not a typo – the namespace is lowercase, I know it’s hard, by try to ignore that…)</p>
<p>Those few lines of course require configuration, the app/web.config is a good place for that so let’s go there now. The config needs three parts; a configSections entry, a log4net appender and a log4net root directive. See for yourself:</p>
<pre class="brush: xml;">&lt;configuration&gt;
  &lt;configSections&gt;
    &lt;section name=&quot;log4net&quot; type=&quot;log4net.Config.Log4NetConfigurationSectionHandler, log4net&quot;/&gt;
  &lt;/configSections&gt;
  &lt;log4net&gt;
    &lt;appender name=&quot;RollingFileAppenderAll&quot; type=&quot;log4net.Appender.RollingFileAppender&quot;&gt;
      &lt;file value=&quot;c:\logs\projectx_log_debug.txt&quot; /&gt;
      &lt;appendToFile value=&quot;true&quot; /&gt;
      &lt;rollingStyle value=&quot;Composite&quot; /&gt;
      &lt;datePattern value=&quot;.yyyyMMdd&quot; /&gt;
      &lt;maxSizeRollBackups value=&quot;10&quot; /&gt;
      &lt;maximumFileSize value=&quot;1MB&quot; /&gt;
      &lt;staticLogFileName value=&quot;true&quot; /&gt;
      &lt;lockingModel type=&quot;log4net.Appender.FileAppender+MinimalLock&quot; /&gt;
      &lt;layout type=&quot;log4net.Layout.Pattern Layout&quot;&gt;
        &lt;conversionPattern value=&quot;%date [%thread] %-6level %logger - %message %exception%newline&quot; /&gt;
      &lt;/layout&gt;
      &lt;filter type=&quot;log4net.Filter.LoggerMatchFilter&quot;&gt;
        &lt;loggerToMatch value=&quot;Jayway.ProjectX&quot; /&gt;
      &lt;/filter&gt;
      &lt;filter type=&quot;log4net.Filter.DenyAllFilter&quot; /&gt;
    &lt;/appender&gt;
    &lt;root&gt;
      &lt;level value=&quot;ALL&quot; /&gt;
      &lt;appender-ref ref=&quot;RollingFileAppenderAll&quot; /&gt;
    &lt;/root&gt;
  &lt;/log4net&gt;</pre>
<h2>Appender</h2>
<p>The appender entry represents a consumer of the logging information. Here I use a <em>RollingFileAppender</em> which rotates the log file periodically, as specified by the <em>datePattern</em>. <em>MaximumFileSize</em> is also honored and breaking that limit also rolls the log file over.</p>
<p>The logging in my project is done from a WCF service with HTTP endpoints. I have testing endpoints (e.g. /log/debug) that just shows the latest log file – very handy. To be able to read from the log file while the service is running, the <em>lockingModel</em> has to be set to <em>FileAppender+MinimalLock </em>which tells log4net to lock the log file as little as possible, instead of all the time which is the default. This will create a performance hit for the logging, but that’s ok for my setup. Specifying a <em>staticLogFileName</em> causes log4net to always log to a specific file, and then rename older log files according to date etc. This allows my hand coded log reader to always know where the latest log info is.</p>
<h2>Root</h2>
<p>The root section is what connects a log consumer (the appender) with a log producer (the ILog in the code). The root section can be replaced by specifying a specific logger (&lt;logger name=”myLogger”&gt;), and that would only process log data from that specific logger. Which logger to process data from brings us to the next topic – filtering.</p>
<h2>Filtering (and getting rid of nhibernate output)</h2>
<p>As you probably know, logs can either say to little, just about right, or WAY too much – that’s where the power of filtering comes in. <em>LogLevel</em> is the most natural and direct thing to filter on. In my service, I have three different log files all set to different levels; one for everything, one for at least <em>Info</em> and one for at least <em>Warning</em>. This is done by having three different appender entries and three appender rows in the <em>root</em> entry. This is where I started bumping into problems, read on…</p>
<h3>One logger per class</h3>
<p>I followed the advice from <a href="http://www.beefycode.com/post/Log4Net-Recommended-Practices-pt-1-Your-Code.aspx">Jim’s log4net recommended practices</a> to create one logger per class – not to use one logger for the entire application. The theory behind this is to have a tag on each log entry allowing you to have a log that “reads like a novel”. I like the idea and it’s very nice to always know what class issued the statement. Here’s an example of log output:</p>
<pre class="brush: csharp;">10:24:57,830 [10] INFO   Jayway.ProjectX.Service - ping called
10:24:57,833 [10] WARN   Jayway.ProjectX.Proxy - ping called
10:28:03,084 [10] INFO   Jayway.ProjectX.RequestCreator - creating request
10:28:03,095 [10] INFO   Jayway.ProjectX.Proxy - sending request
10:28:03,097 [10] WARN   Jayway.ProjectX.Proxy - could not reach host
10:28:03,907 [10] INFO   Jayway.Common.Cache - getting items from cache
10:28:03,910 [10] INFO   Jayway.ProjectX.Proxy - returning cache items
10:28:28,816 [10] INFO   Jayway.ProjectX.Service - returning 100 items</pre>
<p>I made this happen by using a logFactory that I inject into each class, instead of a log. (I’m not using an IoC container, was overkill for this project). The web service class looks like this:</p>
<pre class="brush: csharp;">private readonly ILogFactory _logFactory;
private readonly ILog _log;
public WebService()
{
   _logFactory = new LogFactoryLog4Net();
   _log = _logFactory.Create(this);
}</pre>
<p>whilst one of the classes begins with this:</p>
<pre class="brush: csharp;">private readonly ILog _log;

public Proxy(ILogFactory logFactory)
{
    _log = logFactory.Create(this);
}</pre>
<p>Using this technique, it would be very easy to temporarily add an appender for just a part of your system – giving you awesome control of the logging output.</p>
<h3>nhibernate</h3>
<p>NHibernate also uses log4net – and since I don’t have one logger but one per class, I have to use the “root” logger directive. The root logger funnel everything sent to the log4net system. This caused me to get all the nhibernate debug info in my logs. This was not what I wanted.</p>
<h3>Inverted filtering</h3>
<p>To get the kind of filtering output I wanted I had to use two kinds of filters; the LoggerMatchFilter and the LevelRangeFilter. Filtering in general in log4net works so that if you hit a filter that matches, it breaks the filtering chain and returns. This took me a while to figure out, I thought it just acted as a filter that could be chained, so that I could specify more and more filters to get more and more fine-grained output. But, back to the code:</p>
<pre class="brush: xml;">&lt;filter type=&quot;log4net.Filter.LoggerMatchFilter&quot;&gt;
  &lt;loggerToMatch value=&quot;NHibernate&quot; /&gt;
  &lt;AcceptOnMatch value=&quot;false&quot;/&gt;
&lt;/filter&gt;
&lt;filter type=&quot;log4net.Filter.LevelRangeFilter&quot;&gt;
  &lt;levelMin value=&quot;INFO&quot; /&gt;
&lt;/filter&gt;
&lt;filter type=&quot;log4net.Filter.DenyAllFilter&quot; /&gt;</pre>
<p>As you can see, I use the LoggerMatchFilter inverted. So, when it hits an item that matches “NHibernate” it will immediately reject it. If it does not match, it will continue down the chain and check the level. I figured this out by reading <a href="http://www.matheda.com/Blog/Details/4/log4net-tutorial">Matthew Daugherty’s log4net tutorial</a>, highly recommended.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2011/06/13/a-nice-basic-log4net-setup/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Java ME Logging over Bluetooth using MicroLog</title>
		<link>http://blog.jayway.com/2008/12/17/java-me-logging-over-bluetooth-using-microlog/</link>
		<comments>http://blog.jayway.com/2008/12/17/java-me-logging-over-bluetooth-using-microlog/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 16:17:25 +0000</pubDate>
		<dc:creator>Henrik Larne</dc:creator>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[bluetooth]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=604</guid>
		<description><![CDATA[When developing in Java ME and wanting to support several different devices, you wil no doubt run into problems with devices behaving differently. In some cases it is only the appearance that changes and in others the actual functionality varies or breaks. The first step in solving this is to run your Midlet in the [...]]]></description>
			<content:encoded><![CDATA[<p>When developing in Java ME and wanting to support several different devices, you wil no doubt run into problems with devices behaving differently. In some cases it is only the appearance that changes and in others the actual functionality varies or breaks. The first step in solving this is to run your Midlet in the emulators for the devices that you want to support and hopefully you will be able to solve some of the problems here, but unless you are really lucky there will be some problems remaining that needs to be debugged on the actual device. Depending on which device it is you might be able to run On Device Debugging  to solve it, but in many cases you don't have that option or the On Device Debugger is not stable enough. So now you are left with logging as your only tool to debug the midlet. Logging on a small screen device with very limited ram is not trivial however. </p>
<p>What you really want is to have the midlet write the log to your development PC instantaneously and free of charge, then you can log whatever you want to pinpoint your bug. This could be accomplished by logging over Bluetooth. Previously you had to write your own code to handle the logging and Bluetooth communication as well as a server to which the midlet connects and sends the log messages, but now there is a powerful logging framework for Java ME that offers this support out of the box. The framework is <a href="http://microlog.sourceforge.net">MicroLog</a> and is open source under the Apache Software License, so it is free to use as you see fit. MicroLog can be configured with one or more appenders that takes care of the logging messages and sends them to the right destination and each appender can have its own formatter to format the messages appropriately. This is very similar to log4j, so if you have used log4j before, MicroLog is very easy to learn. If you are using Maven 2 you will be happy to know that MicroLog is built using Maven 2 and is available in a public repository.</p>
<p>Setting up MicroLog to use Bluetooth and log to your PC is simple. It only requires that you setup your Logger:</p>
<pre>
private final static Logger log = Logger.getLogger(TestMidlet.class);
</pre>
<p>and that you configure it to use a <code>BluetoothSerialAppender</code>, which is done like this:</p>
<pre>
log.addAppender(new BluetoothSerialAppender());
</pre>
<p>Now your midlet is all set to start logging over Bluetooth. For a full midlet example see the following code:</p>
<pre>
package se.jayway.me;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import net.sf.microlog.Logger;
import net.sf.microlog.bluetooth.BluetoothSerialAppender;

public class TestMidlet extends MIDlet
{

	private final static Logger log = Logger.getLogger(TestMidlet.class);

	public TestMidlet()
	{
		configureMicroLog();
	}

	protected void destroyApp(boolean arg0) throws MIDletStateChangeException
	{
		log.info("Destroying application...");
	}

	protected void pauseApp()
	{
		log.info("Pausing application...");
	}

	protected void startApp() throws MIDletStateChangeException
	{
		log.info("Starting application...");
		final TextBox textBox = new TextBox("Text", "My text", 100, 0);
		textBox.addCommand(new Command("Log", Command.SCREEN, 0));
		textBox.setCommandListener(new CommandListener() {
			private int counter;

			public void commandAction(Command c, Displayable d)
			{
				log.debug("You clicked " + counter++);
				log.debug(textBox.getString());
			}
		});
		Display.getDisplay(this).setCurrent(textBox);
	}

	private void configureMicroLog()
	{
		log.addAppender(new BluetoothSerialAppender());
	}
}
</pre>
<p>Build and deploy this midlet to your Bluetooth enabled device, supporting JSR-82, the Bluetooth API and make sure that Bluetooth is turned on.</p>
<p>Next you need to get the Bluetooth server that will receive and print the logging messages to standard out. The server is also available in a public <a href="http://microlog.sourceforge.net/repo/m2-snapshot-repository/net/sf/microlog-servers/">Maven repository</a>. Just download the version that ends with -jar-with-dependencies.jar. This file contains all its dependencies. Now make sure that your Bluetooth unit is on and discoverable on your PC. Then start the server with the following command:</p>
<pre>
java -cp microlog-servers-1.1.0-SNAPSHOT-jar-with-dependencies.jar net.sf.microlog.server.btspp.MicrologBtsppServer
</pre>
<p>You might have to change the jar file name if it is not the same as the one you downloaded, then just replace it with the file name of your own microlog-server jar file.</p>
<p>The server starts up and registers a logging service with a unique UUID that the phone will try to locate and connect to. Now start the midlet and see how it will start logging over the Bluetooth connection.</p>
<p>The first phone I tested was a SonyEricsson C905 and it worked perfectly from the start. Then I tried to use a SonyEricsson P990i and for some reason it failed to locate the logging server with the unique UUID. I was unable to determine the reason why it failed to locate the service, so instead I added support to the <code>BluetoothSerialAppender</code> to specify the url of the Bluetooth logger server. Using this and setting the server url to my PC it connected flawlessly to it and started logging. So if you experience problems when your midlet connects to the PC or if you are using multiple logger servers within the Bluetooth range of your device try specifying the server url that the <code>BluetoothSerialAppender</code> should connect to. The url of the server is shown when starting the logger server. This url does however contain a channel that is not possible to determine through the used API's, but it does start on 1 and increases. For each session I always got the same channel and it was only the next day that it changed and I got channel 2 instead, so try with 1 to start with and if that does not work increase it by one and try again. It will most likely work first or second time.</p>
<p>Now you are free to log as much as you want and do not have to restrict your logging during the development phase of your project. Neither is there a reason for writing your own Bluetooth logger, just use MicroLog.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2008/12/17/java-me-logging-over-bluetooth-using-microlog/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

