<?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>Cata.printBlog(); &#187; Development</title>
	<atom:link href="http://cata.onsysol.com/blog/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://cata.onsysol.com/blog</link>
	<description>... it&#039;s about software!</description>
	<lastBuildDate>Sun, 30 May 2010 13:19:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>URL Validation in JavaScript</title>
		<link>http://cata.onsysol.com/blog/2010/05/url-validation-in-javascript/</link>
		<comments>http://cata.onsysol.com/blog/2010/05/url-validation-in-javascript/#comments</comments>
		<pubDate>Sun, 30 May 2010 13:19:27 +0000</pubDate>
		<dc:creator>Catalin Ciocov</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[user input]]></category>
		<category><![CDATA[validation]]></category>

		<guid isPermaLink="false">http://cata.onsysol.com/blog/?p=69</guid>
		<description><![CDATA[This won&#8217;t catch every malformed URL, but it&#8217;s a pretty good filter:
function test_url(url) {
  // comments:  (protocol )(user&#38;pass   ) (subdomains&#38;domain) (TLD            )(port   ) (path &#38; query string   )
  var regex = /^https?:\/\/(\w+(:\w+)?\@)?([\w\-]+&#124;\.[\w\-]+)+(\.[a-zA-Z]{2,6})(:[0-9]+)?(\/[\w#!:.?+=&#38;%@!\-\/]*)?$/i;
  return url.match(regex);
}
]]></description>
			<content:encoded><![CDATA[<p>This won&#8217;t catch every malformed URL, but it&#8217;s a pretty good filter:</p>
<pre>function test_url(url) {
  // comments:  (protocol )(user&amp;pass   ) (subdomains&amp;domain) (TLD            )(port   ) (path &amp; query string   )
  var regex = /^https?:\/\/(\w+(:\w+)?\@)?([\w\-]+|\.[\w\-]+)+(\.[a-zA-Z]{2,6})(:[0-9]+)?(\/[\w#!:.?+=&amp;%@!\-\/]*)?$/i;
  return url.match(regex);
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://cata.onsysol.com/blog/2010/05/url-validation-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Network in a Box Part 2</title>
		<link>http://cata.onsysol.com/blog/2010/02/network-in-a-box-part-2/</link>
		<comments>http://cata.onsysol.com/blog/2010/02/network-in-a-box-part-2/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 08:31:05 +0000</pubDate>
		<dc:creator>Catalin Ciocov</dc:creator>
				<category><![CDATA[Ad Server]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[networks]]></category>
		<category><![CDATA[virtual machine]]></category>
		<category><![CDATA[XEN]]></category>

		<guid isPermaLink="false">http://cata.onsysol.com/blog/?p=53</guid>
		<description><![CDATA[Long, long, looong time ago I wrote about setting up a virtual network using XEN virtual machines, with everything running on the same server. In the first part of this post I&#8217;ve mostly described my 2-day experience with making this work and now I&#8217;m simply going to copy &#38; paste a README file I&#8217;ve created [...]]]></description>
			<content:encoded><![CDATA[<p>Long, long, looong time ago I wrote about setting up a virtual network using XEN virtual machines, with everything running on the same server. In <a href="http://cata.onsysol.com/blog/2009/12/network-in-a-box/">the first part</a> of this post I&#8217;ve mostly described my 2-day experience with making this work and now I&#8217;m simply going to copy &amp; paste a README file I&#8217;ve created for myself to remember what exactly needs to be done to get such a setup up and running.</p>
<pre>This file describes how to create a load-balanced virtual network of
XEN guests (virtual machines) on a XEN Debian server. It is assumed
that the XEN server and xen-tools are already installed.

<strong>Step 1: Creating the XEN virtual machine using CentOS as guest OS</strong>
-------

- Fix rinse installation of CentOS 5. Add the following lines to
/etc/rinse/centos-5.packages:

nss
nspr
python-iniparse

- Optionally, install the packages for CentOS 5 version from a new
location. Modify /etc/rinse/rinse.conf:

[centos-5]
mirror       = http://mirror.bytemark.co.uk/centos/5/os/i386/CentOS/
mirror.amd64 = http://mirror.bytemark.co.uk/centos/5/os/x86_64/CentOS/

- Create the XEN virtual machine with the following command. Modify
parameters to suit needs:

xen-create-image --hostname node01 --dist centos-5 --install-method \
rinse --size 4Gb --swap 1Gb --memory 2Gb --ip 192.168.1.101 \
--netmask 255.255.255.0 --gateway 192.168.1.1 --passwd

<strong>Step 2: Bring the new virtual machine online and open a console to it</strong>
-------

- Run the following command:

xm create /etc/xen/node01.cfg -c

<strong>Step 3: Set up the network settings on the node</strong>
-------

echo 1 &gt; /proc/sys/net/ipv4/ip_forward
echo 1 &gt; /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 &gt; /proc/sys/net/ipv4/conf/all/arp_announce
echo 1 &gt; /proc/sys/net/ipv4/conf/eth0/arp_ignore
echo 2 &gt; /proc/sys/net/ipv4/conf/eth0/arp_announce

- Setup the ipip tunnel to the load balancer:

ifconfig tunl0 &lt;public IP of load-balancer&gt; netmask 255.255.255.255

- Optionally, set up another public IP address on eth0:1 (to access
this node directly, which is good when developing or debugging):

On the node, type:
ifconfig eth0:1 &lt;IP&gt; broadcast &lt;IP&gt; netmask 255.255.255.255

On the gateway (XEN server / Dom0), type:
route add -host &lt;IP&gt; &lt;vifX.Y&gt;

The vifX.Y must be the one used by XEN for the virtual machine on
which the node runs.

<strong>Step 4: Install and start the HTTP server</strong>
-------

yum install httpd.x86_64
echo "node01" &gt; /var/www/html/index.html
echo "ok" &gt; /var/www/html/status.html
/etc/init.d/httpd start

The status.html file is used by the load balancer to determine if the
node is online or not so that it knows if it can use it.

<strong>Step 5: Configure the load balancer to use the new node</strong>
-------

On the load balancer node (lb), edit /etc/ha.d/conf/ldirectord.cf:
real=192.168.1.101:80 ipip 10

Test that the new node is load-balanced (you should see node01 after a
few refreshes, in case you have more than 1 node):
http://&lt;public Load-balancer IP address&gt;/</pre>
<p>A few remarks:</p>
<ul>
<li>You need at least 2 public IP addresses on your server, but I would recommend 3 or more. One will be used by the server itself (to connect to Dom0), one will be used by the load balancer (your web requests will go to that IP and will be distributed among the available nodes) and at least another one should be assigned to one of the nodes to access it directly and not through the load balancer, which is very important for development and debugging of your load-balanced application.</li>
</ul>
<ul>
<li>The load balancer in my setup is another (virtual) node of the system&#8230; a XEN guest. This is needed because the load balancer cannot be on the same machine as the router for your virtual network, which will be Dom0 (i.e.: the main server itself, on which XEN and everything else runs). Why not? Well, because if you use the same IP for both your router and your load balancer when a packet is sent from one of your end nodes to a client it will have the source IP set to the public IP of the load balancer. Now, the router will receive a packet from &#8220;outside&#8221; that needs to be routed with the same IP address as its own IP address and will say &#8220;no, no! this isn&#8217;t right&#8221; and will drop that packet as being &#8220;source martian&#8221;. Google a bit for &#8220;source martian problem&#8221; and you&#8217;ll get a clearer picture.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cata.onsysol.com/blog/2010/02/network-in-a-box-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Network in a Box</title>
		<link>http://cata.onsysol.com/blog/2009/12/network-in-a-box/</link>
		<comments>http://cata.onsysol.com/blog/2009/12/network-in-a-box/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 10:48:53 +0000</pubDate>
		<dc:creator>Catalin Ciocov</dc:creator>
				<category><![CDATA[Ad Server]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[networks]]></category>
		<category><![CDATA[virtual machine]]></category>
		<category><![CDATA[XEN]]></category>

		<guid isPermaLink="false">http://cata.onsysol.com/blog/?p=44</guid>
		<description><![CDATA[I finally managed to get a new development server that I&#8217;ll use to build the ad server engine I was talking about. As you (might) know from my previous post, the system is supposed to run on multiple load-balanced servers. Using this setup I believe scaling won&#8217;t be a problem in the future, but I [...]]]></description>
			<content:encoded><![CDATA[<p>I finally managed to get a new development server that I&#8217;ll use to build the <a href="http://cata.onsysol.com/blog/2009/10/building-an-ad-server-engine/">ad server engine I was talking about</a>. As you (might) know from my <a href="http://cata.onsysol.com/blog/2009/11/ad-server-system-design-architecture/">previous post</a>, the system is supposed to run on multiple load-balanced servers. Using this setup I believe scaling won&#8217;t be a problem in the future, but I guess I&#8217;ll just have to wait and see.</p>
<p>My first task was to create this system setup on my development server. Basically, the system has N nodes with a load-balancer in front of them. Since I only have one server, the obvious choice is to use <a href="http://www.xen.org/">XEN</a> and create a virtual machine for every node of the system (including the load balancer). All nodes of the system (i.e.: XEN virtual machines) will sit on a private virtual network which is, again, created on just one real computer (my development server).</p>
<p>So far, so good! Everything seems quite simple from the description above and is definitely simple to setup (&#8230; after 3 days of intense googling!!!). The story goes like this&#8230;</p>
<p>I&#8217;m getting my server (yay!) with CentOS installed on it (I requested it). When it comes to Linux distributions I like Slackware, but using CentOS is so much easier when you don&#8217;t want to configure and install everything by hand and I didn&#8217;t want to spend too much time on installing and compiling software from source, like I usually do on Slackware.</p>
<p>So, anyway, my CentOS is up and running and I&#8217;m about to install XEN&#8230; easy!, just type &#8220;yum install xen&#8221; and you&#8217;re done. XEN requires a new kernel, so once you reboot the machine (with the new XEN kernel) you have a working XEN environment where you can create additional virtual machines. Just to note, at least on CentOS, you don&#8217;t have to configure anything (like grub for example); yum does everything for you&#8230; so once you install XEN with yum you just restart the server and you&#8217;re done&#8230; pretty cool!</p>
<p>Next step: build a virtual machine&#8230; how hard could this be? Well, it turns out it&#8217;s not that simple, at least not on CentOS. First of all, I think the documentation about this is a bit lacking, especially if you&#8217;re not familiar with how Linux works and a dozen or so command-line tools. I think I&#8217;m pretty good at Linux stuff, but nevertheless, I couldn&#8217;t create a XEN virtual machine on CentOS. To keep a long story short, I was able to boot a virtual machine but I wasn&#8217;t able to install the &#8220;guest&#8221; operating system on it because I didn&#8217;t have network access from inside the virtual machine and frankly I don&#8217;t know what didn&#8217;t work and I also didn&#8217;t want to spend too much time on this.</p>
<p>So I went and asked Google what&#8217;s the easiest way to create a XEN virtual machine&#8230; and the answer was &#8220;use xen-tools&#8221;. I said &#8220;aha! let&#8217;s try that&#8230;&#8221; and immediately went to my CentOS to type &#8220;yum install xen-tools&#8221;. To my surprise, yum said there is no package with that name, so again I turned to Google to find out more about these xen-tools. I read now from their page: &#8220;xen-tools is a collection of simple perl scripts which allow you to easily create new guest Xen domains upon your Debian GNU/Linux host&#8221;. Damn, I&#8217;m on the wrong Linux distribution&#8230; and from looking at the examples of how to use xen-tools it seems quite simple and easy, so it&#8217;s worth trying to work with Debian on my development server.</p>
<p>Luckily my hosting provider has a very easy and convenient way to (re)install a new OS, so I went to my administration console and looked for Debian through the available OSes and I was very happy to find a &#8220;Debian + XEN 3.2&#8243; OS template there&#8230; I selected that, clicked &#8220;Restore&#8221; and in about 30 minutes my new Debian + XEN 3.2 development server was back online!</p>
<p>What comes next&#8230; you&#8217;ll have to read it in part 2 of this post. Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://cata.onsysol.com/blog/2009/12/network-in-a-box/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ad Server: System Design &amp; Architecture</title>
		<link>http://cata.onsysol.com/blog/2009/11/ad-server-system-design-architecture/</link>
		<comments>http://cata.onsysol.com/blog/2009/11/ad-server-system-design-architecture/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 19:33:35 +0000</pubDate>
		<dc:creator>Catalin Ciocov</dc:creator>
				<category><![CDATA[Ad Server]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[data partitioning]]></category>
		<category><![CDATA[distributed systems]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[sharding]]></category>

		<guid isPermaLink="false">http://cata.onsysol.com/blog/?p=29</guid>
		<description><![CDATA[In a recent post I mentioned my next big project is to build an ad server engine. This will basically respond to ad requests and will record stats for served ads (such as impressions, clicks, custom interactions and whatever else you might want to track). This post is about the system&#8217;s design, how its different [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://cata.onsysol.com/blog/2009/10/building-an-ad-server-engine/">recent post</a> I mentioned my next big project is to build an ad server engine. This will basically respond to ad requests and will record stats for served ads (such as impressions, clicks, custom interactions and whatever else you might want to track). This post is about the system&#8217;s design, how its different parts will interact and how it should behave in certain scenarios.</p>
<p>The goal is to have a system that&#8217;s scalable! Ideally, doubling the number of components (servers) in the system should double its performance as well. Redundancy on the other hand is not that important, at least not for this particular application. As we&#8217;ll see later on, the engine will be able to function correctly even if some of its components (temporarily) crash.</p>
<p>I&#8217;ve done quite a bit of research lately on building scalable and redundant systems using MySQL databases. Almost all articles on this topic mention something about replication. At some point I was tempted to use circular replication, to get (unnecessary) data redundancy, however this was not going to help me get the much more important scaling, which is very important, especially for ad servers.</p>
<p>Let&#8217;s start by looking at what kind of data is used by a typical ad server. I could identify 3 major categories:</p>
<ol>
<li><strong>Configuration Data</strong><br />
This contains information about current campaigns, targeting parameters, CPM, target impressions, etc. The engine will mostly use this data in a &#8220;read-only&#8221; mode. In my particular case, this data comes from a completely separate admin application. The frequency at which this data changes is relatively low, at least when compared to the other 2 categories below.</li>
<li><strong>Runtime Data</strong><br />
This contains information generated during the normal operation of the ad server engine. You will find here things like counters, session data, etc. The engine will both read &amp; write this data in almost equal proportions.</li>
<li><strong>Reporting Data</strong><br />
This contains everything that&#8217;s being logged about served ads (clicks, interactions, timers, etc). This information is mainly written to the database and otherwise not required by the ad server engine. In my particular case, this information will be picked up by the completely separate admin application and used to generate reports and adjust the configuration data.</li>
</ol>
<p>The configuration data will be quite small in size (at least when compared with the reporting data) and will most likely be cached for super-fast access. The runtime data will also be kept in memory (as much as possible) but will also be saved in the database for persistence. The reporting data will be by far the largest in size and we&#8217;ll need to save this to the database as soon as possible (we&#8217;ll use an intermediary cache to reduce the number of WRITE operations to the database).</p>
<p>If I take into account one of the goals for this ad server engine (to be able to serve 1 billion ads per month) and assume that for each ad served an additional 10-15 database WRITE operations are required (I&#8217;ve exaggerated a bit here), it soon becomes obvious that scalability actually means in this case being able to cope with all those database WRITE operations.</p>
<p>I&#8217;ve mentioned above that almost all articles I&#8217;ve read about scaling MySQL talk about replication. Well, this is only useful when scaling READ operations. Scaling WRITE operations will only work by data partitioning (or sharding). Quick example: if you have an application with 100 million users, you most likely don&#8217;t want to keep all of those users in the same DB table because it will become unmanageable. Instead, you&#8217;ll split those users into say 20 tables each storing 5 million users. How do you determine which user goes into which table? Simple, you make this decision based on the user ID (using modulo 20) and this will make the user ID your partitioning key.</p>
<p>Since a picture is worth a thousand words, here&#8217;s how the ad server engine will look like. It&#8217;s important to realize that almost all the computers from the image below do not necessarily need to be physical boxes and the entire system will happily work on just one server.</p>
<div id="attachment_37" class="wp-caption alignnone" style="width: 581px"><img class="size-full wp-image-37" title="Ad Server Engine Architecture" src="http://cata.onsysol.com/blog/wp-content/uploads/2009/11/1.gif" alt="Ad Server Engine Architecture" width="571" height="349" /><p class="wp-caption-text">Ad Server Engine Architecture</p></div>
<p>Most likely each web server and its corresponding database server (black box and gray box right above it) will actually be on the same physical server running and HTTP server and a MySQL database. The &#8220;&#8230;&#8221; means that we will be able to add more servers to increase performance (horizontal scaling).</p>
<p>The Load Balancer will dispatch the incoming requests evenly to all available servers. The only data shared by the servers is the configuration and runtime data. Everything else is kept locally.</p>
<p>If a server crashes (not likely, but still) its local data will become temporarily unavailable, but here&#8217;s the nice thing about it: it doesn&#8217;t matter (more on this below)! The data kept locally by each server is mostly reporting data which is not time sensitive. The runtime information stored in RAM on that server will also be lost, but the RAM cache will actually be replicated on at least another server and unless both servers die at the same time there will be no loss of runtime data.</p>
<p>So, how it all works? Below are a few scenarios and the corresponding system behavior.</p>
<ul>
<li><strong>New ad request is received</strong><br />
The Load Balancer will dispatch the request to one of the available web servers. The selected web server and its corresponding database server will become the &#8220;origin&#8221; for that ad request. An ID will be generated for the request which is actually composed of the servers ID and a locally unique ID generated by the DB (auto-increment field for example). Besides being a globally unique ID, the request ID will also contain the origin server&#8217;s ID, which is useful to know when subsequent requests are received that are dispatched to different servers by the Load Balancer. The origin server will process the request, update what needs to be updated and send back the result. Everybody&#8217;s happy!</li>
<li><strong>The user clicked on the previously served ad</strong><br />
Again, the Load Balancer will dispatch this request to one of the available servers. The request this time will contain the request ID, because it&#8217;s a reporting/tracking request for an already served ad. The selected web server will inspect the request ID and determine which is the origin server and will use the appropriate database server to handle the request. So normally, all requests for already served ads will use the origin database keeping everything consistent, although the request itself might be processed by any of the available servers. So in this case, the selected server will contact the origin database (which is exactly the same as using its local database from a software perspective) and will process the request. Everybody&#8217;s happy!Now suppose the origin server is actually offline because it crashed right after processing and serving the initial ad request. In this case, the selected server (by the Load Balancer) will simply write whatever needs to be written to its local database (remember that all configuration and runtime information is still available). The beauty is that the selected server doesn&#8217;t need to access or read any of the local data stored on the origin server (which is down in our hypothetical scenario). The selected server will simply use its own local database and the available runtime data to process and serve the request. When the origin server will finally get back online, it could update its database with all the information he missed, but this is neither required nor important, it will practically be an implementation decision. Again, everybody&#8217;s happy (even if some servers crashed)!</li>
</ul>
<p>This is it! If you&#8217;ve got questions or feedback, I&#8217;m looking forward to reading your comments. As I&#8217;ll go along and implement this ad server engine, I&#8217;ll write more posts about the interesting parts.</p>
]]></content:encoded>
			<wfw:commentRss>http://cata.onsysol.com/blog/2009/11/ad-server-system-design-architecture/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Importance of Logging</title>
		<link>http://cata.onsysol.com/blog/2009/10/the-importance-of-logging/</link>
		<comments>http://cata.onsysol.com/blog/2009/10/the-importance-of-logging/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 19:43:25 +0000</pubDate>
		<dc:creator>Catalin Ciocov</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[logging system]]></category>

		<guid isPermaLink="false">http://cata.onsysol.com/blog/?p=25</guid>
		<description><![CDATA[When it comes to testing and validating the code I write, I usually do it right after I write the actual code. As much as possible I try writing very small bits of code (a function or even half a function) and then test immediately. If the input range is fairly limited (for example a [...]]]></description>
			<content:encoded><![CDATA[<p>When it comes to testing and validating the code I write, I usually do it right after I write the actual code. As much as possible I try writing very small bits of code (a function or even half a function) and then test immediately. If the input range is fairly limited (for example a function that only accepts 1 true/false parameter), you could easily check all scenarios and determine if there&#8217;s a bug or not pretty quickly. However, if you have a lot of possible inputs for the piece of code you want to test, most times you&#8217;ll test for 2-3-4 different situations and once all issues are fixed you might conclude that everything works OK. At least this is how I do it.</p>
<p>If you think unit testing might be a better solution, please stop now! In just a few words, I hate unit testing, I&#8217;ve never done it and I don&#8217;t think I ever will, unless the application I&#8217;m working on falls into one of those tiny, small and microscopic categories where unit testing actually makes sense. Writing code that validates other code that most likely will never change (at least most of it) just doesn&#8217;t make sense to me. Furthermore, in most web based applications the result of a test is actually something being displayed or rendered in a browser, so it&#8217;s much easier to just do the testing while you develop the application: write code, save, go to browser and press F5, check result and so on&#8230; quite easy!</p>
<p>Logging on the other hand is something I find truly useful. Not so much for testing, but for maintenance and debugging at a later stage. Once your application is set free into the wild, the real testing begins: scenarios you didn&#8217;t even thought were possible will start showing up and inevitably some bugs will surface. At this stage, it&#8217;s imperative and absolutely necessary for you to be able to  track down what is happening with your application.</p>
<p>I usually log almost everything. I&#8217;m using a logging system on 5 levels (below) meant to provide every bit of information about what the application is doing at any stage.</p>
<p><strong>Level 1 &#8211; Errors</strong><br />
When an error message is generated, it means the application or a specific piece of code cannot perform the action it&#8217;s supposed to do and cannot recover or find alternative solutions to complete the action.</p>
<p><strong>Level 2 &#8211; Warnings</strong><br />
Warnings are less severe error messages if you will. It means the application cannot perform a certain action, but could use an alternative solution. It could also mean that some features of the application will be disabled, but overall the application is still able to perform the action is supposed to perform.</p>
<p><strong>Level 3 &#8211; Info Messages</strong><br />
Info messages are generated whenever something non-deterministic is happening. For example, the user pressed a button or an e-mail was received.</p>
<p><strong>Level 4 &#8211; Debug Messages</strong><br />
Debug messages are generated whenever something deterministic is happening or as additional messages for Level 3 above. For example, if you have a timer to perform some action every 20 seconds, you might want to generate debug messages.</p>
<p><strong>Level 5 &#8211; Trace Messages</strong><br />
At this level I like to log everything. Basically, every function of my application will start with a trace message being generated. When this level is enabled, I can see every function call and the complete logic flow of the application. It&#8217;s very useful for tracking exactly where a problem occurs and could reduce debugging time a lot.</p>
<p>To conclude, I think logging could really save the day when it comes to debugging and maintaining a large scale application (think millions of requests/users per day). Bugs will inevitably appear and when they do, logging could make a really big difference.</p>
]]></content:encoded>
			<wfw:commentRss>http://cata.onsysol.com/blog/2009/10/the-importance-of-logging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
