Debugging: Rules & Tools

12,628 views

Published on

Finding and fixing bugs is a major chunk of any developers time. This talk describes the basic rules for effective debugging in any language, but shows how the tools available in PHP can be used to find and fix even the most elusive error

Published in: Technology
2 Comments
23 Likes
Statistics
Notes
  • Thanks Dave, that means a lot! I had some great feedback, a lot of credit for which is definitely due to the great rules you laid out in your book.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Ian, I stumbled on this through a blogger at the International PHP conference. I am not a PHP developer, but I am the author of the book. I am very impressed by your use of the rules to introduce the tools -- of course, I'm convinced that this is a completely thorough and useful presentation as a result! Congratulations on a very well done presentation. I hope you had lots of enthusiastic attendees and good feedback.
    Dave Agans
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
12,628
On SlideShare
0
From Embeds
0
Number of Embeds
47
Actions
Shares
0
Downloads
240
Comments
2
Likes
23
Embeds 0
No embeds

No notes for slide

Debugging: Rules & Tools

  1. DEBUGGING R U L E S A N D TO O L S ian barber - http://phpir.com - @ianbarber
  2. I did X I wanted Y Instead I got Z
  3. http://www.debuggingrules.com
  4. RULE 1 UNDERSTAND THE SYSTEM
  5. Bug Wiki Tracker Frame work RTFM PHP Doc php.net
  6. $field = $document->getField($fieldName); if ($field->storeTermVector) { /** * @todo term vector storing support */ require_once 'Zend/Search/Lucene/Exception.php'; throw new Zend_Search_Lucene_Exception ('Store term vector functionality is not supported yet.'); }
  7. Komodo Eclipse Zend Studio TOOLS PHP Net Storm Text Beans Mate
  8. RULE 2 MAKE IT FAIL
  9. Recreate And Automate PHP Unit SimpleTest Selenium PHP Slim JMeter Ab
  10. Time Load Timing User Server CONTROL Env VARIABLES Request Client DB State Session
  11. [root@localhost ~]# pear channel-discover pear.phpunit.de [root@localhost ~]# pear install phpunit/PHPUnit class Test_User extends PHPUnit_Framework_TestCase { public function testUpdate() { $r = ("a", "b"); try { $u = User::fetch($this->newName); $result = $u->update($r); } catch (Id_Exception $e) { $this->fail($e->getMessage()); } $this->assertEquals($r, $u->getRoles()); } }
  12. http://seleniumhq.org/
  13. class Example extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("http://general.dev/"); } public function testMyTestCase() { $this->open("/"); $this->select("locale", "label=de"); $this->waitForPageToLoad("30000"); $this->assertTrue($this->isTextPresent( "Datenbank-Einrichtung")); } }
  14. http://jakarta.apache.org/jmeter/
  15. RULE 3 QUIT THINKING AND LOOK
  16. if($this->hasRoles) { $this->deleteRoles(); } try { foreach($submittedRoles as $role) { $this->addRole($role); } } catch(Identity_Exception $e) { $this->log->warn('Role add failed.'); throw new Service_Exception_BadRequest( 'Cannot add user role'); }
  17. Instrumentation: Inspect or Report
  18. Xdebug http://www.xdebug.org [root@localhost ~]# pecl install xdebug zend_extension=/usr/lib64/php/modules/xdebug.so
  19. xdebug.profiler_enable=1 xdebug.profiler_output_dir=/tmp
  20. xdebug.auto_trace=1 xdebug.collect_params=4
  21. Key Web Server PHP Script Key Debugging Client XDebug Debugging Commands
  22. xdebug.remote_enable=1 xdebug.remote_port=9000 xdebug.remote_host=192.168.192.1 #xdebug.remote_connect_back=1
  23. [root@localhost ~]# lsof -p 4365 COMMAND USER FD TYPE DEVICE NAME httpd apache mem REG 253,0 /lib64/libssl.so.0.9.8e httpd apache mem REG 253,0 /usr/lib64/php/modules/xdebug.so httpd apache mem REG 253,0 /usr/lib64/libsqlite3.so.0.8.6 [root@localhost ~]# strace -cp 4365 Process 6910 attached - interrupt to quit Process 6910 detached % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------- 36.91 0.037307 466 80 getdents 30.07 0.030393 950 32 7 access 17.04 0.017224 154 112 10 open 5.08 0.005136 12 444 9 lstat 3.87 0.003910 18 213 1 read 3.04 0.003071 29 107 close 2.57 0.002598 1299 2 writev 0.78 0.000785 1 631 stat
  24. [root@localhost ~]# strace -Tp 4365 Process 6910 attached - interrupt to quit epoll_wait(16, {{EPOLLIN, {u32=31389672, u64=47128707528680}}}, 2, 10000) = 1 <6.926140> accept(4, {sa_family=AF_INET6, sin6_port=htons(64930), inet_pton (AF_INET6, "::ffff:192.168.192.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [47128676139036]) = 17 <0.000094> fcntl(17, F_SETFL, O_RDWR|O_NONBLOCK) = 0 <0.000035> read(17, "POST / HTTP/1.1rnHost: general.d"..., 8000) = 522 <0.000044> stat("/mnt/hgfs/habari/htdocs/", {st_mode=S_IFDIR|0755, st_size=408, ...}) = 0 <0.000527> open("/mnt/hgfs/habari/htdocs/.htaccess", O_RDONLY) = 18 <0.000457> fcntl(17, F_SETFL, O_RDWR|O_NONBLOCK) = 0 <0.000037>
  25. [root@localhost ~]# strace -Tp 4365 Process 6910 attached - interrupt to quit epoll_wait(16, {{EPOLLIN, {u32=31389672, u64=47128707528680}}}, 2, 10000) = 1 <6.926140> accept(4, {sa_family=AF_INET6, sin6_port=htons(64930), inet_pton (AF_INET6, "::ffff:192.168.192.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [47128676139036]) = 17 <0.000094> fcntl(17, F_SETFL, O_RDWR|O_NONBLOCK) = 0 <0.000035> read(17, "POST / HTTP/1.1rnHost: general.d"..., 8000) = 522 <0.000044> stat("/mnt/hgfs/habari/htdocs/", {st_mode=S_IFDIR|0755, st_size=408, ...}) = 0 <0.000527> open("/mnt/hgfs/habari/htdocs/.htaccess", O_RDONLY) = 18 <0.000457>
  26. Zend Drupal Log syslog sfLogger Kohana Log error_log("Message for the PHP log") error_log("Log to email", 1, "me@foo.com"); error_log("Log to a file",3, "/tmp/m.log"); error_log("Message for the SAPI log", 4);
  27. MQ Syslog File LOGGING SYSTEM Gearman Database Pipe
  28. FirePHP
  29. [root@localhost ~]# pear channel-discover pear.firephp.org [root@localhost ~]# pear install firephp/FirePHPCore require_once('FirePHPCore/FirePHP.class.php'); ob_start(); $firephp = FirePHP::getInstance(true); doStuff($firephp); $firephp->warn('Done Stuff'); $firephp->error('An error!'); $firephp->log($_GET); ob_end_flush(); function doStuff($firephp) { $firephp->trace('Stuff Backtrace'); echo "This page intentionally blank"; }
  30. RULE 4 DIVIDE AND CONQUER
  31. <?xml version="1.0" encoding="UTF-8"?> <phpunit bootstrap="./TestHelper.php" colors="true"> <testsuite name="Commonlib Tests"> <directory>./library/Cl/</directory> <directory>./library/Sso/</directory> </testsuite> <filter> <whitelist> <directory suffix=".php">../Sso/</directory> <directory suffix=".php">../Cl/</directory> </whitelist> </filter> </phpunit>
  32. Folder Root CL SSO Auth Client Model User Adapter Plugin Exception Abstract SSO SFDC Gearman
  33. <?php $worker = new GearmanWorker(); $worker->addServer(); $worker->addFunction( "allow_access", "allowAccess"); $worker->addFunction( "deny_access", "denyAccess"); while ($worker->work());
  34. Git Bisect git bisect start git bisect bad git bisect good <known good rev> git bisect ? git bisect reset
  35. good bad 1 Request View 2 Front 3 Controller Plugin Input Model Filter Controller
  36. Firewall Cache Web Server Database
  37. Tamper Data Curl Firewall Wireshark Cache Netcat Web Server MySQL Proxy Xdebug Database
  38. Tamper Data https://addons.mozilla.org/firefox/addon/966
  39. Wireshark http://www.wireshark.org/
  40. [root@localhost ~]# { echo -ne "HTTP/1.0 200 OKrn rn"; cat test.html; } | nc -l 8080 GET / HTTP/1.1 User-Agent: curl/7.19.7 (i386-apple-darwin10.0.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3 Host: general.dev:8080 Accept: */* [root@localhost ~]# curl http://general.dev:8080 -v * About to connect() to general.dev port 8080 (#0) * Trying 192.168.192.129... connected * Connected to general.dev (192.168.192.129) port 8080 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (i386-apple-darwin10.0.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3 > Host: general.dev:8080
  41. local log_file = 'mysql.log' local fh = io.open(log_file, "a+") function read_query( packet ) if string.byte(packet) == proxy.COM_QUERY then local query = string.sub(packet, 2) fh:write( string.format("%sn",query)) fh:flush() end end MySQL Proxy
  42. RULE 5 CHANGE ONE THING AT A TIME
  43. [root@localhost ~]#: svn st M index.php [root@localhost ~]#: git stash save Saved working directory and index state WIP on master: 0e22fdd Initial checkin HEAD is now at 0e22fdd Initial checkin [root@localhost ~]#: git status # On branch master nothing to commit (working directory clean) Source Control
  44. [root@localhost ~]#: svn log . ------------------------------------------- r4341 | rickc | 2010-09-24 03:01 | 3 lines Don't test if Post::tags is empty before getting tags. There may be a performance hit for this. It can be dealt with if it is noticable. Fixes ticket #1235. Props to ilo for the patch. Note that Post still needs to be updated to use real Tags, not an array of slug/label pairs as the tags member. -------------------------------------------- Source Control
  45. Known Good [root@localhost ~]# diff -yw web.conf web2.conf <VirtualHost *:80> <VirtualHost *:80> ServerAdmin root@e.com ServerAdmin root@e.com DocumentRoot /www/htdocs | DocumentRoot /www/hdocs ServerName general.dev ServerName general.dev ErrorLog logs/error_log ErrorLog logs/error_log </VirtualHost> </VirtualHost>
  46. RULE 6 KEEP AN AUDIT TRAIL
  47. Hot Key Log http://www.blacktree.com/ http://do.davebsd.com/ https://launchpad.net/mb http://simplenoteapp.com/
  48. Backpack Journal http://backpackit.com/
  49. [root@localhost htdocs]# history 20 365 ls /mnt/hgfs/habari/ 366 ls 367 vi /etc/httpd/conf.d/web.conf 368 setenforce 0 369 /etc/init.d/httpd restart 370 vi /var/log/httpd/error_log 371 cd /mnt/hgfs/habari/ 372 ls 373 cd htdocs/ 374 ls 375 cd scripts/ 376 ls 377 cd .. 378 ls 379 vi /etc/php.ini
  50. RULE 7 CHECK THE PLUG
  51. Sources of Plugs [root@localhost ~]# apachectl -M Loaded Modules: core_module (static) mpm_prefork_module (static) http_module (static) so_module (static) [root@localhost ~]# whoami auth_basic_module (shared) root auth_digest_module (shared) [root@localhost ~]# ifconfig authn_file_module (shared) eth0 Link encap:Ethernet HWad authn_alias_module (shared) authn_anon_module inet addr:192.168.192.129 (shared) inet6 addr: fe80::20c:29ff: authn_dbm_module (shared)
  52. RULE 8 GET A FRESH VIEW
  53. if(!is_string($i)) { throw new Xapian_Exception('Incorrect query type, expecting string or array of strings'); } $q = $this->getParser()->parse_query($i);
  54. if(!is_string($i)) { throw new Xapian_Exception('Incorrect query type, expecting string or array of strings'); } $q = $this->getParser()->parse_query($i, FLAG_SPELLING_CORRECTION);
  55. “Grovelling is not a substitute for doing your homework” - ESR http://www.catb.org/esr/faqs/smart-questions.html
  56. RULE 9 IF YOU DIDN’T FIX IT - IT AIN’T FIXED
  57. Five Whys The page is blank: Why? There is a fatal error: Why? No mb_check_encoding(): Why? mbstring is not installed: Why? It isn’t part of the build: Why? It was setup for another project.
  58. The Rules 1. Understand The System 2. Make It Fail 3. Quit Thinking And Look 4. Divide And Conquer 5. Change One Thing At A Time 6. Keep An Audit Trail 7. Check The Plug 8. Get A Fresh View 9. If You Didn’t Fix It, It Ain’t Fixed
  59. Questions ?
  60. Image Credits When men were men and wore white coats - by Jitze http://www.flickr.com/photos/jitze1942/4292084185/ Vacuum Tube Etch-A-Sketch - by Jurvetson http://www.flickr.com/photos/jurvetson/197768962/ Classic - by Oskay http://www.flickr.com/photos/oskay/1364147095 Firmware Bug - by Oskay http://www.flickr.com/photos/oskay/1364148351 Ready to hop - by Oskay http://www.flickr.com/photos/oskay/1364153441/ Albino - by Oskay http://www.flickr.com/photos/oskay/1364143833 Coming Through! - by Oskay http://www.flickr.com/photos/oskay/1364147807 Tux the Pinguin - by Patrick van der Velden From the photographer’s private collection
  61. THANKANDTOOLS DEBUGGING: RULES YOU http://joind.in/2173

×