网站数据统计分析工具是网站站长和运营人员经常使用的一种工具,比较常用的有谷歌分析、百度统计和腾讯分析等等。所有这些统计分析工具的第一步都是网站访问数据的收集。目前主流的数据收集方式基本都是基于javascript的。
收集信息
| 名称 | 途径 | 备注 | 
|---|
| 访问时间 | 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 |  | 
| 网站标识 | javascript | 自定义对象 | 
埋点代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | <script type="text/javascript">  var _maq = _maq || [];
 _maq.push(['_setAccount', '网站标识']);
 
 (function() {
 var ma = document.createElement('script'); ma.type = 'text/javascript'; ma.async = true;
 ma.src = ('https:' == document.location.protocol ? 'https://tj' : 'http://tj') + '.tongji.com/ma.js';
 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ma, s);
 })();
 </script>
 
 | 
前端统计脚本
| 12
 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
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 
 | (function () {  var params = {};
 
 if(document) {
 params.domain = document.domain || '';
 params.url = document.URL || '';
 params.title = document.title || '';
 params.referrer = document.referrer || '';
 }
 
 if(window && window.screen) {
 params.sh = window.screen.height || 0;
 params.sw = window.screen.width || 0;
 params.cd = window.screen.colorDepth || 0;
 }
 
 if(navigator) {
 params.lang = navigator.language || '';
 }
 
 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]);
 }
 
 
 var img = new Image(1, 1);
 img.src = 'http://tj.tongji.com/1.gif?' + args;
 })();
 
 | 
日志格式
需要在nginx的配置文件中定义日志格式
| 12
 3
 4
 
 | 
 
 log_format tick "$msec^A$remote_addr^A$u_domain^A$u_url^A$u_title^A$u_referrer^A$u_sh^A$u_sw^A$u_cd^A$u_lang^A$http_user_agent^A$u_utrace^A$u_account";
 
 | 
Nginx+Lua配置
nginx配置本身的逻辑表达能力有限,这里选用了OpenResty做这个事情。OpenResty是一个基于Nginx扩展出的高性能应用开发平台,内部集成了诸多有用的模块,其中的核心是通过ngx_lua模块集成了 Lua,从而在nginx配置文件中可以通过Lua来表述业务。这里用到了诸多第三方ngxin模块(全都包含在OpenResty中了)
| 12
 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
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 
 | location /1.gif {  
 default_type image/gif;
 
 access_log off;
 
 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";
 
 
 empty_gif;
 }
 
 location /i-log {
 
 internal;
 
 
 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_utrace $arg_utrace;
 set_unescape_uri $u_account $arg_account;
 
 
 log_subrequest on;
 
 access_log /path/to/logs/directory/ma.log tick;
 
 
 echo '';
 }
 
 | 
日志轮转
真正的日志收集系统访问日志会非常多,时间一长文件变得很大,而且日志放在一个文件不便于管理。所以通常要按时间段将日志切分,例如每天或每小时切分一个日志。这里为了效果明显,每一小时切分一个日志。并通过crontab定时调用一个shell脚本实现
| 12
 3
 4
 5
 6
 
 | _prefix="/path/to/nginx"
 time=`date +%Y%m%d%H`
 
 mv ${_prefix}/logs/ma.log ${_prefix}/logs/ma/ma-${time}.log
 kill -USR1 `cat ${_prefix}/logs/nginx.pid`
 
 | 
Contab配置
| 1
 | 59  *  *  *  * root /path/to/directory/rotatelog.sh
 | 
关于分析
注意,原始日志最好尽量多的保留信息而不要做过多过滤和处理。例如上面的MyAnalytics保留了毫秒级时间戳而不是格式化后的时间,时间的格式化是后面的系统做的事而不是日志收集系统的责任。后面的系统根据原始日志可以分析出很多东西,例如通过IP库可以定位访问者的地域、user agent中可以得到访问者的操作系统、浏览器等信息,再结合复杂的分析模型,就可以做流量、来源、访客、地域、路径等分析了。当然,一般不会直接对原始日志分析,而是会将其清洗格式化后转存到其它地方,如MySQL或HBase中再做分析。
