原文地址: 网站用户行为日志采集和后台日志服务器搭建
网站流量数据统计分析,可以帮助网站管理员、运营人员、推广人员等实时获取网站流量信息,并从流量来源、网站内容、网站访客特性等多方面提供网站分析的数据依据。从而帮助提高网站流量,提升网站用户体验,让访客更多的沉淀下来变成会员或客户,通过更少的投入获取最大化的收入。
访问日志指用户访问网站时的所有访问、浏览、点击行为数据。比如点击了 哪一个链接,打开了哪一个页面,采用了哪个搜索项、总体会话时间等。而所有 这些信息都可通过网站日志保存下来。通过分析这些数据,可以获知许多对网站 运营至关重要的信息。采集的数据越全面,分析就能越精准。
日志的生成渠道分为以下两种:
在实际操作中,有以下几个方面的数据可以自定义的采集:
类型 | 列举 |
---|---|
系统特征 | 比如所采用的操作系统、浏览器、域名和访问速度等 |
访问特征 | 包括停留时间、点击的 URL、所点击的“页面标签”及标签的属性等 |
来源特征 | 包括来访 URL,来访 IP 等 |
来源特征 | 包括所访问的产品编号、产品类别、产品颜色、产品价格、产品 利润、产品数量和特价等级等 |
下面是博主访问京东首页,其自定义采集的数据日志格式的截取部分:
https://mercury.jd.com/log.gif?t=www.100000&m=UA-J2011-1&pin=zaomianbao&uid=1522992113160771150291522&sid=15229913133260771150291522|42&v=je=0$sc=24-bit$sr=1680x1050$ul=en-us$cs=UTF-8$dt=京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物!$hn=www.jd.com$fl=-$os=mac$br=chrome
埋点是指:在网页中预先加入小段 javascript 代码,这个代码片段一般会 动态创建一个 script 标签,并将 src 属性指向一个单独的 js 文件,此时这个单 独的 js 文件会被浏览器请求到并执行,这个 js 往往就是真正 的数据收集脚本。
数据收集完成后,js 会请求一个后端的数据收集脚本, 这个脚本一般是一个伪装成图片的动态脚本程序,js 会将收集到的数据通过 http 参数的方式传递给后端脚本,后端脚本解析参数并按固定格式记录到访问 日志,同时可能会在 http 响应中给客户端种植一些用于追踪的 cookie。
番外:为什么使用请求图片的形式收集?
步骤:
选型:这里我们选用Apache作为Web服务器,日志后台服务器使用Nginx处理日志请求,同时将JS前端日志收集脚本直接放置在Nginx服务器内(架构中将其单独部署一个服务器)。
名称 | 途径 | 备注 |
---|---|---|
访问时间 | web server | Nginx $msec |
IP | web server | Nginx $remote_addr |
域名 | JavaScript | document.domain |
URL | JavaScript | document.URL |
页面标题 | JavaScript | document.title |
分辨率 | JavaScript | window.screen.height & width |
颜色深度 | JavaScript | window.screen.colorDepth |
Referrer | JavaScript | document.referrer |
浏览客户端 | web server | Nginx $http_user_agent |
客户端语言 | javascript | navigator.language |
访客标识 | cookie | Nginx $http_cookie |
网站标识 | javascript | 自定义对象 |
状态码 | web server | Nginx $status |
发送内容量 | web server | Nginx $body_bytes_sent |
埋点,是网站分析的一种常用的数据采集方法。核心就是在需要进行数据采 集的关键点植入统计代码,进行数据的采集。比如以谷歌分析原型来说,需要在 页面中插入一段它提供的 javascript 片段,这个片段往往被称为 。
其中_maq 是全局数组,用于放置各种配置,其中每一条配置的格式为:
_maq 的机制不是重点,重点是后面匿名函数的代码,这段代码的主要目的
就是引入一个外部的 js 文件(ma.js),方式是通过 document.createElement 方法 创建一个 script 并根据协议(http 或 https)将 src 指向对应的 ma.js,最后将这个 元素插入页面的 dom 树上。
注意 ma.async = true 的意思是异步调用外部 js 文件,即不阻塞浏览器的解 析,待外部 js 下载完成后异步执行。这个属性是 HTML5 新引入的。
番外:js 自调用匿名函数
数据收集脚本(ma.js)被请求后会被执行,一般要做如下几件事:
这里唯一的问题是步骤 4,javascript 请求后端脚本常用的方法是 ajax,但是ajax 是不能跨域请求的。一种通用的方法是 js 脚本创建一个 Image 对象,将 Image 对象的 src 属性指向后端脚本并携带参数,此时即实现了跨域请求后端。这也是 后端脚本为什么通常伪装成 gif 文件的原因。
示例JS代码:
(function () {
var params = {};
//Document对象数据
if(document) {
params.domain = document.domain || '';
params.url = document.URL || '';
params.title = document.title || '';
params.referrer = document.referrer || '';
}
//Window对象数据
if(window && window.screen) {
params.sh = window.screen.height || 0;
params.sw = window.screen.width || 0;
params.cd = window.screen.colorDepth || 0;
}
//navigator对象数据
if(navigator) {
params.lang = navigator.language || '';
}
//解析_maq配置
if(_maq) {
for(var i in _maq) {
switch(_maq[i][0]) {
case '_setAccount':
params.account = _maq[i][1];
break;
default:
break;
}
}
}
//拼接参数串
var args = '';
for(var i in params) {
if(args != '') {
args += '&';
}
args += i + '=' + encodeURIComponent(params[i]);
}
//通过Image对象请求后端脚本
var img = new Image(1, 1);
img.src = 'http://192.168.214.152/log.gif?' + args;
})();
整个脚本放在匿名函数里,确保不会污染全局环境。其中 log.gif 表面上请求静态资源,到了Nginx后台实则为一个后台脚本
日志格式主要考虑日志分隔符,一般会有以下几种选择:固定数量的字符、制表符分隔符、空格分隔符、其他一个或多个字符、特定的开始和结束文本。
我们在 nginx 的配置文件中定义日志格式:
log_format
"$msec||$remote_addr||$status||$body_bytes_sent||$u_domain||$u_url|
|$u_title||$u_referrer||$u_sh||$u_sw||$u_cd||$u_lang||$http_user_ag
ent||$u_account";
注意这里以 u_开头的是我们待会会自己定义的变量,其它的是nginx内置变量
log.gif 是后端脚本,是一个伪装成 gif 图片的脚本。后端脚本一般需要完 成以下几件事情:
之所以要设置 cookie 是因为如果要跟踪唯一访客,通常做法是如果在请求 时发现客户端没有指定的跟踪 cookie,则根据规则生成一个全局唯一的 cookie 并 种植给用户,否则 Set-cookie 中放置获取到的跟踪 cookie 以保持同一用户 cookie 不变。这种做法虽然不是完美的(例如用户清掉 cookie 或更换浏览器会被认为是两个用户),但是目前被广泛使用的手段。
我们使用 nginx 的 access_log 做日志收集,不过有个问题就是 nginx 配置本身的逻辑表达能力有限,所以选用 OpenResty 做这个事情。
番外:什么是OpenResty?
OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。其中的核心是通过 ngx_lua 模块集成了 Lua,从而在 nginx 配置文 件中可以通过 Lua 来表述业务。而Lua 是一种轻量小巧的脚本语言,用标准 C 语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
这里给出Nginx配置文件
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format user_log_format "$msec||$remote_addr||$status||$body_bytes_sent||$u_domain||$u_url||$u_title||$u_referrer||$u_sh||$u_sw||$u_cd||$u_lang||$http_user_agent||$u_account";
sendfile on; #允许sendfile方式传输文件,默认为off
keepalive_timeout 65; #连接超时时间,默认为75s
server {
listen 80;
server_name localhost;
location /log.gif {
#伪装成gif文件
default_type image/gif;
#nginx本身记录的access_log,日志格式为main
access_log logs/access.log main;
access_by_lua "
-- 用户跟踪cookie名为__utrace
local uid = ngx.var.cookie___utrace
if not uid then
-- 如果没有则生成一个跟踪cookie,算法为md5(时间戳+IP+客户端信息)
uid = ngx.md5(ngx.now() .. ngx.var.remote_addr .. ngx.var.http_user_agent)
end
ngx.header['Set-Cookie'] = {'__utrace=' .. uid .. '; path=/'}
if ngx.var.arg_domain then
-- 通过subrequest到/i-log记录日志,将参数和用户跟踪cookie带过去
ngx.location.capture('/i-log?' .. ngx.var.args .. '&utrace=' .. uid)
end
";
#此请求资源本地不缓存
add_header Expires "Fri, 01 Jan 1980 00:00:00 GMT";
add_header Pragma "no-cache";
add_header Cache-Control "no-cache, max-age=0, must-revalidate";
#返回一个1×1的空gif图片
empty_gif;
}
location /i-log {
#内部location,不允许外部直接访问
internal;
#设置变量,注意需要unescape
set_unescape_uri $u_domain $arg_domain;
set_unescape_uri $u_url $arg_url;
set_unescape_uri $u_title $arg_title;
set_unescape_uri $u_referrer $arg_referrer;
set_unescape_uri $u_sh $arg_sh;
set_unescape_uri $u_sw $arg_sw;
set_unescape_uri $u_cd $arg_cd;
set_unescape_uri $u_lang $arg_lang;
set_unescape_uri $u_account $arg_account;
#打开subrequest(子请求)日志
log_subrequest on;
#自定义采集的日志,记录数据到user_defined.log
access_log logs/user_defined.log user_log_format;
#输出空字符串
echo '';
}
}
}
注:这里是对192.168.214.152日志处理Nignx服务器的搭建,对于web服务器,直接在192.168.214.150服务器上执行yum install httpd即可安装成功。
这里自己准备需要的安装包——注:Linux上传方式:三种方式实现Linux的文件上传下载
[root@centos6-3 software]# cd /export/software/
[root@centos6-3 software]# ll
total 5900
//一个Lua包,一个nginx包,一个openresty包,4个nginx模块包
-rw-r--r--. 1 root root 64779 Jun 26 08:38 echo-nginx-module-0.58.tar.gz
-rw-r--r--. 1 root root 847615 Jun 26 08:38 LuaJIT-2.0.4.tar.gz
-rw-r--r--. 1 root root 569372 Jun 26 08:41 lua-nginx-module-0.10.0.tar.gz
-rw-r--r--. 1 root root 833473 Jun 26 08:38 nginx-1.8.1.tar.gz
-rw-r--r--. 1 root root 65029 Jun 26 08:38 ngx_devel_kit-0.2.19.tar.gz
-rw-r--r--. 1 root root 3616491 Jun 26 08:40 openresty-1.9.7.3.tar.gz
-rw-r--r--. 1 root root 35495 Jun 26 08:38 set-misc-nginx-module-0.29.tar.gz
[root@centos6-3 software]#
[root@centos6-3 software]# yum -y install gcc perl pcre-devel openssl openssl-devel
[root@centos6-3 software]# tar -zxvf LuaJIT-2.0.4.tar.gz -C /usr/local/src/
LuaJIT-2.0.4/
LuaJIT-2.0.4/COPYRIGHT
LuaJIT-2.0.4/Makefile
LuaJIT-2.0.4/README
LuaJIT-2.0.4/doc/
LuaJIT-2.0.4/doc/bluequad-print.css
....
[root@centos6-3 software]# cd /usr/local/src/LuaJIT-2.0.4/
[root@centos6-3 LuaJIT-2.0.4]# make && make install PREFIX=/usr/local/luajit
==== Building LuaJIT 2.0.4 ====
make -C src
...
[root@centos6-3 LuaJIT-2.0.4]#
[root@centos6-3 LuaJIT-2.0.4]# vi /etc/profile
//文件末尾追加以下内容
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0
//更新环境变量
[root@centos6-3 LuaJIT-2.0.4]# source /etc/profile
[root@centos6-3 LuaJIT-2.0.4]#
[root@centos6-3 LuaJIT-2.0.4]# mkdir -p /usr/local/nginx/modules
[root@centos6-3 LuaJIT-2.0.4]# cd /export/software/
[root@centos6-3 software]# mv set-misc-nginx-module-0.29.tar.gz /usr/local/nginx/modules/
[root@centos6-3 software]# mv lua-nginx-module-0.10.0.tar.gz /usr/local/nginx/modules/
[root@centos6-3 software]# mv ngx_devel_kit-0.2.19.tar.gz /usr/local/nginx/modules/
[root@centos6-3 software]# mv echo-nginx-module-0.58.tar.gz /usr/local/nginx/modules/
[root@centos6-3 software]# cd /usr/local/nginx/modules/
[root@centos6-3 modules]# ll
total 724
-rw-r--r--. 1 root root 64779 Jun 26 08:38 echo-nginx-module-0.58.tar.gz
-rw-r--r--. 1 root root 569372 Jun 26 08:41 lua-nginx-module-0.10.0.tar.gz
-rw-r--r--. 1 root root 65029 Jun 26 08:38 ngx_devel_kit-0.2.19.tar.gz
-rw-r--r--. 1 root root 35495 Jun 26 08:38 set-misc-nginx-module-0.29.tar.gz
[root@centos6-3 modules]# tar -zxvf lua-nginx-module-0.10.0.tar.gz
[root@centos6-3 modules]# tar -zxvf set-misc-nginx-module-0.29.tar.gz
[root@centos6-3 modules]# tar -zxvf ngx_devel_kit-0.2.19.tar.gz
[root@centos6-3 modules]# tar -zxvf echo-nginx-module-0.58.tar.gz
[root@centos6-3 modules]# ll
total 740
drwxrwxr-x. 6 root root 4096 Jun 22 2015 echo-nginx-module-0.58
-rw-r--r--. 1 root root 64779 Jun 26 08:38 echo-nginx-module-0.58.tar.gz
drwxrwxr-x. 9 root root 4096 Jan 12 2016 lua-nginx-module-0.10.0
-rw-r--r--. 1 root root 569372 Jun 26 08:41 lua-nginx-module-0.10.0.tar.gz
drwxrwxr-x. 9 root root 4096 Sep 26 2013 ngx_devel_kit-0.2.19
-rw-r--r--. 1 root root 65029 Jun 26 08:38 ngx_devel_kit-0.2.19.tar.gz
drwxrwxr-x. 6 root root 4096 Jun 22 2015 set-misc-nginx-module-0.29
-rw-r--r--. 1 root root 35495 Jun 26 08:38 set-misc-nginx-module-0.29.tar.gz
[root@centos6-3 modules]# rm -rf *.tar.gz
[root@centos6-3 modules]# ll
total 16
drwxrwxr-x. 6 root root 4096 Jun 22 2015 echo-nginx-module-0.58
drwxrwxr-x. 9 root root 4096 Jan 12 2016 lua-nginx-module-0.10.0
drwxrwxr-x. 9 root root 4096 Sep 26 2013 ngx_devel_kit-0.2.19
drwxrwxr-x. 6 root root 4096 Jun 22 2015 set-misc-nginx-module-0.29
[root@centos6-3 modules]#
[root@centos6-3 modules]# cd /export/software/
[root@centos6-3 software]# ll
total 5176
-rw-r--r--. 1 root root 847615 Jun 26 08:38 LuaJIT-2.0.4.tar.gz
-rw-r--r--. 1 root root 833473 Jun 26 08:38 nginx-1.8.1.tar.gz
-rw-r--r--. 1 root root 3616491 Jun 26 08:40 openresty-1.9.7.3.tar.gz
[root@centos6-3 software]# tar -zxvf openresty-1.9.7.3.tar.gz -C /usr/local/src/
[root@centos6-3 software]# cd /usr/local/src/openresty-1.9.7.3/
[root@centos6-3 openresty-1.9.7.3]# ./configure --prefix=/usr/local/openresty --with-luajit && make && make install
[root@centos6-3 openresty-1.9.7.3]#
[root@centos6-3 openresty-1.9.7.3]# cd /export/software/
[root@centos6-3 software]# ll
total 5176
-rw-r--r--. 1 root root 847615 Jun 26 08:38 LuaJIT-2.0.4.tar.gz
-rw-r--r--. 1 root root 833473 Jun 26 08:38 nginx-1.8.1.tar.gz
-rw-r--r--. 1 root root 3616491 Jun 26 08:40 openresty-1.9.7.3.tar.gz
[root@centos6-3 software]# tar -zxvf nginx-1.8.1.tar.gz -C /usr/local/src/
[root@centos6-3 software]# cd /usr/local/src/nginx-1.8.1/
[root@centos6-3 nginx-1.8.1]# ./configure --prefix=/usr/local/nginx \
> --with-ld-opt="-Wl,-rpath,/usr/local/luajit/lib" \
> --add-module=/usr/local/nginx/modules/ngx_devel_kit-0.2.19 \
> --add-module=/usr/local/nginx/modules/lua-nginx-module-0.10.0 \
> --add-module=/usr/local/nginx/modules/set-misc-nginx-module-0.29 \
> --add-module=/usr/local/nginx/modules/echo-nginx-module-0.58
make -j2
[root@centos6-3 nginx-1.8.1]# make install
[root@centos6-3 nginx-1.8.1]# cd /usr/local/nginx/
[root@centos6-3 nginx]# ll
total 20
drwxr-xr-x. 2 root root 4096 Jul 3 17:09 conf
drwxr-xr-x. 2 root root 4096 Jul 3 17:09 html
drwxr-xr-x. 2 root root 4096 Jul 3 17:09 logs
drwxr-xr-x. 6 root root 4096 Jul 3 16:59 modules
drwxr-xr-x. 2 root root 4096 Jul 3 17:09 sbin
[root@centos6-3 nginx]# ./sbin/nginx -c conf/nginx.conf
[root@centos6-3 nginx]#
访问192.168.214.152(默认80端口)
后台日志处理Nginx服务器搭建成功!
枣面包的面包坊
枣面包的面包坊
在192.168.214.150的Apache服务器部署index.html
上传index.html到Apache目录下:/var/www/html
注:Linux上传方式:三种方式实现Linux的文件上传下载
[root@centos6-1 html]# rz
rz waiting to receive.
Starting zmodem transfer. Press Ctrl+C to cancel.
Transferring index.html...
100% 568 bytes 568 bytes/sec 00:00:01 0 Errors
[root@centos6-1 html]# ls
index.html
[root@centos6-1 html]#
在192.168.214.152的Nginx服务器部署ma.js
上传ma.js到Nginx目录下:/usr/local/nginx/html
[root@centos6-3 html]# rz
rz waiting to receive.
Starting zmodem transfer. Press Ctrl+C to cancel.
Transferring ma.js...
100% 1 KB 1 KB/sec 00:00:01 0 Errors
[root@centos6-3 html]# ll
total 11
-rw-r--r--. 1 root root 537 Jul 3 17:09 50x.html
-rw-r--r--. 1 root root 1249 Jul 3 2018 ma.js
将nginx.conf文件修改成上面3.5的内容,这里不做重复,读者在按照博主上面系统环境搭建部署完成后,可以直接复制配置内容使用,可以不必对配置中使用到的lua语义过分深究
启动192.168.214.150下的Apache
[root@centos6-1 html]# httpd
[root@centos6-1 html]# ps -ef|grep httpd
root 42392 1 0 19:41 ? 00:00:00 httpd
apache 42393 42392 0 19:41 ? 00:00:00 httpd
apache 42394 42392 0 19:41 ? 00:00:00 httpd
apache 42395 42392 0 19:41 ? 00:00:00 httpd
apache 42396 42392 0 19:41 ? 00:00:00 httpd
apache 42397 42392 0 19:41 ? 00:00:00 httpd
apache 42398 42392 0 19:41 ? 00:00:00 httpd
apache 42399 42392 0 19:41 ? 00:00:00 httpd
apache 42400 42392 0 19:41 ? 00:00:00 httpd
root 42404 42010 0 19:42 pts/0 00:00:00 grep httpd
[root@centos6-1 html]#
启动192.168.214.152下的Nginx
[root@centos6-3 nginx]# sbin/nginx -c conf/nginx.conf
[root@centos6-3 nginx]# ps -ef|grep nginx
root 50763 1 0 19:31 ? 00:00:00 nginx: master process sbin/nginx -c conf/nginx.conf
nobody 50764 50763 0 19:31 ? 00:00:00 nginx: worker process
nobody 50765 50763 0 19:31 ? 00:00:00 nginx: worker process
root 50792 50325 0 19:43 pts/0 00:00:00 grep nginx
在192.168.214.152的nginx目录下执行命令实时观察日志变化
[root@centos6-3 nginx]# tail -f logs/user_defined.log
页面访问192.168.214.150的index.html页面触发
发现请求到了ma.js文件,同时发送了log.gif请求并且状态为200,即请求成功。再去刚才实时观察的shell窗口发现日志已经被收集
[root@centos6-3 nginx]# tail -f logs/user_defined.log
1530618381.695||192.168.214.1||200||0||192.168.214.150||http://192.168.214.150/||\xE6\x9E\xA3\xE9\x9D\xA2\xE5\x8C\x85\xE7\x9A\x84\xE9\x9D\xA2\xE5\x8C\x85\xE5\x9D\x8A||||1050||1680||24||en-US||Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36||zaomianbao
到这里一个整体的结构就成功构建好了,后面使用就行了,当然,这里只有访问页面的触发,并没有添加用户点击事件,这个留给读者在使用中根据业务添加即可。以上内容并没有假如日志切分的展现,读者直接添加即可。本篇博客的架构设计经过优化是可以运用到生产实际当中的。如有错误,欢迎指正。
参考资料:
http://openresty.org/en/
http://nginx.org/en/download.html
https://blog.csdn.net/weixin_37490221/article/details/80849163
http://www.lua.org/about.html
http://www.runoob.com/lua/lua-tutorial.html
以及博主学习使用的PDF文档