Archive for January, 2008

Google Charts

Thursday, January 31st, 2008

There are handful feasible flash based charting solutions, and they just work really great - with interaction. But unfortunately most of those are not open source, nor free. Few months ago(may be it has been there for longer?), google released a chart api which can generate a PNG image based on your data.

The charts API very easy to use, and everything is encoded in the URL. So, you can either download the image and host it on your servers, or rather use that in the web page itself without any troubles at all.

Yesterday, I gave it a try. I got some of my apache logs, parsed them, and used google APIs to draw the charts. The results look good.

Bar Chart

The log files are too big to parse quickly and contains lot of junk data. So, I wrote the code so that it only takes the “200 OK”, and ignores “js,css,png,jpg,gif” requests. Here is the php code.

	$ignored = array('css','js','png','jpg','gif');

	$vals = array();

	$f = fopen("/var/log/apache2/access.log","r");
	while (!feof($f)){
		$line = fgets($f);
		preg_match("/(.*) - - \[(.*)\] \”GET (.*) HTTP\/1.1\” 200/”,$line,$matches);
		// If it’s not 200 OK - just ignore it
		if (empty($matches))
			continue;
		$path = pathinfo($matches[3]);
		if (in_array($path["extension"],$ignored))
			continue;
		$time = strtotime($matches[2]);
		$month = date(”M/y”,$time);
		$vals[$month]++;
	}

	function text_encode($vals,$max) {
		$tvals = array();
		foreach($vals as $val) {
			$tvals[] = round($val/$max*100,1);
		}
		return implode($tvals,”,”);
	}

	function get_y_axis($vals) {
		$max = max($vals)+3000;
		$step = $max/5.0;
		$temp = array();
		for($i=0;$i<5;$i++)
			$temp[] = round($i*$step);
		$temp[] = $max;
		return implode($temp,"|");
	}

	echo "http://chart.apis.google.com/chart?chs=500x300&chd=t:"
			.urlencode(text_encode($vals,max($vals)+3000)).
			"&cht=bvg&chbh=50&chxt=x,y&chxl=0:|".
			urlencode(implode(array_keys($vals),'|')).
			"|1:|".urlencode(get_y_axis($vals))."\n";

Even though this contains code for ommiting unrelated results, it takes too much time. So, you can use the piping to create a simple log file, which is reasonably speed than running this through the whole log file. For example I use this command to create a smaller version of the log file.

cat sandaru1_log | grep 'HTTP/1.1" 200' | grep -v '.css HTTP'
	| grep -v '.png HTTP' | grep -v '.js HTTP'
	| grep -v '.jpg HTTP' | grep -v '.gif HTTP' > log

Google Charts also provides ability to generate pie charts. It’s easier to use a pie chart for browser percentages.

Pie Chart

Here is the code :

	$vals = array();

	function parseUserAgent($ua)
  	{

    	$userAgent = array();
 		$agent = $ua;
    	$products = array();

		$pattern  = "([^/[:space:]]*)” . “(/([^[:space:]]*))?”
		.”([[:space:]]*\[[a-zA-Z][a-zA-Z]\])?” . “[[:space:]]*”
		.”(\\((([^()]|(\\([^()]*\\)))*)\\))?” . “[[:space:]]*”;

		while( strlen($agent) > 0 )
		{
			if ($l = ereg($pattern, $agent, $a))
			{
				// product, version, comment
				array_push($products, array($a[1],    // Product
                                        $a[3],    // Version
                                        $a[6]));  // Comment
				$agent = substr($agent, $l);
			}
			else
			{
				$agent = “”;
			}
		}

		// Directly catch these
		foreach($products as $product)
		{
			switch($product[0])
			{
				case ‘Firefox’:
				case ‘Netscape’:
				case ‘Safari’:
				case ‘Camino’:
				case ‘Mosaic’:
				case ‘Galeon’:
				case ‘Opera’:
					$userAgent[0] = $product[0];
					$userAgent[1] = $product[1];
					break;
			}
		}

		if (count($userAgent) == 0)
		{
			// Mozilla compatible (MSIE, konqueror, etc)
			if ($products[0][0] == ‘Mozilla’ &&
            	!strncmp($products[0][2], ‘compatible;’, 11))
			{
				$userAgent = array();
				if ($cl = ereg(”compatible; ([^ ]*)[ /]([^;]*).*”,
                           $products[0][2], $ca))
				{
					$userAgent[0] = $ca[1];
					$userAgent[1] = $ca[2];
				}
				else
				{
					$userAgent[0] = $products[0][0];
					$userAgent[1] = $products[0][1];
				}
			}
			else
			{
				$userAgent = array();
				$userAgent[0] = $products[0][0];
				$userAgent[1] = $products[0][1];
			}
		}

		if (strstr($userAgent[1],”http:/”))
			$userAgent[1] = “”;

		return $userAgent[0]
			.($userAgent[0]==”"||$userAgent[1]==”"?”":” “)
			.$userAgent[1];
	}

	$f = fopen(”log”,”r”);
	while (!feof($f)){
		$line = fgets($f);
		preg_match(”/([\d.]+).* [^ ] [^ ] \[(.*?)\] (.*?) (.*) (.*)”
				.” (\d+) ([^ ]+) (.*?) \”(.*?)\”/”,
					$line,$matches);
		$bot = parseUserAgent($matches[9]);
		$bot = preg_replace(”/Firefox 2.*/”,”Firefox 2″,$bot);
		$bot = preg_replace(”/Firefox 1.*/”,”Firefox 1″,$bot);
		$vals[$bot]++;
	}

	$others = 0;

	foreach($vals as $key => $val)
		if ($val<500) {
			$others += $val;
			unset($vals[$key]);
		}

	$vals['Others'] = $others;
	$vals['Unknown'] = $vals['-'];
	unset($vals['-']);

	$lables = array();
	function text_encode($vals,$sum) {
		global $lables;
		$tvals = array();
		foreach($vals as $key => $val) {
			$tvals[] = round($val/$sum*100,1);
			$lables[] = $key.” (”.round($val/$sum*100,2).” %)”;
		}
		return implode($tvals,’,');
	}

	echo “http://chart.apis.google.com/chart?cht=p&chd=t:”.
			urlencode(text_encode($vals,array_sum($vals))).
			“&chs=700×400&chl=”.
			urlencode(implode($lables,”|”)).”\n”;

This code will get the user agent, parse it and generate a pie chart. The user agent parse function is by dotvoid.com.

Blog Syndication

Thursday, January 31st, 2008

Since the web 2.0 bubble expanded, a new word has been added to the dictionary (of course it has been there for technology geeks for a long time) called RSS. It’s so simple so that when combined with GNU naming schemes, you can call that “RSS Stands for Simple” (Note: in case you are wondering, yes, this is not the right term :) ).

The great thing about RSS is you can keep track of your favourite blogs, without ever going there to check for new updates. Just by using a RSS Reader(I use google reader), the newly posted items will be just there.

However, the “web 2.0″ concept is not just about AJAX or RSS or rather whatever technology. It’s more of the community, the bunch of people with same interests get together and use their creativity instead of automated robots to generated rich quality content. The same thing happens when you start blogging, people read your blog, then put comments, or rather write an offensive post on their blog, and so on… This blogsphere is what makes bloggers ticking.. what makes blogging interesting..

As with the Sri Lankan blogs, there is a great community built around kottu.org which has been there for several years. Niro also just started a blogging community for Sri Lanka called slblogs.org. They have just started, so at the moment there are not much of blogs there, but it’ll eventually grow. Although since the Sri Lankan blogsphere is relatively small, I’m not sure there is enough ground for a battle. In my personal opinion, It would be more interesting to see a blogsphere for growing number of Sinhalese blogs.

VirtualBox

Friday, January 11th, 2008

One headache of web development is that there are tons of browsers which behave differently from each other. So, for a better quality we should always test sites in different browsers as much as possible. There is a well known fact : among all the browsers, most annoying browser is IE 6.0. But no matter how annoying there are still people who are using it. So, we should always test it in IE. There is a project to get IE running under wine, but I couldn’t get it working for some reason.

So, I tried VirtualBox which is obviously not as fast as wine, but more accurate. VirtualBox seems to show more performance than VMWare(No guarantees - I have only used VMWare once). It’s worth checking that out.

VirtualBox

Say Cheese

Tuesday, January 1st, 2008

It’s new year, 2008. Time to smile :)

Few days ago, I’ve been playing around with a pretty old USB webcam. I just plugged in it, and v4l(Video for Linux) drivers detected that fine (”dmesg | tail” would do the trick for checking what has been going in the system).

Since I don’t any specific webcam capture apps, I just used VLC to do some little testing. By running “vlc v4l:/dev/video0″, the green light on the top of the webcam turned on (turning on a small smile on my face :) ) and the video showed up. But it was about 60×60 size (and the smile faded away). So, I experimented with several sizes, and the best worked so seemed to be “320×240″.

Now, assuming that it’s enough for my needs (I don’t really need this anyway), I decided to install a webcam app. The “Cheese” from gnome foundation looked promising, So, I downloaded the code, compiled and installed it. bham, there is nothing, just the gtk widget background with a gnome hand imprinted.

I guessed that the both problem and solution should lie in the gstreamer settings. So, I downloaded and installed the newest stable version of gstreamer(0.10.15), plugins-base(0.10.15), plugins-good(0.10.6) and plugins-ugly(0.10.6). But as a matter of fact, it didn’t have any effect on “Cheese”, but to break my mp3 playing capabilities of totem. Later on I found out it’s due to some plugins aren’t not compiled to properly, so compiling them fixed the mp3, but not the webcam app.

However, after going through the Cheese FAQ, I found out that I have to set some properties from the gstreamer-properties dialog and just blaming myself for not thinking of checking FAQ before going to all the hassle of compiling gstreamer, I changed the settings as it said (ximagesink something - I can’t remember now), then fired up Cheese.

Whoa, the webcam is blinking and suddenly the video appeared. But their seems to be small problem with the video, 3/4 of the image is blank. Only top 1/4 is displayed properly. First, I though it’s a temporarily problem, so I did a “rmmod and modprobe” to reset the device, but it didn’t help. So, I fired up cheese from the command line to see what’s going on. First it was detecting the webcam, then the sizes it can support (in other words the available “modes”). Then, it’s selecting so called the best mode, which is the largest.

For my webcam that was a weird size something with 288 x XXX (Sorry I can’t remember that either now). So, I tried that size with the VLC, and it’s the same results. As you can guess it’s not a problem with gstreamer but the V4L drivers. I looked for any cheese configuration file to set the preferred “mode” of the webcam, but unfortunately the product is still very young.

I didn’t want to mess with the V4L drivers, so I had a look at the Cheese source code. There is an universal truth about everything, it’s always easier to break things rather than fix them. So, I just break the webcam mode detection code which leads into my hardcoded preferred webcam settings. Changes are done in cheese-webcam.c, and here is the diff file - just in case.

Cheese Screenshot

Now, It’s time to say Cheese, and Happy New Year!