Getting PHP Variables into Apache Logs

Gleaning information about the various things that are going on inside of a compuer or on a web site can be a somewhat difficult process. System logs are probably the most useful source of this information, but sometimes (especially for web sites) they don’t necessarily record all the interesting data. One example of a situation where this may be true is when you want your Apache logs to record your web site’s user session IDs.

Since PHP variables are known only to the current PHP process and not to Apache, you can’t just plug them into your Apache system log without first informing Apache about the variable you want to record. This can be done in two nearly identical ways, though the implementation of each is somewhat different. Luckily for the PHP progammer, it makes very little difference which way you choose.

Apache Notes

One way of getting Apache to recognize PHP session variables, or any variable for that matter, is to leave a note in Apache’s notes table via the PHP function apache_note(). An Apache note can be thought of as a reminder from one Apache process to another that a certain variable exists, and what its value is.

Thus, doing apache_note('userID', $_SESSION['userid']) will make the PHP session variable userid available to Apache as userID via an Apache note. Calling apache_note() from another page with only the first arguement ('userID') will retrieve the note from Apache’s notes table.

Apache Subprocess Environment

Another way to make PHP variables accessible to Apache is by putting them into an Apache procesess’ runtime environment. Note that simply using the PHP function putenv() will not work because environment variables set with putenv() expire at the end of the current request. Instead, another Apache-specific function must be used: apache_setenv().

Using the same example as with the Apache note, the code would look like this: apache_setenv('userID', $_SESSION['userid']). In order to retrieve the value from another page, you need to use the corresponding function apache_getenv(): $userid = apache_getenv('userID').

Moving the Variable into the Log File

Now that Apache has been made aware of the existence of the variable, the value must be recorded in Apache’s logs. This is the easy part. All you need do is add it to the LogFormat line in your config file. So, using the userID example from before, if your LogFormat directive looks like this,

LogFormat "%h %l %u %t "%r" %>s %b"

and you used an apache_note() You simply need to edit it so that it looks like this:

LogFormat "%h %l %u %t "%r" %>s %b %{userID}n"

Note the small n after the placement of the %{userID} variable in the log format. This signifies that the variable will come from an Apache note. If you used an Apache environment variable (apache_setenv()), then that small n should be changed to an e to signify that the variable comes from the environment.

Analyzing your web site traffic using this technique can often be just as effective as logging information to a database but there is much less overhead involved here than with most other options.

4 replies on “Getting PHP Variables into Apache Logs”

  1. Hi,

    I just came across your article. apache_note’s sounds great. Would you know if there are any performance issues with using it on medium and large traffic sites, i.e. avg session time of 30 min. and 20,000 visitors per hour.

    Thanks!

  2. Hey Shane. Unfortunately I don’t have a lot of performance related info on apache_note()s. I can’t imagine that it would be too bad even on high-performance sites since it’s designed for Apache modules to talk to each other and there’s little overhead involved in logging requests. That said, you’ll naturally want to have a test run before implementing it in production code, especially if you’re planning on using it in “creative” ways. :) Good luck — and please do let me know how you get on.

  3. Nice wrtiteup!

    What about using custom http headers instead?
    The server config needs to be a bit more convoluted, first logging the header then removing it.
    But it should be doable also on IIS and possibly other servers too…

Comments are closed.