<?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>Netuality &#187; python</title>
	<atom:link href="http://www.netuality.ro/tag/python/feed" rel="self" type="application/rss+xml" />
	<link>http://www.netuality.ro</link>
	<description>Taming the big, bad, nasty websites</description>
	<lastBuildDate>Sun, 13 Jun 2010 07:44:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Google: sorry, but Lisp/Ruby/Erlang not on the menu</title>
		<link>http://www.netuality.ro/google-sorry-but-lisprubyerlang-not-on-the-menu/tools/20080529</link>
		<comments>http://www.netuality.ro/google-sorry-but-lisprubyerlang-not-on-the-menu/tools/20080529#comments</comments>
		<pubDate>Wed, 28 May 2008 21:35:00 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.netuality.ro/google-sorry-but-lisprubyerlang-not-on-the-menu/tools/20080529</guid>
		<description><![CDATA[Yes, language propaganda again. Ain&#8217;t it fun ?
Here comes a nice quote from the latest Steve Yegge post (read it entirely if you have the time, it&#8217;s both fun and educational &#8211; at least for me). So, there:
I made the famously, horribly, career-shatteringly bad mistake of trying to use Ruby at Google, for this project. [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, language propaganda again. Ain&#8217;t it fun ?</p>
<p>Here comes a nice quote from the <a href="http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html" target="_blank">latest Steve Yegge post</a> (read it entirely if you have the time, it&#8217;s both fun and educational &#8211; at least for me). So, there:</p>
<p><em>I made the famously, horribly, career-shatteringly bad mistake of trying to use Ruby at Google, for this project. And I became, very quickly, I mean almost overnight, the Most Hated Person At Google. And, uh, and I&#8217;d have arguments with people about it, and they&#8217;d be like Nooooooo, WHAT IF&#8230; And ultimately, you know, ultimately they actually convinced me that they were right, in the sense that there actually <strong><em>were</em> a few things</strong>. There were some taxes that I was imposing on the systems people, where they were gonna have to have some maintenance issues that they wouldn&#8217;t have. [...] But, you know, <strong>Google&#8217;s all about getting stuff done</strong>.</em></p>
<p><em>[...]</em></p>
<p><em><strong>Is it allowed at Google to use Lisp and other languages?</strong></p>
<p>No. No, it&#8217;s not OK. <strong>At Google you can use C++, Java, Python, JavaScript</strong>&#8230; I actually found a legal loophole and used server-side JavaScript for a project.</em></p>
<p>Mmmmm &#8230; key ?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/google-sorry-but-lisprubyerlang-not-on-the-menu/tools/20080529/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Java going down, Python way up, and more &#8230;</title>
		<link>http://www.netuality.ro/java-going-down-python-way-up-and-more/tools/20080524</link>
		<comments>http://www.netuality.ro/java-going-down-python-way-up-and-more/tools/20080524#comments</comments>
		<pubDate>Sat, 24 May 2008 14:36:19 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.netuality.ro/java-going-down-python-way-up-and-more/tools/20080524</guid>
		<description><![CDATA[According to O&#8217;Reilly Radar, sales of Java books have declined in the last 4 years by almost 50%. C# is selling more books from year to year and will probably level up with Java in 2008. Javascript is on the rise (due to AJAX, for sure) and PHP is on a surprising decrease path (although [...]]]></description>
			<content:encoded><![CDATA[<p>According to <a href="http://radar.oreilly.com/archives/2008/03/state-of-the-computer-book-mar-23.html">O&#8217;Reilly Radar</a>, sales of Java books have <a href="http://www.theserverside.com/news/thread.tss?thread_id=49341" target="_blank">declined</a> in the last 4 years by almost 50%. C# is selling more books from year to year and will probably level up with Java in 2008. Javascript is on the rise (due to AJAX, for sure) and PHP is on a surprising decrease path (although the job statistics indicate quite the contrary).</p>
<p style="text-align: center"><img src="http://www.netuality.ro/wp-content/uploads/2008/05/languages.gif" alt="According to O’Reilly Radar, sales of Java books have declined in the last 4 years by almost 50%" /></p>
<p>In 2007, the number of sold Ruby books was larger than the number of Python books. In their article they qualify Ruby as being a &#8220;mid-major programming language&#8221; and Python as &#8220;mid-minor programming language&#8221;. However, after the announcement of <a href="http://code.google.com/appengine/" target="_blank">Google App Engine</a> the number of Python downloads from ActiveState has <strong><a href="http://blogs.activestate.com/activestate/2008/05/number-of-activ.html" target="_blank">tripled</a></strong> in May. This should become visible in the book sales statistics, pretty soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/java-going-down-python-way-up-and-more/tools/20080524/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>memcached vs tugela vs memcachedb</title>
		<link>http://www.netuality.ro/memcached-vs-tugela-vs-memcachedb/presentations/20080317</link>
		<comments>http://www.netuality.ro/memcached-vs-tugela-vs-memcachedb/presentations/20080317#comments</comments>
		<pubDate>Sun, 16 Mar 2008 21:38:38 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Presentations]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[memcachedb]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tugela]]></category>
		<category><![CDATA[wurbe]]></category>

		<guid isPermaLink="false">http://www.netuality.ro/memcached-vs-tugela-vs-memcachedb/presentations/20080317</guid>
		<description><![CDATA[This presentation was planned for an older Wurbe event, but as this never quite happened in the last 4 months I am publishing it now, before it becomes totally obsolete.

My original contribution here is a comparison between the original memcached server from Danga and the tugela fork from the MediaWiki programmers. I&#8217;ve also tried memcachedb [...]]]></description>
			<content:encoded><![CDATA[<p>This presentation was planned for an older <a href="http://wurbe.ro/" target="_blank">Wurbe</a> event, but as this never quite happened in the last 4 months I am publishing it now, before it becomes totally obsolete.</p>
<p><center><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=memcached-vs-tugela-1205702329685207-3"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=memcached-vs-tugela-1205702329685207-3" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></center></p>
<p>My original contribution here is a comparison between the <a href="http://www.danga.com/memcached/" target="_blank">original memcached serve</a>r from Danga and the <a href="http://meta.wikimedia.org/wiki/Tugela_Cache" target="_blank">tugela fork</a> from the MediaWiki programmers. I&#8217;ve also tried <a href="http://memcachedb.org/" target="_blank">memcachedb</a> but the pre 1.0 version (from Google Code) in November 2007 was quite unstable and unpredictible.</p>
<p>In a nutshell, these memcache versions are using <a href="http://www.oracle.com/technology/products/berkeley-db/index.html" target="_blank">BerkeleyDB</a> instead of memory slab allocator. There are 2 direct consequences:</p>
<ul>
<li>when the memory is large enough for the whole cache, database-backed servers will be slower (my tests shown 10-15% which might be tolerable &#8211; or not &#8211; for your app)</li>
<li>when you&#8217;ve got lots of data to cache and your server&#8217;s memory is low, relying on bdb is significantly better than letting the swap mechanism to do its job (from my benchmarks, the difference can go up to 10 times faster especially under very high concurrency conditions)</li>
</ul>
<p>Tugela will prove especially useful when running it on virtualized servers with very low memory.</p>
<p>My tests were performed with the &#8220;Tummy&#8221; Python client and Stackless for the multithreaded version. In one of the following weeks I&#8217;ll update the benchmarks for memcachedb 1.0.x &#8211; and I promise never ever to wait 4 months for a presentation, again &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/memcached-vs-tugela-vs-memcachedb/presentations/20080317/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Programming is hard &#8211; the website</title>
		<link>http://www.netuality.ro/programming-is-hard-the-website/tools/20060802</link>
		<comments>http://www.netuality.ro/programming-is-hard-the-website/tools/20060802#comments</comments>
		<pubDate>Wed, 02 Aug 2006 20:07:31 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/programming-is-hard-the-website/uncategorized/20060802</guid>
		<description><![CDATA[A newcomer in the world of &#8220;code snippets&#8221; sites in programmingishard.com. Although the site is a few months old, only recently it started to gain some steam. Unlike its competition Krugle and Koders, this is not a code search engine but a snippet repository entirely tag-based, user-built. The author has a blog at tentimesbetter.com.
As for [...]]]></description>
			<content:encoded><![CDATA[<p>A newcomer in the world of &#8220;code snippets&#8221; sites in <a href="http://programmingishard.com/" target="_new">programmingishard.com</a>. Although the site is a few months old, only recently it started to gain some steam. Unlike its competition <a href="http://krugle.com/" target="_new">Krugle</a> and <a href="http://www.koders.com/" target="_new">Koders</a>, this is not a code search engine but a snippet repository entirely tag-based, user-built. The author has a blog at <a href="http://tentimesbetter.com/" target="_new">tentimesbetter.com</a>.</p>
<p>As for watering your mouth, this is a Python code fragment that I found on the site, for the classic inline conditional which does not exist &#8220;such as&#8221; in Python:</p>
<pre>n = ['no', 'yes'][thing == 1]</pre>
<p>Obviously it has the big disadvantage of having to compute both values no matter what the condition <em>thing</em> is, but is very short and elegant. Simple but nice code sugar.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/programming-is-hard-the-website/tools/20060802/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monitoring memcached with cacti</title>
		<link>http://www.netuality.ro/monitoring-memcached-with-cacti/tools/20060802</link>
		<comments>http://www.netuality.ro/monitoring-memcached-with-cacti/tools/20060802#comments</comments>
		<pubDate>Wed, 02 Aug 2006 19:54:44 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[cacti]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[snmp]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/monitoring-memcached-with-cacti/uncategorized/20060802</guid>
		<description><![CDATA[Memcached is a clusterable cache server from Danga. Or, as they call, it a distributed memory object caching system. Well, whatever. Just note that memcached clients exist for lots of languages (Java, PHP, Python, Ruby, Perl) &#8211; mainstream languages in the web world. A lighter version of server was rewritten in Java by Mr. Jehiah [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.danga.com/memcached/" target="_new">Memcached</a> is a clusterable cache server from <a href="http://www.danga.com/" target="_new">Danga</a>. Or, as they call, it a <strong>distributed memory object caching system</strong>. Well, whatever. Just note that memcached clients exist for lots of languages (Java, PHP, Python, Ruby, Perl) &#8211; mainstream languages in the web world. A lighter version of server was <a href="http://jehiah.com/projects/j-memcached/" target="_new">rewritten in Java</a> by Mr. Jehiah Czebotar. Major websites such as Facebook, Slashdot, Livejournal and Dealnews use memcached in order to scale for the huge load they&#8217;re serving.  Recently, we needed to monitor the memcache servers on a high-performance web cluster serving the <a href="http://www.planigo.com/en/index.html" target="_blank">Planigo</a> websites. By googling and reading the related newsgroups, I was able to find two solutions:</p>
<ul>
<li>from faemalia.net, a script which is integrated with the <a href="http://www.faemalia.net/mysqlUtils/" target="_new">MySQL server templates</a> for Cacti. Uses the Perl client.</li>
<li>from dealnews.com, a dedicated memcached template for Cacti and some scripts based on the Python client. The installation is <a href="http://dealnews.com/developers/cacti/memcached.html" target="_new">thoroughly described here</a>.</li>
</ul>
<p>These two solutions have the same approach &#8211; provide a specialized Cacti template. The charts drawn by these templates are based on data extracted by the execution of memcached client scripts. Maybe very elegant, but could become a pain in the dorsal area. Futzing with Cacti templates was never my favorite pasttime. Just try to import a template exported from a different version of Cacti and you&#8217;ll know what I mean.  In my opinion, there is a simple way, which consists in installing a memcached client on all the memcached servers, then extracting the statistical values using a script. We&#8217;ll use the technique described in <a href="http://www.netuality.ro/monitor-everything-on-your-linux-servers-with-snmp-and-cacti/tools/20060305" target="_blank">one of my previous posts</a>, to expose script results as SNMP OID values. Then, track these values in Cacti via the generic existing mechanism. My approach has the disadvantage of installing a memcached client on all the servers. However, it is very simple to build your own charts and data source templates, as for any generic SNMP data.  All you need now a simple script which will print the memcached statistics, one per line. I will provide one-liners for Python, which will obviously work only on machines having Python and the <a href="ftp://ftp.tummy.com/pub/python-memcached/" target="_new">&#8220;tummy&#8221; client</a> installed. This is the recipe (default location of Python executable on Debian is <em>/usr/bin/python</em> but YMMV):</p>
<p>1. first use this one liner as snmpd exec :</p>
<p><em>/usr/bin/python -c &#8220;import memcache; print (&#8216;%s&#8217;%[memcache.Client(['127.0.0.1:11211'], debug=0).get_stats()[0][1],]).replace(\&#8221;&#8216;\&#8221;,&#8221;).replace(&#8216;,&#8217;,'\n&#8217;).replace(&#8216;[','')<br />
.replace(']&#8216;,&#8221;).replace(&#8216;{&#8216;,&#8221;).replace(&#8216;}&#8217;,&#8221;)&#8221;</em></p>
<p>This will display the name of the memcached statistic along with its value and will allow you to hand pick the OIDs that you want to track. Yes, I know it could be done simpler with <em>translate</em> instead of multiple <em>replace</em>. Left as an exercise for the Python-aware reader.</p>
<p>2. after having a complete list of OIDs use this one-liner:</p>
<p><em>/usr/bin/python -c &#8220;import memcache; print &#8216;##&#8217;.join(memcache.Client(['127.0.0.1:11211'], debug=0).get_stats()[0][1].values()).replace(&#8216;##&#8217;,'\n&#8217;)&#8221;</em></p>
<p>The memcached statistics will be displayed in the same order, but only their values not their names.</p>
<p>And this is the mandatory eye candy:</p>
<p><img src="http://www.jroller.com/resources/a/aspinei/mem1.png" alt="" width="432" height="179" /><br />
<img src="http://www.jroller.com/resources/a/aspinei/mem2.png" alt="" width="426" height="171" /><br />
<img src="http://www.jroller.com/resources/a/aspinei/mem3.png" alt="" width="432" height="178" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/monitoring-memcached-with-cacti/tools/20060802/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Unicode in Python micro-recipe : from MySQL to webpage via Cheetah</title>
		<link>http://www.netuality.ro/unicode-in-python-micro-recipe-from-mysql-to-webpage-via-cheetah/tools/20060414</link>
		<comments>http://www.netuality.ro/unicode-in-python-micro-recipe-from-mysql-to-webpage-via-cheetah/tools/20060414#comments</comments>
		<pubDate>Fri, 14 Apr 2006 20:42:52 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/unicode-in-python-micro-recipe-from-mysql-to-webpage-via-cheetah/uncategorized/20060414</guid>
		<description><![CDATA[Very easy:

start by adding the default-character-set=utf8 in your MySQL configuration file and restart the database server
apply this recipe from Activestate Python Cookbook (&#8220;guaranteed conversion to unicode or byte string&#8221;)
inside the Cheetah template, use the ReplaceNone filter:


#filter ReplaceNone
${myUnicodeString}
#end filter
in order to prevent escaping non-ASCII characters.

Now. That&#8217;s better.
]]></description>
			<content:encoded><![CDATA[<p>Very easy:</p>
<ul>
<li>start by adding the default-character-set=utf8 in your MySQL configuration file and restart the database server</li>
<li>apply <a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/466341" target="_blank">this recipe from Activestate Python Cookbook</a> (&#8220;guaranteed conversion to unicode or byte string&#8221;)</li>
<li>inside the Cheetah template, use the ReplaceNone filter:</li>
</ul>
<p><code><br />
#filter ReplaceNone<br />
${myUnicodeString}<br />
#end filter</code></p>
<p>in order to prevent escaping non-ASCII characters.</p>
<p><img src="http://www.netuality.ro/wp-content/uploads/2008/03/unicode.png" /></p>
<p>Now. That&#8217;s better.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/unicode-in-python-micro-recipe-from-mysql-to-webpage-via-cheetah/tools/20060414/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monitor everything on your Linux servers &#8211; with SNMP and Cacti</title>
		<link>http://www.netuality.ro/monitor-everything-on-your-linux-servers-with-snmp-and-cacti/tools/20060305</link>
		<comments>http://www.netuality.ro/monitor-everything-on-your-linux-servers-with-snmp-and-cacti/tools/20060305#comments</comments>
		<pubDate>Sun, 05 Mar 2006 14:27:22 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[snmp]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/monitor-everything-on-your-linux-servers-with-snmp-and-cacti/uncategorized/20060305</guid>
		<description><![CDATA[Two free open-source tools are running the show for network and server-activity monitoring. The oldest and quite popular among network and system administrators is Nagios. Nagios does not only do monitoring, but also event traps, escalation and notification. The younger challenger is called Cacti. Unlike Nagios, it&#8217;s written in a scripting language [PHP] so no [...]]]></description>
			<content:encoded><![CDATA[<p align="left">Two free open-source tools are running the show for network and server-activity monitoring. The oldest and quite popular among network and system administrators is <a href="http://www.nagios.org/" target="_new">Nagios</a>. Nagios does not only do monitoring, but also event traps, escalation and notification. The younger challenger is called <a href="http://www.cacti.net/" target="_new">Cacti</a>. Unlike Nagios, it&#8217;s written in a scripting language [PHP] so no compiling is necessary &#8211; it just runs out of the box<a title="sc1" name="sc1" href="#sn1"><sup>1</sup></a>. Cacti&#8217;s problem is that &#8211; at its current version &#8211; is missing lots of real-time features such as monitoring and notification. All these features are scheduled to be integrated in future versions of the product, but as with any open-source roadmap nothing is guaranteed, Anyway, this article is focusing on Cacti integration because it&#8217;s what I am currently using.</p>
<p align="left">Cacti is built upon an open-source graphing tool called <a title="The Multi Router Traffic Grapher" href="http://people.ee.ethz.ch/~oetiker/webtools/mrtg/" target="_new">MRTG</a> and a communication protocol <a title="Simple Network Management Protocol" href="http://www.snmp.com/protocol/" target="_new">SNMP</a>. SNMP is not exactly a developer&#8217;s cup of tea, being more of a network administrator&#8217;s tool<a title="sc2" name="sc2" href="#sn2"><sup>2</sup></a>. However, a monitoring server comes extremely handy in performance measurement and tuning, especially for complex performance behavior which can only be benchmarked long-term : such as large caches impact on a web application, or performance of long-running operations.</p>
<p align="left">But is that specific variable you need to monitor, available with SNMP out of the box ? There is a strong chance it is. SNMP being an extensible protocol, lots of organization have recorded their own <a title="Management information base" href="http://en.wikipedia.org/wiki/Management_information_base" target="_new">MIB</a>s and respective implementations. Basically, a MIB is a group of unique identifiers called <a title="Object identifier" href="http://en.wikipedia.org/wiki/Object_identifier" target="_new">OID</a>s. An OID is a sequence of numbers separated by dots, for instance &#8216;.1.3.6.1.4.1.2021.11&#8242;; each number has a special meaning in a standard object tree &#8211; this example, the meaning of &#8216;.1.3.6.1.4.1.2021.11&#8242; is &#8216;.iso.org.dod.internet.private.enterprises.ucdavis.systemStats&#8217;. Even you can have your own MIB in the &#8216;.iso.org.dod.internet.private.enterprises&#8217; tree, by applying on <a title="Apply for your own MIB" href="http://www.iana.org/cgi-bin/enterprise.pl" target="_new">this</a> page at <a title="Internet Assigned Numbers Authority" href="http://en.wikipedia.org/wiki/Internet_Assigned_Numbers_Authority" target="_new">IANA</a>.</p>
<p align="left">Most probably you don&#8217;t really need your own MIB, no matter how &#8216;exotic&#8217; your monitoring is, because:</p>
<p>a) it&#8217;s already there, in the huge list of existing MIBs and implementations</p>
<p>and</p>
<p>b) you are not bound to the existing official MIBs, in fact you can create your own MIB as long as you replicate it in the snmp configuration on all the servers that you want to monitor.</p>
<p style="text-align: center"><img src="http://www.netuality.ro/wp-content/uploads/2008/01/snmp1.gif" alt="" width="499" height="298" /></p>
<p align="left">To take a look at existing MIBs, free tools are available on the net, IMHO the best one being <a href="http://www.ireasoning.com/mibbrowser.shtml" target="_new">MibBrowser</a>. This multiplatform [Java] MIB browser has a free version which should be more than enough for our basic task. The screen capture shown here depicts a &#8220;Get Subtree&#8221; operation on the &#8216;.1.3.6.1.4.1.2021.11&#8242; MIB; the result is a list of single value MIBs, such for instance &#8216;.1.3.6.1.4.1.2021.11.11.0&#8242; which has the alias &#8217;ssCpuIdle.0&#8242; and value 97 [meaning that the CPU is 97% idle]. You can see the alias by loading the corresponding MIB file [select File/Load MIB then choose 'UCD-SNMP-MIB.txt' from the list of predefined MIBs].</p>
<p align="left">From command line, in order to display existing MIB values, you can use snmpwalk:</p>
<pre>snmpwalk -Os -c [community_name] -v 1 [hostname] .1.3.6.1.4.1.111111.1</pre>
<p><a title="sc3" name="sc3" href="#sn3"><sup>3</sup></a> and the result is:</p>
<pre>.1.3.6.1.4.1.2021.11 OID (.iso.org.dod.internet.private.enterprises.ucdavis.systemStats)
snmpwalk -v 1 -c sncq localhost .1.3.6.1.4.1.2021.11
UCD-SNMP-MIB::ssIndex.0 = INTEGER: 1
UCD-SNMP-MIB::ssErrorName.0 = STRING: systemStats
UCD-SNMP-MIB::ssSwapIn.0 = INTEGER: 0
UCD-SNMP-MIB::ssSwapOut.0 = INTEGER: 0
UCD-SNMP-MIB::ssIOSent.0 = INTEGER: 4
UCD-SNMP-MIB::ssIOReceive.0 = INTEGER: 2
UCD-SNMP-MIB::ssSysInterrupts.0 = INTEGER: 4
UCD-SNMP-MIB::ssSysContext.0 = INTEGER: 1
UCD-SNMP-MIB::ssCpuUser.0 = INTEGER: 2
UCD-SNMP-MIB::ssCpuSystem.0 = INTEGER: 1
UCD-SNMP-MIB::ssCpuIdle.0 = INTEGER: 96
UCD-SNMP-MIB::ssCpuRawUser.0 = Counter32: 17096084
UCD-SNMP-MIB::ssCpuRawNice.0 = Counter32: 24079
UCD-SNMP-MIB::ssCpuRawSystem.0 = Counter32: 6778580
UCD-SNMP-MIB::ssCpuRawIdle.0 = Counter32: 599169454
UCD-SNMP-MIB::ssCpuRawKernel.0 = Counter32: 6778580
UCD-SNMP-MIB::ssIORawSent.0 = Counter32: 998257634
UCD-SNMP-MIB::ssIORawReceived.0 = Counter32: 799700984
UCD-SNMP-MIB::ssRawInterrupts.0 = Counter32: 711143737
UCD-SNMP-MIB::ssRawContexts.0 = Counter32: 1163331309
UCD-SNMP-MIB::ssRawSwapIn.0 = Counter32: 23015
UCD-SNMP-MIB::ssRawSwapOut.0 = Counter32: 13730</pre>
<p>Each of this values has its own significance, like for instance &#8217;ssCpuIdle.0&#8242; which announces that the CPU is 96% idle.<br />
In order to retrieve just a single value of the list, use its alias as a parameter to the snmpget command, for instance</p>
<pre>snmpget -Os -c [community_name] -v 1 [hostname] UCD-SNMP-MIB::ssCpuIdle.0</pre>
<p align="left">Sometimes, you want to monitor something which you do not seem to find in the list of MIBs. Say, for instance, the performance of a MySQL database that your&#8217;re pounding pretty hard with your webapp<a title="sc4" name="sc4" href="#sn4"><sup>4</sup></a>. The easiest way of doing this is to pass through a script &#8211; snmp implementations can take the result of any script and expose it through the protocol, line by line.</p>
<p>Supposing you want to keep track of the values obtained with the following script:</p>
<pre>#!/bin/sh
/usr/bin/mysqladmin -uroot status | /usr/bin/awk '{printf("%f\n%d\n%d\n",$4/
10,$6/1000,$9)}'</pre>
<p align="left">The <em>mysqladmin</em> command and a bit of simple awk magic display the following three values, each on a separate line:</p>
<ul>
<li>number of opened connections / 10</li>
<li>number of queries / 1000</li>
<li>number of slow queries</li>
</ul>
<p align="left">It is interesting to not that, while the first value is instantaneous gauge-like, the following two are incremental, growing and growing as long as new queries and new slow queries are recorded. Will keep this in mind for later, when we will track these values.</p>
<p align="left">But for now, let&#8217;s see how these three values are exposed through snmp. The first step is to tell the SNMP daemon that the script has an associated MIB. This is done in the configuration file, usually located at <em>/etc/snmp/snmp.d</em>. The following line attaches the script [for example /home/user/myscript.sh] execution to a certain OID:</p>
<pre>exec .1.3.6.1.4.1.111111.1 MySQLParameters /home/user/myscript.sh</pre>
<p align="left">the &#8216;.1.3.6.1.4.1.111111.1&#8242; OID is a branch of &#8216;.1.3.6.1.4.1&#8242; [meaning '.iso.org.dod.internet.private.enterprises']. We tried to make it look &#8216;legitimate&#8217; but obviously you can use here any sequence you want to.</p>
<p align="left">After restarting the daemon, let&#8217;s interrogate Mibbrowser for the freshly created OID, see the following image <em>snmpwalk -Os -c [community_name] -v 1 [hostname] .1.3.6.1.4.1.111111.1</em> ; the result is:</p>
<pre>enterprises.111111.1.1.1 = INTEGER: 1
enterprises.111111.1.2.1 = STRING: "MySQLParameters"
enterprises.111111.1.3.1 = STRING: "/etc/snmp/mysql_params.sh"
enterprises.111111.1.100.1 = INTEGER: 0
enterprises.111111.1.101.1 = STRING: "0.900000"
enterprises.111111.1.101.2 = STRING: "18551"
enterprises.111111.1.101.3 = STRING: "108"
enterprises.111111.1.102.1 = INTEGER: 0
enterprises.111111.1.103.1 = ""</pre>
<p align="left">Great ! Now we have the proof that it really works and our specific values extracted with a custom script are visible through SNMP. Let&#8217;s go back to Cacti and see how we can make some nice charts out of them<a title="sc5" name="sc5" href="#sn5"><sup>5</sup></a>.</p>
<p align="left">Cacti has this nice feature of defining &#8216;templates&#8217; that you can reuse afterwards. My strategy is to define a data template for each one of the 3 parameters I want to chart, using the &#8216;Duplicate&#8217; function applied to the &#8216;SNMP &#8211; Generic OID Template&#8217;.</p>
<p style="text-align: center"><img src="http://www.netuality.ro/wp-content/uploads/2008/01/snmp2.gif" alt="" width="501" height="48" /></p>
<p align="left">On the duplicate datasource template, you have to change the datasource title, name to display in charts, data source type [use DERIVE for incremental counters and GAUGE for instantaneous values], specific OID and the snmp community. Do it for the three values.</p>
<p style="text-align: center"><img src="http://www.netuality.ro/wp-content/uploads/2008/01/snmp3.gif" alt="" width="500" height="172" /></p>
<p align="left">Using the three new datasource templates, create a chart template for &#8216;MySQL Activity&#8217;. That&#8217;s a bit more complicated, but it boils down to the following procedure, repeated for each of the 3 data sources:</p>
<ul>
<li>add a data source and associate a graph [I always use AREA for the first graph as a background and LINE3 for the other, but it's just a matter of taste]</li>
<li>associate labels with current or computed values: CURRENT, AVERAGE, MAX in this example</li>
</ul>
<p>All the rest is really fine tuning &#8211; deciding for better colors, wether to use autoscale or fixed scale and so on. By now, your graph template should be ready to use.</p>
<p style="text-align: center"><img src="http://www.netuality.ro/wp-content/uploads/2008/01/snmp4.gif" alt="" width="501" height="352" /></p>
<p align="left">Note that for the incremental values ['DERIVE' type data sources] I&#8217;ve used titles such as &#8216;Thousands queries/5 min&#8217; &#8211; the 5 minutes come from the Cacti poller which is set to query for data each 5 minutes. The end result is something like this one :</p>
<p style="text-align: center"><img src="http://www.netuality.ro/wp-content/uploads/2008/01/snmp5.gif" alt="" width="500" height="199" /></p>
<p align="left">On this real production chart you&#8217;ll see a few interesting patterns. For instance, at 3 o&#8217;clock in the morning, there is a huge spike in all the charted parameters &#8211; indeed, a cron&#8217;ed script was provoking this spike. From time to time, a small burst of slow queries is recorded &#8211; still under investigation. What is interesting here is that these spikes were previously undetectable on the load average chart, which look clean and innocuous:</p>
<p style="text-align: center"><img src="http://www.netuality.ro/wp-content/uploads/2008/01/snmp6.gif" alt="" width="501" height="220" /></p>
<p align="left">To conclude, SNMP is a valuable resource for server performance monitoring. Often, investigating specific parameters and displaying them in tools such as Cacti can bring interesting insights upon the behavior of servers.</p>
<p align="left">Some SNMP implementations in different programming languages:</p>
<ul>
<li>Java:  <a href="http://snmp.westhawk.co.uk/" target="_new">Westhawk&#8217;s Java SNMP stack</a> [free w commercial support], <a href="http://snmp.adventnet.com/index.html" target="_new">AdventNet SNMP API</a> [commercial, with a feature-restricted un-expiring free version], <a href="http://www.ireasoning.com/snmpapi.shtml" target="_new">iREASONING SNMP API</a> [commercial implementation], <a href="http://www.snmp4j.org/" target="_new">SNMP4J</a> [free and feature-rich implementation - thank you Mathias for the tip]</li>
<li>PHP: client-only supported by the php-snmp extension, <a href="http://ro.php.net/manual/en/ref.snmp.php" target="_new">part of</a> the PHP distribution [free]</li>
<li>Python: <a href="http://pysnmp.sourceforge.net/" target="_new">PySNMP</a> is a Python SNMP framework, client+agents [free].</li>
<li>Ruby: client-only implementation <a href="http://snmplib.rubyforge.org/" target="_new">Ruby SNMP</a> [free]</li>
</ul>
<p><a title="sn1" name="sn1" href="#sc1"><sup>1</sup></a> If you&#8217;re running Debian, Cacti comes with apt so it&#8217;s a breeze to install and run [<em>apt-get install cacti</em>]</p>
<p><a title="sn2" name="sn2" href="#sc2"><sup>2</sup></a> a bit out of the scope of this article, SNMP also allows writing values on remote servers, not only retrieving monitored values.</p>
<p><a title="sn3" name="sn3" href="#sc3"><sup>3</sup></a> Replace [hostname] with the server hostname and [community_name] with the SNMP community &#8211; default being &#8216;public&#8217;. The SNMP community is a way of authenticating a client to a SNMP server; although the system can be used for pretty sophisticated stuff, most of the time the servers have a read-only passwordless community, visible only in the internal network for monitoring purposes.</p>
<p><a title="sn4" name="sn4" href="#sc4"><sup>4</sup></a> In fact, a commercial implementation of SNMP for MySQL does exist.</p>
<p><a title="sn5" name="sn5" href="#sc5"><sup>5</sup></a> The procedure described here applies to Cacti v0.8.6.c</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/monitor-everything-on-your-linux-servers-with-snmp-and-cacti/tools/20060305/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sybase woes &#8211; and Jython saves the day</title>
		<link>http://www.netuality.ro/sybase-woes-and-jython-saves-the-day/tools/20050202</link>
		<comments>http://www.netuality.ro/sybase-woes-and-jython-saves-the-day/tools/20050202#comments</comments>
		<pubDate>Wed, 02 Feb 2005 05:19:55 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/sybase-woes-and-jython-saves-the-day/uncategorized/20050202</guid>
		<description><![CDATA[Until now, I&apos;ve always had a certain respect for Sybase database.
Based on their history, I thought that the product is a sort of MS SQL
without the glitzy features &#8211; think Las Vegas without the lights, the cowboy boots and Eiffel Tower. Which gives: huge crowds of fat tourists in tall, dull buildings. But you always [...]]]></description>
			<content:encoded><![CDATA[<p>Until now, I&apos;ve always had a certain respect for Sybase database.<br />
Based on their history, I thought that the product is a sort of MS SQL<br />
without the glitzy features &#8211; think Las Vegas without the lights, the cowboy boots and Eiffel Tower. Which gives: huge crowds of fat tourists in tall, dull buildings. But you always have Celine Dion, right ?*</p>
<p>Wrong ! Sybase ASE is a large, enormous, huge piece of steaming &#8230;<br />
ummm &#8230; code. Ok, ok, I&apos;m a bit over-reacting. In fact, Sybase is a<br />
very good database &#8211; if you are still living in the 90s and the only<br />
Linux flavour that you are able to manage is RedHat ASE. Otherwise,<br />
it&apos;s a huge &#8230; you know.</p>
<p>Let&apos;s not talk about the extreme fragility of this &#8230; this product.<br />
You never know when it crashes on you without any specific reason.<br />
Sometimes, it&apos;s the bad weather. Crash. Restart. Sometimes, you<br />
flushed twice. Crash. Restart. And maybe, yes maybe, you spent more<br />
than 12 minutes in your lunch break. Crash.</p>
<p>Let&apos;s just talk about the JDBC drivers &#8211; latest version, downloaded<br />
from the site in a temporary moment of insanity. Man, this is cutting<br />
edge. The sharpest cutting edge you&apos;ll ever find &#8211; the more advanced<br />
JDBC drivers bar none ! Excepting of course the fact that these<br />
classes were compiled in that memorable day of 6 January 2002 [the day<br />
when the last Sybase JDBC drivers were compiled]. But, don&apos;t let such<br />
obscure details ruining your enthusiasm. Just download and use them<br />
and you&apos;ll be amazed at their unique features &#8211; it&apos;s the only JDBC<br />
driver which manages to put down DbVisualizer in different and<br />
innovative ways. I&apos;m restarting the poor thing (dbvis) at least 2 or 3<br />
times per day, when working with Sybase.</p>
<p>Also, as a little quasi-undocumented tip, the letter <em>d</em> from<br />
jconn2d.jar does not mean <em>development</em> [drivers] as some of you would be<br />
inclined to think. In fact, it means <em>debug</em> which is the<br />
abbreviation for <em>put me in production poor lousy bastard and I&apos;ll<br />
start spewing reams of useless messages through all the logging APIs<br />
known by man and a few yet to be discovered, therefore instantly<br />
slowing down to a crawl your puny little software</em>.</p>
<p>Ermmm &#8230; well, all this nice introduction just to humbly confess that<br />
we do have a couple of them Sybase licences floating around here and<br />
some of our production databases are on Sybase ASE. While I can assure<br />
you that this is going to change at least on the web backend, it&apos;s<br />
also true that the beast must be alive in order to keep our company up<br />
and running. And, that&apos;s part of my job.</p>
<p>Which is of course very strange for an IT management job. But then again:<br />
when your sole DBA is overwhelmed by a horde of Sybase-specific tasks<br />
(like for instance the log configured to truncate at a specific<br />
threshold which naturally [for Sybase] does not truncate, suddenly<br />
throwing all the users into log suspend in the middle of the peak<br />
production time) &#8211; you have to enter into the damn kitchen and do some<br />
cooking !
<p>My endeavour was to perform simple data mining in order to migrate<br />
some reports from a legacy system [no, you don&apos;t really want to know<br />
what system]. Due to my limited time, starting a mildly complex Java<br />
reporting project was out of the question, so a scripting language was<br />
the natural choice. Python being the first option &#8211; unfortunately,<br />
finding a working Sybase driver for Python is a challenge in itself.<br />
But, thank God for Jython and zxJDBC ! In just a few minutes I was<br />
wiring the tables for reporting. Here&apos;s a fake code snippet which lists the &apos;orders&apos; with amounts < 1000, and you can&apos;t go any simpler:</p>
<pre>
from com.ziclix.python.sql import zxJDBC 

conn = zxJDBC.connect("jdbc:sybase:Tds:myserver.mydomain.com:4110/mydb",\
	"user","pass","com.sybase.jdbc2.jdbc.SybDriver")
cursor = conn.cursor() 

cursor.execute("select count(orderid) from orders")
nb_orders=cursor.fetchone()[0]
print &apos;%.0f total orders ...&apos;%(nb_orders,)

cursor.execute("select orderid, amount from orders where amount <1000")
oids=cursor.fetchall()
for o in oids:
	print &apos;Order %.0f for amount %.2f&apos;%(o[0],o[1])

cursor.close()
conn.close()
</pre>
<p>Easy as pie. And once you got one down, you got&apos;em all. For instance,<br />
yesterday evening I wrote in about an hour a small Jython script which<br />
exports some data. The same export process (running about an order of<br />
magnitude slower) needed previously a couple days of development in<br />
FoxPro. Ah, FoxPro - very juicy subject, but I&apos;ll keep it for my next<br />
horror story. Until then, don&apos;t forget, when you have a monster to<br />
tame and no time at all: try Jython !</p>
<p>*Let&apos;s suppose for a very brief instant that having Celine Dion at a certain location is a positive thing.</br></p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/sybase-woes-and-jython-saves-the-day/tools/20050202/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Searching for a working Python plugin in Eclipse 3.0M3 ?</title>
		<link>http://www.netuality.ro/searching-for-a-working-python-plugin-in-eclipse-30m3/tools/20041029</link>
		<comments>http://www.netuality.ro/searching-for-a-working-python-plugin-in-eclipse-30m3/tools/20041029#comments</comments>
		<pubDate>Fri, 29 Oct 2004 05:58:29 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/searching-for-a-working-python-plugin-in-eclipse-30m3/uncategorized/20041029</guid>
		<description><![CDATA[If Trustudio Python plugin stops functioning after installing the shiny new Eclipse 3.0M3, try pydev instead. I&apos;ve been using it for the last few hours &#8211; so far, so good. Well, you&apos;ll get nothing more than some syntax coloring, but that&apos;s the current level of all Python plugins for Eclipse for now.
]]></description>
			<content:encoded><![CDATA[<p>If <a href="http://www.xored.com/" target="_new">Trustudio</a> Python plugin stops functioning after installing the shiny new Eclipse 3.0M3, try <a href="http://sourceforge.net/projects/pydev/" target="_new">pydev</a> instead. I&apos;ve been using it for the last few hours &#8211; so far, so good. Well, you&apos;ll get nothing more than some syntax coloring, but that&apos;s the current level of all Python plugins for Eclipse for now.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/searching-for-a-working-python-plugin-in-eclipse-30m3/tools/20041029/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using jython to internationalize a PHP app</title>
		<link>http://www.netuality.ro/using-jython-to-internationalize-a-php-app/tools/20040301</link>
		<comments>http://www.netuality.ro/using-jython-to-internationalize-a-php-app/tools/20040301#comments</comments>
		<pubDate>Mon, 01 Mar 2004 14:20:01 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/using-jython-to-internationalize-a-php-app/uncategorized/20040301</guid>
		<description><![CDATA[At first, this might seem a mind-boggling combination. What do
 jython and PHP have in common (excepting the fact that I am a Python fan
and my current consulting task is in a PHP project) ?
Well, internationalizing a PHP app is pretty much a trivial task.
If you are a sensible PHP programmer insisting to use PEAR [...]]]></description>
			<content:encoded><![CDATA[<p>At first, this might seem a mind-boggling combination. What do<br />
<a href="http://www.jython.org/" target="_new"> jython</a> and PHP have in common (excepting the fact that I am a Python fan<br />
and my current consulting task is in a PHP project) ?<br />
Well, internationalizing a PHP app is pretty much a trivial task.<br />
If you are a sensible PHP programmer insisting to use PEAR instead of randomly choosing a script from the tons of snippets<br />
populating the &#8220;scripting websites&#8221;, <a href="http://pear.php.net/package-info.php?pacid=129" target="_new">I18N</a> is probably the<br />
safest choice.<br />
Maybe &#8211; for you &#8211; application maintainability and performance are not exactly important concerns.<br />
For me, they are. This is why I chose to store internationalized texts in files rather than database.<br />
I&apos;d rather keep the database for real data, which is created, modified, aggregated and such.<br />
And I&apos;d rather like to have an internationalized error message on the screen even if the database is down.<br />
Now we know that we&apos;ll use I18N and text will be kept in some php files. However, I am no professional translator and<br />
have no desire to translate or to manually maintain the correspondence between translators files and PHP files<br />
(no, translators won&apos;t modify PHP code, stop this nonsense right away).<br />
Code generation comes immediately in mind.<br />
Basically, my first idea was to investigate wether the files used by the translators can be quickly transformed to PHP,<br />
and if I am able to generate their formats from my own files (aka. &#8220;roundtrip internationalization process&#8221; ?).<br />
Unfortunately, this is not an easy task &#8211; as the only clue was that the translators use Office tools such as Word or Excel, because they<br />
rely upon some specialized translation software integrated with these products.<br />
The easy choice is Excel, since it allows a better organization of data than having to search for tables in a Word document.<br />
The hard choice is the tool that I&apos;d use for automatically reading and even generating Excel files.<br />
<br />
The difficulty comes from the fact I don&apos;t have Windows with Office installed on my desktop, just Gentoo Linux and OpenOffice.<br />
Thus, I am unable to write a simple Python script which could perform my generation tasks via automation.<br />
Fortunately, this is not the first time I am confronted with the issue.<br />
I happen to know that there is a very nice Java tool that I wholeheartedly<br />
recommend for your Excel processing needs :<br />
<a href="http://www.andykhan.com/jexcelapi/" target="_new">JExcelApi</a>.<br />
<br />
Still, Java is a heavyweight programming language &#8211; it would be a really bad idea to fire up the</p>
<href a="http://www.eclipse.org" target="_new">monster</a> just for some easy processing of Excel files.<br />
Here&apos;s why Jython comes naturally into equation. Four hours and about<br />
100 lines of debugged code later, here I am sitting on top of a perfectly functional internationalization tool which :</p>
<li> generates PHP code from a big xls file (the root vocabulary) which centralizes all the internationalization texts</li>
<p></p>
<li> generates 2-language xls files for translators usage</li>
<p></p>
<li> updates the root vocabulary starting from the files modified by the translators</li>
<p>
Automation scripts are already in cron and there&apos;s also a nice text document explaining translators where to get<br />
their files and where to put them after modification. The resulting script is not exactly fast, but this is tooling<br />
and not production so this should not be a problem after all.<br />
<br />
Whatever your project contraints are, give Jython a try and you&apos;ll be amazed &#8230; As they put it on the<br />
<a href="http://uselesspython.com" target="_new">Useless Python</a> site &#8211; <strong>If it were any simpler, it would be illegal.</strong> <br />
Finally there&apos;s a trick not quite related with Jyhon, nevertheless interesting.<br />
There is an easy way of solving the problem of translating phrases with real data inside them, with easy parameter swapping.<br />
We&apos;ll use the good old <strong>sprintf</strong> but not directly. We&apos;ll pass through a not so popular but extremely useful function,<br />
<a href="http://www.php.net/call_user_func_array" target="_new">call_user_func_array</a>. Suppose that our example needs the<br />
user name and authorization profile description to display inside a nice message. All you have to do is to define placeholders<br />
in I18N files which would fit as the first argument for sprintf. The following example should make it clearer:</p>
<table cellspacing="2" border="0" cellpadding="2" align="center" bgcolor="white">
<tbody>
<tr>
<td bgcolor="#89d2ff">localization/en/login.php</td>
</tr>
<tr>
<td bgcolor="#d3ffb4">
<pre>
$messages = array(
&apos;loggedin&apos;=>&apos;You are authenticated successfully as user %1$s with profile %2$s.&apos;
);
$this->set($messages);
</td>
</pre>
</tr>
<tr>
<td bgcolor="#89d2ff">localization/fr/login.php</td>
</tr>
<tr>
<td bgcolor="#d3ffb4">
<pre>
$messages = array(
&apos;loggedin&apos;=>&apos;Vous avez le profile %2$s en tant qu&apos;utilisateur %1$s.&apos;
);
$this->set($messages);
</td>
</pre>
</tr>
<tr>
<td bgcolor="#89d2ff">Simple passing of multiple parameters to I18N in PHP. Example function without error processing or data domain checking.</td>
</tr>
<tr>
<td bgcolor="#d3ffb4">
<pre>
#this is the multiple parameter function
function complexTranslation($i18n, $label, $params)
{
  return call_user_func_array(&apos;sprintf&apos;,array_merge(array($i18n->_($label)),$params));
}
</td>
</pre>
</tr>
<tr>
<td bgcolor="#89d2ff">Then, you have to initialize your I18N object. This can be done in a generic manner for all pages.</td>
</tr>
<tr>
<td bgcolor="#d3ffb4">
<pre>
#specific I18N initialization stuff
require_once &apos;I18N/Messages/File.php&apos;;
$g_language_dir = dirname($_SERVER[&apos;PATH_TRANSLATED&apos;]).&apos;/localization/&apos;;
$i18n =&#038; new I18N_Messages_File($g_langCode,$script_name,$g_language_dir);
</td>
</pre>
</tr>
<tr>
<td bgcolor="#89d2ff">Finally, use the function.</td>
</tr>
<tr>
<td bgcolor="#d3ffb4">
<pre>
#translate the successfull login message
$loginbox = Tools::complexTranslation($i18n,&apos;loggedin&apos;,array($operator->name,$profile->description));
</td>
</pre>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/using-jython-to-internationalize-a-php-app/tools/20040301/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The real big deal with Eclipse 3.0M7 &#8230;</title>
		<link>http://www.netuality.ro/the-real-big-deal-with-eclipse-30m7/tools/20040214</link>
		<comments>http://www.netuality.ro/the-real-big-deal-with-eclipse-30m7/tools/20040214#comments</comments>
		<pubDate>Sat, 14 Feb 2004 14:28:21 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[velocity]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/the-real-big-deal-with-eclipse-30m7/uncategorized/20040214</guid>
		<description><![CDATA[&#8230; is that 99% of plugins developed for previous versions 2.x-M4 should now be able to run again, unmodified, starting with release M7, due to &#8220;additional runtime compatibility mechanisms&#8221; ! This was already announced on Ed Burnette&apos;s blog as well as in the Eclipse porting guide, but I have just checked that a plugin I&apos;m [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230; is that 99% of plugins developed for previous versions 2.x-M4 should now be able to run again, unmodified, starting with release M7, due to &#8220;additional runtime compatibility mechanisms&#8221; ! This was already announced on Ed Burnette&apos;s <a href="http://www.eclipsepowered.org/archives/000012.html" target="_new">blog</a> as well as in the Eclipse <a href="http://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.eclipse.platform.doc.isv/porting/eclipse_3_0_porting_guide.html#General%20Information%20on%20Compatibility" target="_new">porting guide</a>, but I have just checked that a plugin I&apos;m currently developing, which stopped working in M5, is alive and kicking in M7, as promised.<br/><br />
But it didn&apos;t stop here ! The next trick I did was to copy every directory from &apos;features&apos; and &apos;plugins&apos; from my older 2.1.2 install, copy all the workspace content and import the settings. Now, all my projects and my &#8220;good old&#8221; plugins are installed inside a shiny new Eclipse. And (almost) everything is  working.<br/><br />
In case you&apos;re interested, here&apos;s my list of plugins and some observations based on simple 5-minute functionality tests:<br/><br />
<a HREF="http://spindle.sourceforge.net/" target="_new">Spindle</a> 0.0.37, the Tapestry plugin &#8211; close to full functionality, with some error reports in the log which seem to be related with validity checking of .jwc and .page files.<br/><br />
<a HREF="http://brosinski.com/stephan/archives/000028.php" target="_new">Regex tester</a> 0.9.0, regular expressions evaluations tool &#8211; ok<br/><br />
<a HREF="http://quantum.sourceforge.net/" target="_new">Quantum</a> 2.2.4b , managing SQL files, run SQL scripts against DB &#8211; working <br/><br />
<a HREF="http://jfacedbc.sourceforge.net/" target="_new">Jfacedbc</a> for RDB and data management &#8211; works fine<br/><br />
<a HREF="http://www.azzurri.jp/en/software/clay/index.jsp" target="_new">Clay</a> for RDB roundtrip design &#8211; nope, because it needs GEF 2.1.X which is impossible to enable under 3.0, GEF backwards compatibility would be nice<br/><br />
<a HREF="http://csseditor.sourceforge.net/" target="_new">CSS editor</a> 0.0.3 &#8211; working, but this should not be a surprise since the plugin is only for 3.0 stream<br/><br />
<a HREF="http://codesugar.sourceforge.net/" target="_new">Codesugar</a> 0.2.1 &#8211; ok<br/><br />
<a HREF="http://pydev.sourceforge.net/" target="_new">Pydev</a> 0.3 &#8211; Python developement environment &#8211; ok<br/><br />
<a HREF="http://eclipsecolorer.sourceforge.net/index_profiler.html" target="_new">Profiler</a> 0.5.30 &#8211; what a great profiling tool. Working fine.<br/><br />
<a HREF="http://veloedit.sourceforge.net/" target="_new">VelocityUI</a> 1.0.2, for editing Velocity templates &#8211; ok.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/the-real-big-deal-with-eclipse-30m7/tools/20040214/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maven-less Codehaus</title>
		<link>http://www.netuality.ro/maven-less-codehaus/tools/20031206</link>
		<comments>http://www.netuality.ro/maven-less-codehaus/tools/20031206#comments</comments>
		<pubDate>Sat, 06 Dec 2003 13:31:57 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.netoo.loco/maven-less-codehaus/uncategorized/20031206</guid>
		<description><![CDATA[While I think that Codehaus is an exceptional provider of open-source software (some of the projects hosted there are really shining), I&apos;m a little horrified by all their Maven-generated sites. It&apos;s not because I&apos;m ignorant to Maven usefulness, but BECAUSE I&apos;ve worked extensively with Maven since the beta7 days (August 2002, if i remember well [...]]]></description>
			<content:encoded><![CDATA[<p>While I think that <a HREF="http://www.codehaus.org" target="_new">Codehaus</a> is an exceptional provider of open-source software (some of the projects hosted there are really shining), I&apos;m a little horrified by all their Maven-generated sites. It&apos;s not because I&apos;m ignorant to Maven usefulness, but BECAUSE I&apos;ve worked extensively with Maven since the beta7 days (August 2002, if i remember well ?) and gave up in April this year, replacing everything with Ant tasks and customized Python scripts. Painful memories of strange bugs (compatibility issues from a version to another, proxy problems, not being able to create a simple and primitive CVS log, or test suites for one of our projects not executing under Maven due to some obscure, unsolved class loader problems) are haunting me. But, the most frustrating issue on Codehaus is the &apos;Mavenized&apos; sites &#8211;  superfluous clicks and a number of pages you have to see again and again just to download the latest version of a certain project &#8230; a not so strange resemblance with the <a HREF="http://www.jroller.com/page/fate/20031201#awkward_download_links" target="_new">horrendous</a> structure of the Jakarta site.<br/><br />
The simplest solution is just ignore the project sites on Codehaus and go directly to the <a HREF="http://dist.codehaus.org/" target="_new">root</a> of the download repository. Only by looking at directories dates, you can guess if a new version was released. And as a small bonus, you&apos;ll find there some (still incubating ?) projects that aren&apos;t even referenced on the Codehaus main page. There is <a HREF="http://jmock.codehaus.org/getting-started.html" target="_new">JMock</a>, which looks like a easier-to-use <a HREF="http://www.easymock.org/index.html" target="_new">EasyMock</a>-like library (but it doesn&apos;t seem like being up to EasyMock on functionality level). And a nice <a HREF="http://spice.codehaus.org/" target="_new">Spice</a> project, a sort of library of IoC-able components with multi-container support, some of them worth a look (JNDIKit, ThreadPool).<br/><br />
You know what would be really nice ? Being able to subscribe to RSS feeds containing release information a la SourceForge &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netuality.ro/maven-less-codehaus/tools/20031206/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
