cooking, programming and everyday life xrado

Sunday, August 28, 2011

wmon - web server monitor

wmon or web monitor for Linux servers is tool I made about 3 years ago. The idea was to get a better picture of web server load. That's how it looked back in 2008.



A few lines of PHP and bash commands and chart made with GD library. Turned out to be quite useful. I gave it also to some friends and the totally forgot about it. Then one day a friend mention me, what about wmon, its very cool tool, are you planing any updates. I've been quite happy to hear it and that gave me some momentum to actually push it further.

I've found a nice charting tool dygraphs, that draws canvas charts and also have zooming in some other cool features. Dygraph relay gave mi some good options to add additional features, like top processes and services status changes for any pointed time on chart. I've also added easy way to include external wmon in to one report. Thats how you can monitor all servers from one location.


Turned out pretty good and probably useful for others, so i decide it to sell it on codecanyon.net. Hopefully it will buy me some beer :). If you are interested you can get it and try it here. Thanks!

Wednesday, July 14, 2010

php slow log

A few days ago a friend called me, asking me how could he find the slowest PHP scripts on its server? ..and didn't think of anything. Of course there are tools like xdebug, but they are only useful in development. If you have a server with hundred websites and you are trying to find out what it taking the most of your cpu time, you will probably need something like mysql slow query log. 

I remembered that php.ini has auto_prepend_file and auto_append_file setting, and that can help me wrap every php request with the timer. I made two simple scripts that wont add much extra overhead. It works exactly as mysql slow log. You just set up the SLOW_LOG_TIME and SLOW_LOG_FILE destination. All php requests that take more than SLOW_LOG_TIME will be logged. 

php.ini

auto_prepend_file = "/path_to/before.php"
auto_append_file = "/path_to/after.php"

before.php

<?php
define('SLOW_LOG_START',microtime(TRUE));

after.php

<?php
// Settings
define('SLOW_LOG_TIME', 0.5); // (sec)
define('SLOW_LOG_FILE', '/tmp/php_slow.log');

// Logging
define('SLOW_LOG_END', microtime(TRUE));
$time = SLOW_LOG_END - SLOW_LOG_START;
if ($time > SLOW_LOG_TIME)
{
	$log = date('Y-m-d H:i:s')."\t".round($time,3)."\t".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']."\n";
	file_put_contents(SLOW_LOG_FILE, $log, FILE_APPEND);
}
sample output with SLOW_LOG_TIME set to 0.1 sec ( on my home server P4 Celeron 2Ghz, 1Gb Ram )
2010-07-08 23:15:19	0.178	xrado.hopto.org/post/baked-lasagna-and-potatoes-kebab-style-seitan
2010-07-08 23:16:32	0.115	xrado.hopto.org/post/extract-emails
2010-07-08 23:16:34	0.13	xrado.hopto.org/
2010-07-08 23:16:38	0.121	xrado.hopto.org/post/going-freelance
...

Actually this wont tell you which are the slowest script, but you'll get the list of PHP requests that take the most processing time. That will give you the clue where to start looking.

Final notes:

  • do not set SLOW_LOG_TIME too low, otherwise your log will be screaming, your server too, depending on number of requests you get
  • check syntax in before.php and after.php, any error can break all your sites
  • remove auto_prepend_file and auto_append_file whey you are done, otherwise logs can go big and you don't need extra disk load

It will be nice to see your timings before and after the optimization.

Wednesday, January 21, 2009

Simple combining of multiple javascript and css files

I've already wrote about "firefox only includes styles form .css files" and I found out that isn't quite true. Actually firefox doesn't care about the css file extension, but only relay on header Content-Type: text/css. If you as usual have .css file, apache will take care of right content-type, otherwise you will have to take care about it.
header('Content-Type: text/css');
I came across this when i was writing this script:
## combine.php

// Define path prefix
$prefix = realpath('.');

if(!empty($_GET['js'])) {
	header('Content-Type: application/x-javascript');
	$data = Array('path'=>$prefix.'/template/js/','files'=>$_GET['js'],'ext'=>'.js');
} elseif(!empty($_GET['css'])) {
	header('Content-Type: text/css');
	$data = Array('path'=>$prefix.'/template/styles/','files'=>$_GET['css'],'ext'=>'.css');
} else exit();

foreach(explode(',',$data['files']) as $file) {
	if($file && file_exists($data['path'].$file.$data['ext'])) readfile($data['path'].$file.$data['ext']);
}
Simple few lines of code, but already do the trick. That will minimise number of server requests and benefit in faster page loading.

Defining the path and file extension is important, otherwise you may expose some other scripts source or even worse, some system files.

Usage in page head
<link rel="stylesheet" type="text/css" href="combine.php?css=style,forms" />
<script type="text/javascript" src="combine.php?js=mootools,validate,fx"></script>
Hope you like it, otherwise If you want more advanced solution try minify.

cheers

Thursday, December 13, 2007

PHP / Javascript Obfuscator

Have you ever want to prevent others sticking their fingers into your code? I did. I have searched over the web, but i didn't find anything suitable. Actually i didn't want to protect my code, but just make it harder to read and modify. So i made small script that do just that. The script strips all new lines, tabs, unneeded spaces and comments, so the code is braked in to one line. I didn't forget about php "here document" that i use quite a lot. This one needs new line right after the terminator, so if you using it, the output will have some more lines on the end.

I run this script from the linux shell as you see below, stored in to file comp.php. Just "cd" to directory where you have your php or js scripts and run the command. Find will recursively found all the *.php scripts and obfuscate them. Be careful before running the script!!! Always check the path you are in and do a backup copy, otherwise you might end up with a headache or even losing the code.

Usage
find . -iname "*.php" -exec php comp.php {} \;
find . -iname "*.js" -exec php comp.php {} \;
script:
// here document terminator
$here_document = "END";

error_reporting(0);

if(ereg($argv[0],$argv[1])) exit();

function cleanup($line){
	$line = preg_replace('/(^|\s)\/\/(.*)\n/','',$line); // remove line comments // comment
	$line = preg_replace('/(\t|\r|\n)/','',$line);  // remove new lines \n, tabs and \r
	return $line;
}

$lines = file($argv[1]);
echo $argv[1]." ";
echo "lines: ".count($lines)." -> ";
foreach ($lines as $line) {
        if(ereg($here_document,$line) && ereg("<<<",$line)) $out.= cleanup($line)."\n";
        else if(ereg("$here_document;",$line)) $out.= "\n".cleanup($line)."\n";
        else $out.= trim(cleanup($line))." ";
}
$out = preg_replace('/(\/\*[\s\S]*?\*\/)/', '', $out); // remove multi-line comments /* */

file_put_contents($argv[1],trim($out));	// store back to file

echo count(file($argv[1]))."\n";
Source: comp.php.txt