Skip to main content
Advertisement

Apache Log Configuration and Analysis

Apache's logs are essential tools for access pattern analysis, error diagnosis, and security auditing. This chapter covers CustomLog format configuration, ErrorLog levels, and log rotation with rotatelogs — everything needed in production.


Log Types

LogDefault Path (Ubuntu)Purpose
Access Log/var/log/apache2/access.logHTTP request records
Error Log/var/log/apache2/error.logError and warning records

CustomLog — Access Log Format

Default Formats

# combined format (most widely used)
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

# common format
LogFormat "%h %l %u %t \"%r\" %>s %O" common

CustomLog ${APACHE_LOG_DIR}/access.log combined

Custom Format with Response Time

# %D: microseconds, %T: seconds
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" combined_time
CustomLog ${APACHE_LOG_DIR}/access.log combined_time

JSON Format

LogFormat "{ \
\"time\": \"%{%Y-%m-%dT%H:%M:%S%z}t\", \
\"remote_addr\": \"%a\", \
\"method\": \"%m\", \
\"uri\": \"%U%q\", \
\"status\": %s, \
\"bytes\": %O, \
\"response_time_us\": %D \
}" json

CustomLog ${APACHE_LOG_DIR}/access.json json

Key Log Format Variables

VariableDescription
%hClient IP (or hostname if HostnameLookups is On)
%aClient IP (always IP)
%tRequest time
%rRequest line (method + URI + protocol)
%mRequest method
%UURL path (no query string)
%qQuery string
%>sFinal status code
%OResponse size including headers (bytes)
%DRequest processing time (microseconds)
%TRequest processing time (seconds)
%{Referer}iReferer header
%{User-Agent}iUser-Agent header
%vVirtual host name

ErrorLog Level Settings

ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn

# Levels: emerg > alert > crit > error > warn > notice > info > debug > trace1~8
LevelDescriptionFor Production
errorRequest processing failuresAlways logged
warnWarningsRecommended
infoInformationalDevelopment
debugDetailed debugTemporary only

Per-Module Log Level

# Overall warn, but trace3 for rewrite module
LogLevel warn rewrite:trace3

Per-VirtualHost Log Separation

<VirtualHost *:80>
ServerName site1.com
ErrorLog ${APACHE_LOG_DIR}/site1.error.log
CustomLog ${APACHE_LOG_DIR}/site1.access.log combined
</VirtualHost>

Excluding Unnecessary Logs

SetEnvIf Request_URI "^/health$" dontlog
SetEnvIf Request_URI "\.(ico|png|jpg|gif|css|js)$" dontlog
CustomLog ${APACHE_LOG_DIR}/access.log combined env=!dontlog

Log Rotation

Using rotatelogs (Apache built-in)

# New log file per day
CustomLog "|/usr/bin/rotatelogs /var/log/apache2/access.%Y%m%d.log 86400" combined

Using logrotate (system tool)

/var/log/apache2/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
sharedscripts
postrotate
if invoke-rc.d apache2 status > /dev/null 2>&1; then
invoke-rc.d apache2 reload > /dev/null 2>&1
fi
endscript
}

Practical Log Analysis

# Status code distribution
awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -rn

# Top 20 most requested URLs
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20

# Top 10 IPs by request count
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -10

# All 5xx error requests
awk '($9 ~ /^5/) {print $1, $7, $9}' /var/log/apache2/access.log

Summary

ItemDirectiveRecommendation
Access logCustomLogcombined with response time
Error logErrorLog + LogLevelProduction: warn, debug: per-module
Exclude noiseSetEnvIf + env=!Exclude health checks, static files
Rotationlogrotatedaily + 14 days + compress
Multiple sitesPer-VirtualHost logsSeparate logs per site
Advertisement