The nature of Internet applications creates an issue with debugging. For example, how do you debug an application that may be getting hundreds or even thousands of hits every minute? How do you debug this application without sending sensitive data to the user in the form of comments or debug statements that are “hidden” for only as long as nobody is looking for them? What do you do when you are unable to trigger an error but your user base is, though they lack the knowledge to be of much assistance other then “I borked it!”?

There are several new contenders on the debugging scene for PHP code, the most popular of which is FirePHP and their unholy union with FireBug. These two are great tools for debugging an Internet application but they both suffer from one fatal flaw in my eyes: the ability to view debugging information from anonymous Internet users.

Sure, it is a great feature to be able to hit a site and have debugging information pop up in a panel in my browser but how does that help me when dealing with users that I do not personally know? It doesn’t… Dumping data to a .log file offers several problems in and of itself, the largest of which is the rate at which said log file can reach an unwieldy size.

Another flaw in FirePHP is that sometimes you just want it short, sweet and not sent to the client. For years I have gone with a tried and true method of remote debugging which allows for me to view dumped data on a remote server. Yes, a REMOTE server… as in 3000 miles away and not in my browser.

UDP is a stateless Internet protocol which allows for no handshaking or error checking, this creates an almost “fire and forget” method of sending packets to a remote system. UDP is perfect when you do not want to stop things to make sure the other side gets the information and you don’t really care if there is even someone at the other end listening.

USAGE:

 php snippet
require_once("UDPDEBUG_CLASS.php");
$UDPDEBUG = new UDPDEBUG("127.0.0.1", 4545);
$UDPDEBUG->SEND("This is a simple test", 'LOW', TRUE);
    

Line:

1. Include the debugging class

2. Create a new object and tell it we are using the ip address 127.0.0.1 and port 4545

3. Send our data debug statement to the server with a low priority and display the PORT and LEVEL.

Three lines is all it takes to send the data off and we can easily replace “This is a simple test” with $our_value.

Reading this data can be done using several different tools but the one I will focus on here is Netcat, which is a network diagnostic tool.

From a command console (or windows CMD prompt with access to the NC binary) type:

nc -u -l -p 4545

This will start Netcat listening (-l) on UDP (-u) port (-p) 4545, now when we hit our udpdebug enabled page Netcat will spit out the information we wish to see. For this example I am using this test file:

 php (udptest.phps) download
<?
require_once("UDPDEBUG_CLASS.php");
$UDPDEBUG = new UDPDEBUG("127.0.0.1", 4545);
$UDPDEBUG->SEND("This is a simple test", 'LOW', TRUE);
$UDPDEBUG->SEND("This is a simple test", 'MEDIUM', TRUE);
$UDPDEBUG->SEND("This is a simple test", 'HIGH', TRUE);
$UDPDEBUG->SEND("This is a simple test", 'LOW', FALSE);
$UDPDEBUG->SEND("This is a simple test", 'MEDIUM', FALSE);
$UDPDEBUG->SEND("This is a simple test", 'HIGH', FALSE);
?>

    

Which produces the following output if everything works right:

The reason that UDP will send the port and level if requested is because I often assign a unique port number to each application I am working on. Meaning that I have created a simple application that listens full time on a list of ports I have specified. This way I can check and see if all of the sudden my_nifty_webapp.com is throwing a database error because its port number is 12127.

 php (UDPDEBUG_CLASS.phps) download
<?php
/**********************************************************************
*	Author:	Terry Valladon (terry@terryvalladon.com)
*	Web...:	http://www.terryvalladon.com
*	Name..:	UDBDebug Class
*	Desc..:	This class is used to send debug messages as a datagram packet to a UDP port
*
*	Notes.:	<IP ADDRESS>	= The IP address you want the packet sent to
*		<PORT>		= The port you want the packet sent to
*		<LEVEL>		= LOW, MEDIUM, HIGH
*		<VERBOSE>	= TRUE, FALSE - Display information like LEVEL and PORT
*
*	Usage.:	require_once("UDPDEBUG_CLASS.php");            
*		$UDPDEBUG = new UDPDEBUG(<IP ADDRESS>, <PORT>);
*		$UDPDEBUG->SEND($MESSAGE, <LEVEL>, <VERBOSE>);
*
*/

	class UDPDEBUG {
		public $IP_ADDRESS;
		public $PORT;
		public $UDP_OBJECT;
		public $ERR_NO;
		public $ERR_STR;
		public $ESC_CHR;
		public $LEVEL = array('LOW'=>0,'MEDIUM'=>1,'HIGH'=>2);
		public $LEVEL_WORDS = array(0=>'LOW',1=>'MEDIUM',2=>'HIGH');
		public $LEVEL_COLORS = array(0=>'GREEN',1=>'YELLOW', 2=>'RED');
		public $ANSI_BG = array('RED'=>'[41m','GREEN'=>'[42m','YELLOW'=>'[43m','CYAN'=>'[46m');
		public $ANSI_FG = array('RED'=>'[1;31m','GREEN'=>'[1;32m','YELLOW'=>'[1;33m','CYAN'=>'[1;36m');
		public $ANSI_SPECIAL = array('NORMAL'=>'[0m');

		function UDPDEBUG($IP_ADDRESS, $PORT){
			$this->ESC_CHR = chr(27);
			$this->IP_ADDRESS = $IP_ADDRESS;
			$this->PORT = $PORT;
		}

		function SEND($STRING, $LEVEL = 1, $VERBOSE = FALSE)
		{
			$LEVEL = $this->LEVEL[$LEVEL];
			if($VERBOSE == TRUE){
				$OUTPUT = sprintf("[%s]:%s:%s%s\n",$this->ESC_CHR.$this->ANSI_FG['CYAN'].$this->PORT,$this->ESC_CHR.$this->ANSI_FG[$this->LEVEL_COLORS[$LEVEL]].str_pad($this->LEVEL_WORDS[$LEVEL], 9),$this->ESC_CHR.$this->ANSI_SPECIAL['NORMAL'], $STRING);
			}else{
				$OUTPUT = sprintf("%s\n",$this->ESC_CHR.$this->ANSI_FG[$this->LEVEL_COLORS[$LEVEL]].$STRING.$this->ESC_CHR.$this->ANSI_SPECIAL['NORMAL']);
			}
			$this->UPD_OBJECT = fsockopen("udp://" . $this->IP_ADDRESS, $this->PORT, $this->ERR_NO, $this->ERR_STR);
			if (!$this->UPD_OBJECT) {
				echo "ERROR IN UDP SYSTEM: $this->ERR_NO - $this->ERR_STR<br />\n";
				return 0;
			}
			fwrite($this->UPD_OBJECT, $OUTPUT);
			fclose($this->UPD_OBJECT);
		}
	}
?>

    

Come back next week when we will modify our base UDPDEBUG class to add in array handling. This will enhance our debugging ability and open up for a future change of passing objects and even mysql record sets.

UPDATE.
Please visit part two of this article series at Remote debugging with UDP sockets part 2.

Till next week, code sexy.

–Terry Valladon

Share and Enjoy:
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • LinkArena
  • LinkedIn
  • Technorati
  • Tumblr
  • TwitThis
  • StumbleUpon

Technorati Tags: , , , , , ,

Leave a Reply

Spam protection by WP Captcha-Free