site.authent
is set up with two
virtual hosts, one for customers and one for salespeople, and each
has its own logs in ... /logs/customers and
... /logs/salesmen. We can follow that scheme
and apply one LogFormat
to both, or each can have
its own logs with its own LogFormat
s inside the
<VirtualHost>
directives. They can also have
common log files, set up by moving ErrorLog
and
TransferLog
outside the
<VirtualHost>
sections, with different
LogFormat
s within the sections to distinguish the
entries. In this last case, the LogFormat
files
could look like this:
<VirtualHost www.butterthlies.com> LogFormat "Customer:..." ... </VirtualHost> <VirtualHost sales.butterthlies.com> LogFormat "Sales:..." ... </VirtualHost>
Let’s experiment with a format for customers, leaving everything else the same:
<VirtualHost www.butterthlies.com> LogFormat "customers: host %h, logname %l, user %u, time %t, request %r status %s, bytes %b," ...
We have inserted the words host
,
logname
, and so on
to make it clear in the file what is doing what. In real life you
probably wouldn’t want to clutter the file up in
this way because you would look at it regularly and remember what was
what or, more likely, process the logs with a program that would know
the format. Logging on to www.butterthlies.com
and going to summer
catalog
produces this log file:
customers: host 192.168.123.1, logname unknown, user -, time [07/Nov/ 1996:14:28:46 +0000], request GET / HTTP/1.0, status 200,bytes - customers: host 192.168.123.1, logname unknown, user -, time [07/Nov/ 1996:14:28:49 +0000], request GET /hen.jpg HTTP/1.0, status 200, bytes 12291, customers: host 192.168.123.1, logname unknown, user -, time [07/Nov /1996:14:29:04 +0000], request GET /tree.jpg HTTP/1.0, status 200, bytes 11532, customers: host 192.168.123.1, logname unknown, user -, time [07/Nov/ 1996:14:29:19 +0000], request GET /bath.jpg HTTP/1.0, status 200, bytes 5880,
This is not too difficult to follow. Notice that while we have
logname
unknown
, the user is -,
the usual report for an unknown value. This is because customers do
not have to give an ID; the same log for salespeople,
who do, would have a value here.
We can improve things by inserting lists of conditions based on the
error codes after the %
and before the command
letter. The
error codes are defined in the HTTP 1.0
specification:
200 OK 302 Found 304 Not Modified 400 Bad Request 401 Unauthorized 403 Forbidden 404 Not found 500 Server error 503 Out of resources 501 Not Implemented 502 Bad Gateway
The list from HTTP 1.1 is as follows:
100 Continue 101 Switching Protocols 200 OK 201 Created 202 Accepted 203 Non-Authoritative Information 204 No Content 205 Reset Content 206 Partial Content 300 Multiple Choices 301 Moved Permanently 302 Moved Temporarily 303 See Other 304 Not Modified 305 Use Proxy 400 Bad Request 401 Unauthorized 402 Payment Required 403 Forbidden 404 Not Found 405 Method Not Allowed 406 Not Acceptable 407 Proxy Authentication Required 408 Request Time-out 409 Conflict 410 Gone 411 Length Required 412 Precondition Failed 413 Request Entity Too Large 414 Request-URI Too Large 415 Unsupported Media Type 500 Internal Server Error 501 Not Implemented 502 Bad Gateway 503 Service Unavailable 504 Gateway Time-out 505 HTTP Version not supported
You can use !
before a code to mean
“if not.” !200
means “log this if the response was
not OK.” Let’s
put this in salesmen:
<VirtualHost sales.butterthlies.com> LogFormat "sales: host %!200h, logname %!200l, user %u, time %t, request %r, status %s,bytes %b," ...
An attempt to log in as fred with the password
don't
know
produces the
following entry:
sales: host 192.168.123.1, logname unknown, user fred, time [19/Aug/ 1996:07:58:04 +0000], request GET HTTP/1.0, status 401, bytes -
However, if it had been the infamous bill with
the password theft
, we would see:
host -, logname -, user bill, ...
because we asked for host
and
logname
to be logged only if the
request was not OK. We can combine more than one condition, so that
if we only want to know about security problems on sales, we could
log usernames only if they failed to authenticate:
LogFormat "sales: bad user: %400,401,403u"
We can also extract data from the HTTP headers in both directions:
%[condition
]{user-agent}i
This prints the user agent (i.e., the software the client is running) if
condition
is met. The old way of doing
this was AgentLog
logfile
and ReferLog
logfile
.