One PHP error log per developer
At work we’re using a shared web development server, with a setup that allows every developer to have his own compartmentalized development space. It requires some tricky configurations, but in the end I find it way more efficient than the policy “every developer installs its own Apache/PHP/MySQL stack”. I already talked about the general ideas in a previous article (in french) two years ago, and so far it works like a charm. Our setup it constantly improving, and today’s big question is: how to make so that every developer has it’s own PHP error log?
Apache config
First, a little insight on the Apache configuration. If we would be using one virtual host directive per developer, this wouldn’t be an issue at all. Just set up the proper error_log path (using Apache’s php_value directive like so: php_value error_log /var/log/php/errors_username.log) for every virtual host, reload Apache and you’re done.
Our Apache, however, is using mod_vhost_alias. Basically we have “one virtual host to rule them all”, because I’m lazy and I don’t want to write one virtual host for every new dev, or modify a dozens of virtual host directives everytime I change a setting.
So how does it works? The first part of the URL is the developer username, then the second part is the project’s folder name, then the remaining part is the dev server hostname. With the VirtualDocumentRoot directive, you use parts of the URL has variable for calculating the correct document root path. (Actually, our setup includes a third part which is the subfolder to separate the document root of a project from all the include files, but that’s not the point of this article). Example:
<VirtualHost *:80> ServerName dev.domain.com ServerAlias *.dev.domain.com UseCanonicalName off VirtualDocumentRoot /home/%1/web/%2 <Directory /home/*/web/*/*> Allow from all AllowOverride all </Directory> </VirtualHost>
The address http://remi.awesome.dev.domain.com will automagically has a document root located in: /home/remi/web/awesome. The benefit is obvious: simplicity and flexibilty. I love convention over configuration design principle.
PHP config
Now the problem is that it’s impossible to tell PHP to logs the errors on a different file based on the first part of the URL directly into the Apache configuration, because the %1, %2,… variable are only valid inside the VirtualDocumentRoot directive.
So we need to do it inside PHP or inside an htaccess file on every folder. But doing it for every project is a pain, not to mention the conflicts to come in SVN because every developer will have his own path. That’s when PHP’s auto_prepend_file option come into play (and honestly, I would never have thought it’ll be useful one day).
I just create a file named /etc/php5/prepend.php with that one-liner:
<?php ini_set('error_log',sprintf('/var/log/php/errors_%s.log',substr($_SERVER['SERVER_NAME'], 0, strpos($_SERVER['SERVER_NAME'],'.'))));
And add this settings to php.ini:
auto_prepend_file = /etc/php5/prepend.php
Note that the directory /var/log/php will not be created out of the blue, so you have to take care of it, and it must be writeable by www-data. Files will be named errors_(first part of the url).log, so for example errors_remi.log in the previous example. Users belongs to group www-data, so as long as the logs are readable by the group (what they are by default) they’ll be able to read their logs.
And now the cherry on top of the cake, the logrotate configuration to rotate logs weekly, and keep one month (4 files) of archive:
/var/log/php/errors_*.log {
weekly
missingok
rotate 4
compress
delaycompress
notifempty
create 640 www-data www-data
}
Et voilà!
Développement web collaboratif
On me demande souvent comment j’organise le développement web dans mon entreprise : comment on arrive à coder à plusieurs sur le même fichier sans se marcher sur les pieds, comment on archive les versions, comment on effectue les livraisons en production, etc. Il est vrai que le développement web collaboratif est souvent mal organisé, et il est courant d’avoir comme seul outil un simple dossier partagé…
Contraintes liées au développement web collaboratif
Contrairement à un projet classique qui ne nécessite “que” un compilateur et des bibliothèques, une application web est une association complexe de plusieurs composants logiciels dont les versions et les configurations très variables peuvent influer sur le bon fonctionnement de l’application :
- un serveur web (vhost, htaccess, mod_rewrite, etc.),
- l’interpréteur php (options de php.ini, modules supplémentaires comme pdo, gettext, etc.),
- le sgbd (configuration des users, etc.).
Donc la solution “classique” d’avoir un poste de développement par développeur est ici difficile à maintenir : il faudrait installer tous ces logiciels sur chaque poste et surtout veiller à avoir une configuration identique partout. Et ça se complique dès qu’il faut faire une mise à jour de la config…
Une autre solution serait d’avoir un serveur de dev unique (pour éviter les problèmes de maintenance évoqués ci-avant), et de travailler directement dessus via des partages de fichiers (Samba, NFS, etc.). Or cette solution pose plusieurs problèmes :
- en cas d’accès concurrents à un fichier : le risque est grand de voir ses modifications écrasées par un autre développeur ;
- en cas de modifications lourdes (exemple : un refactoring de la base) : les autres développeurs sont bloqués ;
- impossible d’utiliser correctement le svn : il n’y a qu’une seule version des fichiers et on ne sait pas qui l’a modifiée.
Nous avons donc créée une solution intermédiaire : un serveur de dev unique (pour une maintenance facile), qui fournit des serveurs virtuels pour chaque développeur (pour une bonne séparation des données et une utilisation optimale de svn).
Le serveur de dev fonctionne avec Debian GNU/Linux, les postes clients avec Windows XP.