Log your application's users
The access log can record which user of your application made a request.
Your application names the user in the Elpan-Log-User response header;
the edge copies the value into the user.name key of the
access record and removes the header, so your
visitors never see it.
This works with anything that can set a response header: PHP, a CGI program, an app server, or a container.
Two user fields
An access record can have two user fields:
| Key | Set by |
|---|---|
user.name | Your application, with the Elpan-Log-User header. |
elpan.auth.user | The web server, when its authentication accepted the user, e.g. with access control on the website. |
weblogconv puts one of them in the user field of a text line:
elpan.auth.user by default, falling back to user.name; --user app
and --user auth pick one. See
Convert the records to text.
PHP
Send the header before the page's first output:
<?php
if ($username !== null) {
header('Elpan-Log-User: ' . $username);
}
WordPress
Put this file in wp-content/mu-plugins/, e.g. as elpan-log-user.php;
WordPress loads every file there automatically, on the website and in the
dashboard.
<?php
/*
* Plugin Name: Log the WordPress user
* Description: Names the signed-in user in the access log of the website.
*/
add_action('init', function () {
if (is_user_logged_in() && !headers_sent()) {
header('Elpan-Log-User: ' . wp_get_current_user()->user_login);
}
});
Laravel
Add a middleware that sets the header on the response:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class LogUser
{
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
if ($user = $request->user()) {
$response->headers->set('Elpan-Log-User', (string) $user->getAuthIdentifier());
}
return $response;
}
}
Then apply it to every request in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->append(\App\Http\Middleware\LogUser::class);
})
This logs the user's ID. Use $user->email or another attribute if you
prefer.
The rules
- One value, in UTF-8. If your application sends the header twice,
the edge joins the values with
,. - At most 256 bytes. The edge trims surrounding spaces, then cuts a
longer value at a character boundary and ends it with
…, which counts toward the 256. - An empty value is no value. A value that is empty after trimming doesn't go into the record.
- The log only. The header never reaches the visitor and changes nothing else. It doesn't select the log file; the request's hostname does.
The edge doesn't check it. user.name is what your application sent, and
elpan.auth.user is what the web server reported, which the website's
.htaccess can also change. Both are good for searching your own log;
neither proves who made the request. The records go only to your own
website's log files.
When the server shows its own error page instead of yours, e.g. for a 404,
elpan.auth.user can be missing from the record.
A user name, an email address, or a user ID is personal data in many countries. Archived log files are kept for 15 days. Log only what you need, e.g. an ID rather than an email address.