用new Image().src作LOG统计的一个注意事项 .
在大型网站做很多用户行为分析、产品的策划方案基本上都是通过分析用户的访问等信息而做出的,LOG信息的统计准确性会直接影响到产品的设计开发(比如搜索结果的先后排名rank值的产生等)。目前最常用的一个写LOG的方法就是用JavaScript脚本在网页里 new Image().src = "http://xxx.com/log?msg="+ msg; 这种统计方法基本上不会干扰用户的正常操作,虽然有LOG丢失的可能,但只要用得好,还是一种非常好的LOG统计回收的方案。
但是这种LOG回收手段有一个非常隐秘的隐患,事情是这样被发现的。今年3月份百度搜索结果页面上线了Suggestion功能升级版,在LOG统计中突然发现上线后的LOG总量比上线前的少了很多(10%以上),表现出来的现象就是LOG丢失了,没有回收到服务器中来。
工程师立即做了详细排除,从各种因素上确定LOG的大量丢失跟网页上线Suggestion有关,我们马上对Suggestion脚本进行地毯式排查,逐行分析代码,结论是这个脚本没有阻拦 new Image().src 的发包请求(至少表面上是这样的),这段脚本放在一个脚本闭包中,没有影响到全局变量/方法,也没有屏蔽干扰HTTP请求的因素。
我们又做了一个线下试验,同样的代码环境,在线下的测试环境中用这种 new Image().src 的手段,总共向Server端发送了10000个LOG数据,也没有发生LOG丢失,试验的结果也没有发现LOG丢失的原因。
但是在线上的环境中发生的就是有LOG数据丢失,原因不明,所以只能紧急下线这个Suggestion升级版。在这个脚本下线之后,LOG统计数据马上回归到“原正常”状态。从这个现象来看,也从另一个角度说明上线的新脚本确实对LOG统计有影响,头疼呀......
愚者千虑,必有一得!最后方知这个问题的原因是浏览器的垃圾回收机制!
function c(q) {
var p=window.document.location.href,sQ='',sV='';
for(v in q){
switch (v){
case "title":sV=encodeURIComponent(q[v].replace(/<[^<>]+>/g,""));break;
case "url":sV=escape(q[v]);break;
default:sV=q[v]
}
sQ+=v+"="+sV+"&";
}
new Image().src = "http://s.baidu.com/w.gif?q=meizz&"+sQ+"path="+p+"&cid=9&t="+ new Date().getTime();
return true;
}
这个 new Image() 对象没有赋给任何变量,在这个函数执行结束时,浏览器的垃圾回收机制对这种“无主”的对象是毫不客气的回收的,而正是这种回收行为导致了这个HTTP请求(异步的)没有发出,从而造成了LOG数据的丢失。那为什么上线一个脚本就会造成大量的LOG丢失呢?因为一个大脚本的运行回产生大量的“垃圾”,浏览器垃圾回收也会相应地更频繁的启动,从而造成LOG数据丢失。找到原因之后对症下药,把这个 new Image() 对象赋给一个全局有变量常期持有即可,相应的代码如下:
var n = "log_"+ (newDate()).getTime();
var c = window[n] =newImage(); //把new Image()赋给一个全局变量长期持有
c.onload = (c.onerror=function(){window[n] = null;});
c.src = "http://s.baidu.com/w.gif?q=meizz"+ xxxx;
c = null; //释放局部变量c
在这个统计代码上线之后,百度的搜索结果页面的LOG立即多出近10%,之后再上线其它的脚本也没有再出现LOG统计量的波动。
---------------------------------------------------------------------------------------------------------------------------------
局部变量下,测试连续发1000个log
IE6-7 发现log丢失,某些IE内核浏览器也发现log丢失
但在FF, chrome下未发现丢失
因此 保险的做法是用一个非局部变量持有
- var unique = (function () {
- var time= (new Date()).getTime()+'-', i=0;
- return function () {
- return time + (i++);
- }
- })();
- var imgLog = function (url) {
- var data = window['imgLogData'] || (window['imgLogData'] = {});
- var img = new Image();
- var uid = unique();
- img.onload = img.onerror = function () {//销毁一些对象
- img.onload = img.onerror = null;
- img = null;
- delete data[uid];
- }
- img.src = url + '&_uid=' + uid;
- };
var unique = (function () {
var time= (new Date()).getTime()+'-', i=0;
return function () {
return time + (i++);
}
})();
var imgLog = function (url) {
var data = window['imgLogData'] || (window['imgLogData'] = {});
var img = new Image();
var uid = unique();
img.onload = img.onerror = function () {//销毁一些对象
img.onload = img.onerror = null;
img = null;
delete data[uid];
}
img.src = url + '&_uid=' + uid;
};
转自 http://blog.csdn.net/fudesign2008/article/details/6772108
用new Image().src作LOG统计的一个注意事项 .的更多相关文章
- python统计某一个进程名所占用的内存
设计思路: 通过python,执行cmd中tasklist命令,获取要统计的进程的相关信息:通过正则表达式,查找出进程名称.进程pid.内存使用,然后打印出来. 作为pythoner,有时候需要统计p ...
- 关于apache access log 统计的那些事儿
统计APACHE ACCESS.LOG IP访问记录 可以根据自己的需要,统计很多,每个IP访问多少个页面等等! cat access.log-20090904 |awk '{print $3}'|s ...
- Eviews作时间序列分析的一个实例
时间序列分析是作时间序列数据预测的一个重要部分,由于此次实验室竞赛也用到了时间序列分析,就在此说一下平稳性分析以及非平稳处理的方法: 1.判断平稳性 1.1平稳性的定义 ...
- js正则获取图片的src属性及正则分割一个字符串
try{ var str='<P>xczxzxzxcxcxc<IMG src="http://file.ynet.com/2/1612/12/12119048.jp ...
- git log查看某一个分支的提交
如果想查看某一个分支的提交信息:git log 或者是查看分支名:git log $分支名/tag名/远程分支名 查看提交的详情: git log -p
- 统计的一个小题目python实现
最近面试碰到的一个题目,业余时间用python实现的. 拿到数据,先用sort 命令排序,也可再进一步去重复 sort -k 1,2 data.txt |uniq > data.new # ...
- 素数计数函数$\pi(x)\sim \Theta(\frac{x}{\log{x}})$的一个初等方法——素数定理的估计
$\DeclareMathOperator{\lcm}{lcm}$ 本文的方法来源于GTM 190:"Problems in Algebraic Number Theory",给出 ...
- 统计Oracle一个表空间中各个segment占用的空间大小
SQL语句参考以下: select owner,segment_name,segment_type,tablespace_name,sum(bytes)/1024/1024/1024 from dba ...
- 2017/10 冲刺NOIP集训记录:暁の水平线に胜利を刻むのです!
前几次集训都没有记录每天的点滴……感觉缺失了很多反思的机会. 这次就从今天开始吧!不能懈怠,稳步前进! 2017/10/1 今天上午进行了集训的第一次考试…… 但是这次考试似乎是近几次我考得最渣的一次 ...
随机推荐
- DBProxy 入门到精通系列(一):DBProxy概述
DBProxy概述 DBProxy是支持分库分表,读写分离的中间件,博客内容除了阅读github官方文档外,还会附加上本人个人测试的结果,但了解一个中间件,需要对这个中间件有一个基本的认识,方便控制. ...
- MySQL中的SQL流程分析简述
分析MySQL中这条语句的整个流程 update table_a set c1=xx where c2=xxx 朋友考我的一个问题在此处列出个人见解 1 客户端连接进来首先进行权限验证 2 验证通过后 ...
- 登录案例locustfile.py
# 保存为locustfile.py # coding=utf-8 from locust import HttpLocust, TaskSet, task ''' 实现场景:先登录(只登录一次),然 ...
- git原理:pack打包
git向磁盘中存储对象使用“松散(loose)”对象格式.比如文件a.txt第一个版本大小是10k,第二个版本向其中添加了一行代码,假如此时文件为10.1k,那么第二个版本会重新产生一个1.1k的文件 ...
- 数据库质疑修复(SUSPECT)总结,DBCC报错
当SQL SERVER数据库状态为质疑(SUSPECT)状态时,我们可以用以下方法来处理: DBCC报错 1. 修改数据库为紧急模式:ALTER DATABASE DBName SET EMERGEN ...
- Mybatis使用pageHelper步骤
1.在pom.xml中添加如下依赖: <dependency> <groupId>com.github.pagehelper</groupId> <artif ...
- Percona备份mysql全库及指定数据库(完整备份与增量备份)
Percona Xtrabackup备份mysql全库及指定数据库(完整备份与增量备份) Xtrabackup简介 Percona XtraBackup是开源免费的MySQL数据库热备份软件,它能对I ...
- spring项目报org.apache.tiles.definition.DefinitionsFactoryException: I/O错误原因及解决办法。
今天升级一个spring项目遇到如下错: HTTP Status 500 - Request processing failed; nested exception is org.apache.til ...
- Python基础(16)_面向对象程序设计(类、继承、派生、组合、接口)
一.面向过程程序设计与面向对象程序设计 面向过程的程序设计:核心是过程,过程就解决问题的步骤,基于该思想设计程序就像是在设计一条流水线,是一种机械式的思维方式 优点:复杂的问题的简单化,流程化 缺点: ...
- 谷歌机器学习速成课程---3降低损失 (Reducing Loss):学习速率
正如之前所述,梯度矢量具有方向和大小.梯度下降法算法用梯度乘以一个称为学习速率(有时也称为步长)的标量,以确定下一个点的位置.例如,如果梯度大小为 2.5,学习速率为 0.01,则梯度下降法算法会选择 ...