利用 GoAccess 分析日志,将 Web 访问数据可视化

本文最后更新于:2022年3月26日 晚上

通过 leancloud不蒜子,博主可以轻松掌握自己博客的独立访客(Unique Visitor,简称 UV),以及文章的访问量(Page View,简称 PV)。可是博客中记录的 UVPV 并不能准确记载访客的具体信息,因此需要特殊的统计工具来帮助博主分析访客的相关数据。

Web 服务器可以详细记录访客的访问时间、网址链接、流量、IP 和客户端等信息。例如 nginx 的 access.log 中就包含以下内容:

1
2
3
4
5
12.34.56.78 - - [12/Mar/2022:23:20:43 +0800] "GET / HTTP/3.0" 200 4491 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.36" "-"
12.34.56.78 - - [12/Mar/2022:23:20:44 +0800] "GET /css/main.css HTTP/3.0" 200 7698 "https://vickey.fun/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.36" "-"
12.34.56.78 - - [12/Mar/2022:23:20:44 +0800] "GET /css/highlight.css HTTP/3.0" 200 743 "https://vickey.fun/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.36" "-"
12.34.56.78 - - [12/Mar/2022:23:20:44 +0800] "GET /js/utils.js HTTP/3.0" 200 2070 "https://vickey.fun/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.36" "-"
12.34.56.78 - - [12/Mar/2022:23:20:44 +0800] "GET /js/color-schema.js HTTP/3.0" 200 2455 "https://vickey.fun/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.36" "-"

成千上万行的日志当然不可能一行一行的分析,我们可以通过 GoAccess 将网站的访问数据可视化,让数据更易读。

一、什么是 GoAccess

GoAccess 是一款开源(MIT 许可证)的且具有交互视图界面的实时 Web 日志分析工具,通过你的 Web 浏览器或者 *nix 系统下的终端程序即可访问[1]。它为需要动态可视化报告的系统管理员提供了快速而有价值的 HTTP 统计信息[2]。GoAccess 解析指定的 Web 日志文件,并将数据输出到 X 终端。功能包括:

  • 通用统计:此面板展示了几个主要指标,比如:有效和无效请求的数量、分析这些数据所花费的时间、独立访客的情况、请求的文件、静态文件(CSS、ICO、JPG 等)的完整 URL、404 错误、被解析的日志文件的大小以及消耗的带宽。

  • 独立访客:此面板按照日期展示了访问次数、独立访客数,以及累计消耗的带宽等指标。具有相同IP、相同访问时间、相同的 UserAgent 的 HTTP 请求将会被识别为独立访客。默认情况下包含了网络爬虫。

    也可以选择使用 --date-spec=hr 参数将按照日期分析修改为按照小时,例如:05/Jun/2016:16 。这对于希望在小时级别去跟踪每日流量非常有帮助。

  • 请求的文件:此面板展示您服务器上被请求次数最多的文件。包含访问次数、独立访客数、百分比、累计消耗带宽、使用的协议、请求方式。

  • 请求的静态文件:列出请求频率最高的静态文件类型,例如 JPG、CSS、SWF、JS、GIF 和 PNG , 以及和上一个面板一样的其他指标。 另外静态文件可以被添加到配置文件中。

  • 404 或者文件未找到:展示内容与之前的面板类似,但是其数据包含了所有未找到的页面,以及俗称的 404 状态码。

  • 主机:此面板展示主机自身的详细信息。能够很好的发现不怀好意的爬虫以及识别出是谁吃掉了你的带宽。

    扩展面板将向您展示更多信息,比如主机的反向 DNS 解析结果,主机所在国家和城市。如果开启了 -a 参数,选择想查看的 IP 地址并按回车,将会显示 UserAgent 列表。

  • 操作系统:此面板将显示主机使用的操作系统的信息。GoAccess 将尽可能尝试为每一款操作系统提供详细的信息。

  • 浏览器:此面板将显示来访主机使用的浏览器信息。GoAccess 将尽可能尝试为每一款浏览器提供详细的信息。

  • 访问时间:此面板按小时报告。因此将显示 24 个数据点,每一个均对应每一天的某一个小时。

    使用 --hour-spec=min 参数可以将时间范围由每小时调整为每十分钟,最终以 16:4 这种格式显示,如果要发现服务器上的流量峰值,这会非常有用。

  • 虚拟主机:此面板将显示从访问日志中解析出来的不同的虚拟主机的情况。此面板仅在日志格式中启用了 %v 参数时显示。

  • 来源地址(Referer URL):如果问题主机通过其他的资源访问了你的站点,以及通过从其他主机上的链接或者跳转到你的站点,则这些来源地址(Referer URL)将会被显示在此面板。可以在配置文件中通过 --ignore-panel 开启此功能。(默认关闭)

  • 来源站点:此面板将仅显示来源地址的主机名部分,而不是完整的 URL。

  • 关键字:报告支持用在谷歌搜索,谷歌缓存,谷歌翻译上使用关键字。目前仅支持通过 HTTP 使用谷歌搜索。可以在配置文件中通过 --ignore-panel 开启此功能。(默认关闭)

  • 地理位置:根据 IP 地址判断地理位置。统计数据按照大洲和国家分组。需要地理位置模块的支持。

  • HTTP 状态代码:以数字表示的 HTTP 请求的状态编码。

  • 远程用户(HTTP验证):通过 HTTP 验证来确定访问文档的权限。如果文档没有被密码保护起来,这部分将会显示为 “-”。此面板默认为开启,除非在日志格式变量中设置了参数 %e

  • 缓存状态:如果你在服务器上启用了缓存,则你可能想要知道用户请求对象是否已被缓存。此面板显示服务器中请求对象的缓存状态。除非在日志格式变量中给出 %C,否则不会启用此面板。状态可以是 MISSBYPASSEXPIREDSTALEUPDATINGREVALIDATEDHIT

  • MIME 类型:此面板指定某种媒体类型(MIME Types)和媒体子类型,将其记录在该面板中。除非在日志格式变量中给出 %M,不然不会启用此面板。有关更多详细信息,请参阅 MIME 类型

  • 加密设置:此面板将显示加密套件中使用的 SSL/TLS 协议。除非在日志格式变量中给出 %K,否则不会启用此面板。

如果在日志格式中配置了请求时间,所有面板还可以显示服务器处理请求的平均时间消耗。

二、安装 GoAccess

使用 Linux 发行版的软件包管理器来安装 GoAccess 是最简单的方法。但是请注意,并非所有发行版都提供最新版本的 GoAccess[3]

例如,在 Debian/Ubuntu 中安装 GoAccess:

1
sudo apt install goaccess

虽然这种方法最简单,但是这并不能为您提供最新的稳定版本,Ubuntu 软件包管理器中的 GoAccess 版本仍为 1.3。要确保您运行的是最新的稳定版本的 GoAccess,请参考下面的方法,将 GoAccess 的官方源添加到 Debian/Ubuntu 的软件包管理器中:

1
2
3
4
wget -O - https://deb.goaccess.io/gnugpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/goaccess.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg] https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
sudo apt-get update
sudo apt-get install goaccess

三、配置 GoAccess

在运行 GoAccess 之前,你需要先对其进行配置。使用文本编辑器打开 /etc/goaccess 目录中的 goaccess.conf 文件,你会看到很多选项,每个选项都会有详细的说明,你可以参考下文进行配置。

1. 设置时间格式

1
2
3
4
5
6
7
8
9
10
11
12
13
######################################
# Time Format Options (required)
######################################
#
# The hour (24-hour clock) [00,23]; leading zeros are permitted but not required.
# The minute [00,59]; leading zeros are permitted but not required.
# The seconds [00,60]; leading zeros are permitted but not required.
# See `man strftime` for more details
#
# The following time format works with any of the
# Apache/NGINX's log formats below.
#
time-format %H:%M:%S

移除 time-format %H:%M:%S 前面的 # 即可。

2. 设置日期格式

1
2
3
4
5
6
7
8
9
10
11
12
13
######################################
# Date Format Options (required)
######################################
#
# The date-format variable followed by a space, specifies
# the log format date containing any combination of regular
# characters and special format specifiers. They all begin with a
# percentage (%) sign. See `man strftime`
#
# The following date format works with any of the
# Apache/NGINX's log formats below.
#
date-format %d/%b/%Y

移除 date-format %d/%b/%Y 前面的 # 即可。

3. 设置日志格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
######################################
# Log Format Options (required)
######################################
#
# The log-format variable followed by a space or \t for
# tab-delimited, specifies the log format string.
#
# NOTE: If the time/date is a timestamp in seconds or microseconds
# %x must be used instead of %d & %t to represent the date & time.

# In addition to specifying the raw log/date/time formats, for
# simplicity, any of the following predefined log format names can be
# supplied to the log/date/time-format variables. GoAccess can also
# handle one predefined name in one variable and another predefined
# name in another variable.
#
log-format COMBINED

通常将 log-format COMBINED 前面的 # 移除,就可以匹配 nginx 默认日志格式。如果你想显示更加详尽的信息,可以设置为 log-format %h %^[%d:%t %^] "%r" %M %s %b %T %K/%k "%R" "%u"。当然,你需要同时修改 nginx 的日志格式,例如:

1
2
3
4
5
6
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
'$sent_http_content_type $status $body_bytes_sent '
'$request_time $ssl_protocol/$ssl_cipher "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

你可通过下表来设置 GoAccess 和 nginx 日志格式中的对应变量[1]

GoAccess
日志格式变量
nginx
日志格式变量
变量说明
%h$remote_addr主机(客户端的 IPv4 或 IPv6 地址)
%d:%t$time_local访问日期和时间(服务器本地时间)
%r$request客户端的请求路径(location)
%M$sent_http_content_type请求的资源类型(MIME-type)
%s$status服务器返回客户端的状态代码
%b$body_bytes_sent对象返回客户端的大小
%T$request_time服务器响应请求的时间(毫秒计量)
%K$ssl_protocol建立连接的 TLS 加密协议类型
%k$ssl_cipher建立连接的 TLS 加密算法类型
%R$http_referer请求标头中的来源(Referer)信息
%u$http_user_agent请求标头中的 user-agent 信息
%v$host虚拟主机名称
%e$remote_user通过 HTTP 身份认证访问网站的用户标识
%C$upstream_cache_status服务器返回对象的缓存状态

4. 设置 WebSocket 监听端口和 URL

如果要实时显示 Web 日志的分析结果,就需要打开 real-time-html 功能,并设置 WebSocket 的监听端口和访问 url。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# The port to which the connection is being attempted to connect.
# By default GoAccess' WebSocket server listens on port 7890
# See man page or http://gwsocket.io for details.
#
port 7890

# Write the PID to a file when used along the daemonize option.
#
#pid-file /var/run/goaccess.pid

# Enable real-time HTML output.
#
real-time-html true

# URL to which the WebSocket server responds. This is the URL supplied
# to the WebSocket constructor on the client side.
#
# Optionally, it is possible to specify the WebSocket URI scheme, such as ws://
# or wss:// for unencrypted and encrypted connections.
# e.g., ws-url wss://goaccess.io
#
# If GoAccess is running behind a proxy, you could set the client side
# to connect to a different port by specifying the host followed by a
# colon and the port.
# e.g., ws-url goaccess.io:9999
#
# By default, it will attempt to connect to localhost. If GoAccess is
# running on a remote server, the host of the remote server should be
# specified here. Also, make sure it is a valid host and NOT an http
# address.
#
ws-url wss://example.com:443/wss/

使用加密的 WebSocket 连接更加安全,推荐使用 wss 协议。ws-url 需要根据 Web 服务器指定的 URL 来进行设置。

5. 设置 log 文件路径

1
2
3
4
5
6
7
8
######################################
# File Options
######################################

# Specify the path to the input log file. If set, it will take
# priority over -f from the command line.
#
log-file /var/log/nginx/access.log

6. 日志解析器设置

(1) 排除解析的 IP 地址

exclude-ip 命令后面添加 IP 地址或者 IP 地址范围,可以让 GoAccess 不解析这些 IP 地址或 IP 地址范围的访问。推荐将本地 IP 地址都排除掉。

1
2
3
4
5
6
7
8
9
10
# Exclude an IPv4 or IPv6 from being counted.
# Ranges can be included as well using a dash in between
# the IPs (start-end).
#
exclude-ip 127.0.0.1
exclude-ip 192.168.0.0-192.168.255.255
exclude-ip 172.16.0.0-172.31.255.255
exclude-ip 10.0.0.0-10.255.255.255
exclude-ip ::1
#exclude-ip 0:0:0:0:0:ffff:808:804-0:0:0:0:0:ffff:808:808

(2) 解析输出文件设置

GoAccess 可以输出 csv、json 和 html 三种类型文件。通常设置为 html,其优点是能直接通过 Web 浏览器查看。

1
2
3
4
5
6
7
8
# Write  output to stdout given one of the following files and the
# corresponding extension for the output format:
#
# /path/file.csv - Comma-separated values (CSV)
# /path/file.json - JSON (JavaScript Object Notation)
# /path/file.html - HTML
#
output /var/www/html/goaccess/index.html

7. 解析 IP 地理位置

如果要启用 GoAccess 解析客户端 IP 地理位置的功能,我们还需要加载 GeoIP 数据库文件。GeoIP 数据库文件可以在 MaxMind 下载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# === GeoIP2
# For GeoIP2 databases, you can use DB-IP Lite databases.
# DB-IP is licensed under a Creative Commons Attribution 4.0 International License.
# https://db-ip.com/db/lite.php

# Or you can download them from MaxMind
# https://dev.maxmind.com/geoip/geoip2/geolite2/

# For GeoIP2 City database:
# Download the GeoLite2-City.mmdb.gz
# gunzip GeoLite2-City.mmdb.gz
#
# For GeoIP2 Country database:
# Download the GeoLite2-Country.mmdb.gz
# gunzip GeoLite2-Country.mmdb.gz
#
geoip-database /usr/share/GeoIP/GeoLite2-City.mmdb

四、添加 GoAccess 服务

在正确配置 goaccess.conf 文件后,通过在终端中输入 goaccess 指令,便可运行程序。但是为了方便管理,让 GoAccess 能够在系统开机时自动运行。我们还可以手动添加 GoAccess 服务。

首先需要在 /etc/systemd/system 目录中添加 goaccess.service 文件,只需在终端中输入以下指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat >>/etc/systemd/system/goaccess.service <<'EOF'
[Unit]
Description=GoAccess Live Log Analyzer

[Service]
Type=simple
ExecStart=/usr/bin/goaccess
ExecStop=/bin/kill -9 ${MAINPID}
PrivateTmp=false

[Install]
WantedBy=multi-user.target
EOF

然后重新加载 systemd:

1
systemctl daemon-reload

最后启用 GoAccess 服务并运行:

1
2
systemctl enable goaccess.service 
systemctl start goaccess.service

五、在 nginx 中添加 GoAccess 访问入口

goaccess.conf 文件中,我们已经将输出的解析文件类型设置为 html。通过将 html 文件添加到 Web 服务器中,我们便可以在 Web 浏览器中直接查看 GoAccess 的解析结果。

nginx.conf 文件中,添加以下内容增加 GoAccess 的访问入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 443 ssl http2;

server_name goaccess.example.com;

location / {
root /var/www/html/goaccess/;
index index.html index.htm;
}

location /wss {
proxy_pass http://127.0.0.1:7890;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

重启 nginx,我们就可以通过 https://goaccess.example.com 来进行访问了。演示页面

六、解决页面不能实时更新

通常在正确配置后,访问页面就可以查看 GoAccess 的解析结果,如果开启了 real-time-html,网页会实时更新统计数据。更新数据通过 WebSocket 进行传输,此时页面左上角会有绿点,显示已经通过 WebSocket 连接到服务器。而如果右上角为灰点,显示为 Disconnected(已断开),则说明没有连接到服务器的 WebSocket 或已从服务器断开。

GoAccess 连接情况(左图为已连接,右图为未连接或已断开)
图1 GoAccess 连接情况
(左图为已连接,右图为未连接或已断开)

不能正常连接 WebSocket 的原因有很多,主要原因有:

  • ws-url 设置不正确,html 页面没有指向正确的 WebSocket 地址。
  • Web 服务器没有正确配置 WebSocket 连接。
  • WebSocket 没有启用 wss 协议。

由于现代浏览器都已经阻止 HTTPS 网页加载混合内容(包括未加密的内容和连接),因此如果通过 HTTPS 访问 GoAccess 页面,必须让 WebSocket 使用 wss 协议,在 goaccess.conf 中, ws-url 必须以 wss:// 开头。

另外,使用 nginx 搭建 GoAccess 页面时,除了在虚拟主机中创建 html 的访问地址,还需要创建 WebSocket 的访问地址,地址要与 ws-url 中的设置对应。通常使用 Web 服务器来反向代理 WebSocket 连接。

例如,你使用 https://goaccess.example.com 来访问 GoAccess 页面,同时 ws-url 设置为 wss://goaccess.example.com:443/wss/。你需要在 nginx.conf 中添加 /wss/ 入口反向代理服务器的 Websocket 连接,来让用户访问该 WebSocket,如下所示:

1
2
3
4
5
6
7
8
9
10
11
location /wss {
proxy_pass http://127.0.0.1:7890;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

在浏览器的开发人员工具中,你可以看到 wss/ 的状态代码为 101 Switching Protocols,响应头中也会显示 HTTP 请求被升级成 WebSocket。理论上,GoAccess 页面左上角应该就会出现绿点。

开发人员工具中显示的 wss 连接状态
图2 开发人员工具中显示的 wss 连接状态

你可能发现,WebSocket 连接每次都会在 60 秒左右断开,这是因为 nginx 将等待后端的超时时间 proxy_read_timeout 默认设置为 60 秒,这个时间内如果服务端没有数据传输,WebSocket 连接便会断开。

如果你想延长网页实时更新的时间,只需在 WebSocket 的 location(例如 /wss)里添加 proxy_read_timeout 600s; 即可。

七、总结

相较于其他站点统计工具,GoAccess 更加轻便。从安装、配置到使用,过程都十分简单友好,而且解析的信息非常全面直观,其所支持的日志格式基本能满足大多数博主对站点统计需求。

参考资料

  1. GoAccess 中文站 - 操作手册. (https://www.goaccess.cc/?mod=man)
  2. GoAccess - Manual Page. (https://goaccess.io/man)
  3. GoAccess - Downloads. (https://goaccess.io/download)

利用 GoAccess 分析日志,将 Web 访问数据可视化
https://vickey.fun/2022/03/26/goaccess-analyzing-nginx-log-to-visualize-stat/
作者
饶玮琪
发布于
2022年3月26日
许可协议