Just before you lanuch a PHP application
04 Feb 2009
Applications are buggy. Fact. To take professor Dijkstra's advice I won't call them bugs. I call them errors. Me, you, and other folks do err and these errors do sit in the software quietly ticking to go off when the circumstances arise. Improving software build process so the software is less fscked up does not come for free. In fact it's quite expensive, hence the popularity of Beta sign. Public beta phase is nothing more than employing consumers to do some free error hunting for you. The problem is however, that your targeted audience may just not bother doing your job.
Below you will find few tips I found in my last project – Blastbeat.tv.
Forget about users spontaneously reporting problems
Users do use beta software, but they mostly expect it to be of final version quality. Don't even bother placing "Report problem" link as floating-point number only slightly less than 100 per cent of users will actually use it. And even if somehow 50% of them did it's still merely half of all problems that go under the radar – not too good.
What you should do instead is to develop automated reporting utility. With PHP it is super easy. First, wrap whole application with try…catch statement. Once otherwise unhandled exception is thrown it gets sent via email. This way you get error reported immediately with complete stack trace included. No other user would give you that many details in their report.
Don't forget to redirect user to a friendly page apologizing for technical difficulties with link to 1. previous page, 2. home page. I can't stress enough importance of such links (I should probably blog about it some other day).
Other cheap trick is to redirect PHP errors output to a file. This way you catch all fatal errors, warnings and notices that are not normally reported via exceptions. Put these lines in .htaccess:
php_value error_log log/errors.txt
RewriteEngine On
RewriteRule log/* index.php [F]
Be sure to protect your logs with HTTP 403 status code.
I assume you are quite sane and write your programs with error_reporting set to E_ALL or E_ALL | E_STRICT.
"We are sorry, we were unable to recreate your problem"
Just before you go live make sure you can quickly deploy exact copy of live system on any other machine to recreate problems that occur on production box only. This may seem to you as unnecessary effort, but soon you will find it time-saver whenever new developer joins the team. My additional advice is to keep development environment as heterogeneous as possible. This will surface potential problems sooner than in one-OS, one-DB, one-PHP environment. It is also a very good idea to maintain test installation with db synchronized over night. Having exact copy of your live system will help you pin down errors and save your customer from hearing from you the above quotation.
Care about user experience yourself
As I mentioned earlier users don't bother reporting problems. This means that they also won't bother reporting their not-so-great experience with the site. Experience is something more subtle and elusive, and is not as easy to express as working/not-working situation. You will have to care about it before users turn away.
The most technical aspect of user experience is smoothness of navigation. Page load time is something you can measure using external tools like YSlow or internally just by comparing request and response time. You should also log slow database queries and use indices where appropriate. For MySQL just edit /etc/my.cnf file and add:
log-slow-queries=/var/log/mysql-slow-queries.log long_query_time=1
Read your reports
Now you can focus on reading reports coming to your mailbox. Some of them will be pretty obvious and easy to fix, some can be caused by session expiry, some other by outdated web browsers. The ones caused by web crawlers are particularly interesting as they point to an action that should be probably available only for logged user. Fix them one by one and you'll do great. I managed to take amount of emails from ca. 70 per day down to zero in one man-month. What's really interesting is that I was as same confident that software is relatively bug-free before launch as I am now. The difference is that now I can prove it really is.
- Dodek
"What you should do instead is to develop automated reporting utility. With PHP it is super easy."
You mean plain PHP? Altough I've never tried any of PHP frameworks, I can't help to notice that all serious Python web frameworks provide that functionality by default - usually you just need to configure it to suit your needs. This is the way of programming I would call "super easy".- stronger
In this case it really doesn't make any difference whether you handle it manually or via framework. In both scenarios sending email should take no more than 3 lines of code. By "super easy" I mean that average PHP developer already possesses enough knowledge to implement any of my suggestions, whereas using framework would first require him/her to learn functionality provided by a framework in order to use it.
To be fair I do believe the latter is cleaner/more appropriate.- Dodek
Sending an e-mail with 3 lines of code? That's unusual. Could you please tell me how is that supposed to work?
Come to think of it, it is actually possible - if one's using some convenient facility for sending e-mails. But if that's the case, it is no different than using a framework.- Michał Bachowski
@Dodek: have you ever heard about mail() function :>? You don`t have to send whole backtrace via e-mail but instead write it to file and only notice yourself about that:
try {
// my app code goes here
catch( $e ) {
file_put_contents( $name = (time() . '.log'), print_r( $e->getTrace(), true ) );
mail( ja@ja.pl, 'Error you bastard!', "New error occured. More details in file: $name" );
}
Regards- Dodek
mail(), as far as I remember, requires you to setup an SMTP server, which is kind of uneasy task if it is supposed to be done well. That's why I used "convenient facility" phrase instead of "third-party library".
- Michał Bachowski
@Dodek: but usually you don`t have to set up an SMTP because it`s already prepared.
BTW: Stronger, I beg you: update your post and write that errors should not be displayed on a screen :P (display_errors=off)
Regards- stronger
@Dodek: mail() is a no-brainer in PHP world. And if it was a sane developer should write or use handy library to make it actual three-liner.
@Michał: I would update if I was totally convinced it was right. I learned that leaving display_errors on results in better feedback from beta testers. The reason is I think that users not always realize that they found themselves in application's erroneous state, whereas offending them with some semi-programming cryptic junk output make them sure they encountered software problem.
I would be hesitant leaving it "on" on production machine/stable release, tho.- MiB
@stronger: I agree with you, that leaving "display_errors=on" on development or staging server is right but on production server it should be turned off ;)
- pldmachine
There can also be a production server in phase ''beta'', which can be for example - first few months of work.
And if I understood right:
"First, wrap whole application with try…catch statement. Once otherwise unhandled exception is thrown it gets sent via email." this means NO error will be displayed on the screen, no matter display_errors is Of or On.- Michał Bachowski
@pldmachine: putting everything between "try... catch " will suppress only exceptions. PHP hardly ever throws an exception ;P so that we should suppress errors by setting "display_errors" to "Off" ;)
- stronger
pldmachine, Michał, surely catching exception is not enough for successful reporting, hence "php_value error_log log/errors.txt" above. PHP is known to be long standing sucker when it comes to exceptions.
The thing is I am not 100% percent convinced that display_errors should be switched off on production box. To me it seems like choosing the lesser evil between "a fuckup that nobody will ever report, except that the app is behaving mysteriously" and "a fuckup that is evident enough for immediate action". I would go for the latter.







