04 - 日志格式详解
04 - 日志格式详解
4.1 日志格式基础
GoAccess 的核心能力在于解析日志文件。要正确分析日志,必须让 GoAccess 理解日志的格式。GoAccess 使用一套类似 Apache 的格式字符串来描述日志结构。
格式字符串原理
GoAccess 的格式字符串由普通字符和格式说明符组成:
格式说明符: %x (x 是一个字母,代表特定字段)
普通字符: 空格、引号、方括号等原样匹配
例如,Apache Combined Log Format 对应的格式字符串为:
%h - %^ [%d:%t %^] "%r" %s %b "%R" "%u"
解析过程:
192.168.1.1 - - [10/May/2026:13:55:36 +0800] "GET /index.html HTTP/1.1" 200 612 "https://example.com/" "Mozilla/5.0"
│ │ │ │ │ │ │ │ │ │
%h - %^ [%d :%t %^] "%r" %s %b "%R" "%u"
4.2 格式说明符完整列表
| 说明符 | 含义 | 示例值 |
|---|---|---|
%h | 客户端 IP 地址 (Host) | 192.168.1.1 |
%^ | 跳过此字段(忽略) | - |
%d | 日期 (Date) | 10/May/2026 |
%t | 时间 (Time) | 13:55:36 |
%r | 请求行 (Request) | GET /index.html HTTP/1.1 |
%m | 请求方法 (Method) | GET |
%U | URL 路径 (URL path) | /index.html |
%q | 查询字符串 (Query string) | ?id=123 |
%H | 协议版本 (Protocol) | HTTP/1.1 |
%s | 状态码 (Status code) | 200 |
%b | 响应大小 (Bytes sent) | 612 |
%R | 来源页 (Referer) | https://example.com/ |
%u | User-Agent | Mozilla/5.0 ... |
%D | 请求耗时 — 微秒 (Duration) | 1234567 |
%T | 请求耗时 — 秒 (Duration) | 1 |
%^ | 跳过一个字段 | - |
%{VAR}i | 请求头字段 | %{Cookie}i |
%{VAR}o | 响应头字段 | %{Content-Type}o |
注意:
%^是"跳过"(忽略)的意思,当你的日志中有不需要分析的字段时非常有用。
4.3 预定义日志格式
GoAccess 内置了多种常见日志格式,可通过名称直接使用:
4.3.1 Apache / Nginx 标准格式
| 格式名称 | 说明 | 对应配置 |
|---|---|---|
COMBINED | Apache Combined Log Format | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" |
COMMON | Apache Common Log Format | LogFormat "%h %l %u %t \"%r\" %>s %b" |
VCOMBINED | 虚拟主机 Combined 格式 | 比 Combined 多一个虚拟主机字段 |
VCOMMON | 虚拟主机 Common 格式 | 比 Common 多一个虚拟主机字段 |
4.3.2 使用预定义格式
# 使用 Combined 格式(最常用)
goaccess /var/log/nginx/access.log --log-format=COMBINED
# 使用 Common 格式
goaccess /var/log/nginx/access.log --log-format=COMMON
# 使用虚拟主机 Combined 格式
goaccess /var/log/nginx/access.log --log-format=VCOMBINED
4.3.3 COMBINED 与 COMMON 的区别
COMBINED = COMMON + 来源页 + User-Agent
# Common Log Format (CLF)
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
# Combined Log Format
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08"
4.4 Nginx 日志格式
4.4.1 Nginx 默认日志格式
Nginx 的默认 combined 格式与 Apache Combined 一致:
# /etc/nginx/nginx.conf
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
# 使用 COMBINED 格式解析
goaccess /var/log/nginx/access.log --log-format=COMBINED
4.4.2 Nginx 自定义格式示例
示例一:包含请求时间的格式
log_format timed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
GoAccess 配置:
goaccess access.log \
--log-format='%h - %^ [%d:%t %^] "%r" %s %b "%R" "%u" %D' \
--date-format=%d/%b/%Y \
--time-format=%H:%M:%S
示例二:JSON 格式日志
# Nginx 使用 escape=json 输出 JSON 格式日志
log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":"$request_time"'
'}';
GoAccess 解析 JSON 格式日志:
goaccess access.log \
--log-format='"%d:%t","%h","%r","%s","%b","%R","%u","%T"' \
--date-format=%d/%b/%Y \
--time-format=%H:%M:%S
提示:JSON 格式日志的解析相对复杂,需要将 JSON 字段映射为格式说明符的顺序。
示例三:包含 X-Forwarded-For 的格式
log_format proxied '$http_x_forwarded_for - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
goaccess access.log --log-format=COMBINED
# X-Forwarded-For 对应 %h 字段
4.4.3 Nginx 格式速查表
| Nginx 变量 | GoAccess 说明符 | 说明 |
|---|---|---|
$remote_addr | %h | 客户端 IP |
$remote_user | %^ (通常为 -) | 远程用户 |
$time_local | [%d:%t %^] | 时间戳 |
$request | %r | 请求行 |
$status | %s | 状态码 |
$body_bytes_sent | %b | 响应大小 |
$http_referer | %R | 来源页 |
$http_user_agent | %u | User-Agent |
$request_time | %T 或 %D | 请求耗时 |
$upstream_response_time | %T | 上游响应时间 |
$http_x_forwarded_for | %h | 真实客户端 IP |
4.5 Apache 日志格式
4.5.1 Apache 默认配置
# /etc/apache2/apache2.conf 或 httpd.conf
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
# 解析 Combined 格式
goaccess /var/log/apache2/access.log --log-format=COMBINED
4.5.2 Apache 自定义格式示例
示例一:包含处理时间
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" timed
goaccess access.log \
--log-format='%h - %^ [%d:%t %^] "%r" %s %b "%R" "%u" %D' \
--date-format=%d/%b/%Y \
--time-format=%H:%M:%S
示例二:VirtualHost 日志
<VirtualHost *:80>
ServerName example.com
CustomLog /var/log/apache2/example.com_access.log combined
</VirtualHost>
goaccess /var/log/apache2/example.com_access.log --log-format=COMBINED
4.6 自定义日志格式
当日志格式不匹配任何预定义格式时,需要手动指定格式字符串。
4.6.1 自定义格式编写规则
- 分析日志样例,识别每个字段
- 使用格式说明符替换每个字段
- 使用
%^跳过不需要的字段 - 使用普通字符(空格、引号、方括号等)匹配分隔符
4.6.2 实战:从日志样例推导格式
给定日志样例:
2026-05-10 14:30:15 | 192.168.1.100 | GET | /api/users | 200 | 1024 | 0.023 | https://admin.example.com | Chrome/120.0
逐步推导:
字段 值 说明符
────────────────────────────────────────────────
日期 2026-05-10 %d
时间 14:30:15 %t
分隔符 | \|
IP 192.168.1.100 %h
方法 GET %m
路径 /api/users %U
状态码 200 %s
大小 1024 %b
耗时 0.023 %T
来源页 https://admin... %R
浏览器 Chrome/120.0 %u
格式字符串:
goaccess access.log \
--log-format='%d %t | %h | %m | %U | %s | %b | %T | %R | %u' \
--date-format=%Y-%m-%d \
--time-format=%H:%M:%S
4.6.3 更多自定义格式示例
示例一:管道分隔的日志
10.0.0.1|2026-05-10|14:30:15|GET|/api/data|200|512
goaccess access.log \
--log-format='%h|%d|%t|%m|%U|%s|%b' \
--date-format=%Y-%m-%d \
--time-format=%H:%M:%S
示例二:Squid 代理日志
1718446948.256 156 10.0.0.1 TCP_MISS/200 51234 GET http://example.com/ - HIER_DIRECT/93.184.216.34 text/html
goaccess access.log \
--log-format='%^ %^ %h %^/%s %b %m %U %^ %^ %^' \
--date-format=%s # Unix 时间戳,需要特殊处理
示例三:AWS ALB 日志
h2 2026-05-10T14:30:15.123456Z app/my-alb/50dc6c495c0c9188 10.0.0.1:54321 10.0.0.2:80 0.000 0.015 0.000 200 200 512 384 "GET https://example.com:443/api/data HTTP/2.0" "Mozilla/5.0" ...
goaccess access.log \
--log-format='%^ %d:%t %^ %h:%^ %^:%^ %T %^ %^ %s %^ %b %^ "%m %U %H" "%u"' \
--date-format=%Y-%m-%d \
--time-format=%H:%M:%S
4.7 时间与日期格式
4.7.1 日期格式说明符
| 说明符 | 含义 | 示例 |
|---|---|---|
%d | 日(两位) | 01 - 31 |
%m | 月(两位) | 01 - 12 |
%b | 月缩写 | Jan, Feb, …, Dec |
%B | 月全称 | January, February, … |
%Y | 四位年份 | 2026 |
%y | 两位年份 | 26 |
4.7.2 时间格式说明符
| 说明符 | 含义 | 示例 |
|---|---|---|
%H | 小时(24小时制) | 00 - 23 |
%M | 分钟 | 00 - 59 |
%S | 秒 | 00 - 59 |
%f | 微秒 | 123456 |
%T | 时间(时:分:秒) | 14:30:15 |
4.7.3 常见日期时间格式对照
| 日志中的日期格式 | 配置 |
|---|---|
10/May/2026 | --date-format=%d/%b/%Y |
2026-05-10 | --date-format=%Y-%m-%d |
05/10/2026 | --date-format=%m/%d/%Y |
10.05.2026 | --date-format=%d.%m.%Y |
20260510 | --date-format=%Y%m%d |
May 10 2026 | --date-format=%b %d %Y |
| 日志中的时间格式 | 配置 |
|---|---|
14:30:15 | --time-format=%H:%M:%S |
14:30:15.123 | --time-format=%H:%M:%S.%f |
2:30:15 PM | GoAccess 不直接支持 12 小时制 |
4.8 组合格式实战
场景一:Nginx + 请求时间 + X-Forwarded-For
Nginx 配置:
log_format proxy '$http_x_forwarded_for - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time';
日志样例:
203.0.113.50 - - [10/May/2026:14:30:15 +0800] "GET /index.html HTTP/1.1" 200 612 "https://example.com" "Mozilla/5.0" 0.123
GoAccess 命令:
goaccess /var/log/nginx/access.log \
--log-format='%h - %^ [%d:%t %^] "%r" %s %b "%R" "%u" %T' \
--date-format=%d/%b/%Y \
--time-format=%H:%M:%S
场景二:Caddy JSON 日志
Caddy 配置:
{
"logging": {
"logs": {
"default": {
"encoder": {
"format": "json"
}
}
}
}
}
日志样例:
{"ts":1715338215.123,"request":{"remote_addr":"10.0.0.1","method":"GET","uri":"/","proto":"HTTP/2.0","headers":{"User-Agent":["Mozilla/5.0"],"Referer":["https://example.com"]}},"status":200,"size":612,"duration":0.023}
解析方案:Caddy JSON 日志结构复杂,建议先用 jq 转换为适合 GoAccess 的格式:
# 将 Caddy JSON 转为 pipe-delimited 格式
cat /var/log/caddy/access.log | \
jq -r '[.request.remote_addr, (.ts | strftime("%d/%b/%Y")), (.ts | strftime("%H:%M:%S")),
.request.method, .request.uri, .status, .size, .duration,
(.request.headers.Referer[0] // "-"), (.request.headers["User-Agent"][0] // "-")]
| join("|")' | \
goaccess --log-format='%h|%d|%t|%m|%U|%s|%b|%T|%R|%u' \
--date-format=%d/%b/%Y \
--time-format=%H:%M:%S -
场景三:Tomcat 访问日志
Tomcat 配置 (server.xml):
<Valve className="org.apache.catalina.valves.AccessLogValve"
pattern="%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %D"
directory="logs" prefix="access" suffix=".log" />
goaccess /var/log/tomcat/access.log \
--log-format='%h - %^ [%d:%t %^] "%r" %s %b "%R" "%u" %D' \
--date-format=%d/%b/%Y \
--time-format=%H:%M:%S
4.9 使用配置文件简化格式管理
将常用格式保存到配置文件中,避免每次输入:
# ~/.goaccessrc
# === 日志格式 ===
log-format %h - %^ [%d:%t %^] "%r" %s %b "%R" "%u"
# === 时间格式 ===
date-format %d/%b/%Y
time-format %H:%M:%S
# === 预定义格式(二选一) ===
# log-format COMBINED
配置文件后,直接运行:
goaccess /var/log/nginx/access.log
无需再指定 --log-format 等参数。
多配置文件管理
对于不同日志格式的环境,可以创建多个配置文件:
# Nginx 标准格式
goaccess access.log --config-file=~/.goaccessrc.nginx
# Nginx 含请求时间
goaccess access.log --config-file=~/.goaccessrc.nginx-timed
# Apache
goaccess access.log --config-file=~/.goaccessrc.apache
4.10 调试日志格式
4.10.1 测试格式是否正确
GoAccess 提供了调试模式来验证日志格式:
# 显示详细的解析过程
goaccess access.log --log-format=COMBINED --debug-file=debug.txt
# 查看调试输出
head -50 debug.txt
4.10.2 常见格式错误
| 错误现象 | 原因 | 解决方案 |
|---|---|---|
| 所有 Hits 为 0 | 格式不匹配 | 检查格式字符串 |
| 日期解析失败 | 日期格式不匹配 | 调整 --date-format |
| 状态码全为 0 | 字段顺序错误 | 检查字段顺序 |
| IP 地址为空 | %h 位置错误 | 确认 IP 字段位置 |
| 带宽统计异常 | 字段映射错误 | 检查 %b 对应字段 |
4.10.3 验证步骤
# 1. 先看日志的前 5 行
head -5 /var/log/nginx/access.log
# 2. 逐行对照格式说明符
# 假设日志行为:
# 10.0.0.1 - - [10/May/2026:14:30:15 +0800] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0"
#
# 对应关系:
# 10.0.0.1 → %h
# - → -
# - → %^
# [10/May/2026:14:30:15 +0800] → [%d:%t %^]
# "GET / HTTP/1.1" → "%r"
# 200 → %s
# 612 → %b
# "-" → "%R"
# "Mozilla/5.0" → "%u"
# 3. 使用 1-2 行测试
head -2 /var/log/nginx/access.log | goaccess --log-format=COMBINED -
# 4. 使用 --debug-file 查看详细解析
goaccess /var/log/nginx/access.log --log-format=COMBINED --debug-file=/tmp/debug.log
4.11 小结
| 要点 | 说明 |
|---|---|
| 最常用格式 | COMBINED(Apache/Nginx 标准) |
| 跳过字段 | 使用 %^ 跳过不需要的字段 |
| 关键格式 | %h=IP, %d=日期, %t=时间, %r=请求, %s=状态码, %b=大小, %R=来源, %u=UA |
| 调试方法 | --debug-file 查看解析详情 |
| 最佳实践 | 将格式写入配置文件 |
下一章
下一章将详细介绍 GoAccess 的实时监控功能,包括终端实时面板、WebSocket 通信和 HTML 实时面板的搭建。