【系统架构】用JS记录整网页的加载时长

                                                                    用JS记录整网页的加载时长

       导读:

       随着浏览器的发展的发展,现行的浏览器的插件已经提供了查看时间轨迹的工具,如IE的内置调试工具,火狐的firedug,httpWatch等,为单次调制提供了很大极大便利
       但是如果对于获取多个用户的页面打开统计时长,仍然比较棘手,常用的方式是在服务端进行时间的处理,但是这样会忽略网络请求和网络发送的时长,为了解决这些问题
       可以考虑在浏览中运用JS来记录整个页面的所有加载全部时长。

     1.几种常见触发函数的理解
  2.如何判断页面是刷新还是关闭?
  3.深入思考页面的开始渲染时间
  4.前后页面的通讯方式
        5.获取计算页面加载完成的时间
        6.本次计算加载时长最终采用方案
        7.与真实时间的差异性对比

  1.几种常见触发函数的理解


1. <span class="pln">unload</span><span class="pun">,</span><span class="pln">onbeforeunload</span><span class="pun">都是在刷新或关闭时调用,可以在&lt;</span><span class="pln">script</span><span class="pun">&gt;脚本中通过</span><span class="pln">window</span><span class="pun">.</span><span class="pln">onunload</span><span class="pun">来指定或者在&lt;</span><span class="pln">body</span><span class="pun">&gt;里指定。</span>
2. <span class="pun">区别在于</span><span class="pln">onbeforeunload</span><span class="pun">在</span><span class="pln">onunload</span><span class="pun">之前执行,它还可以阻止</span><span class="pln">onunload</span><span class="pun">的执行。</span><span class="pln">   </span>
3. <span class="typ">Onbeforeunload</span><span class="pun">也是在页面刷新或关闭时调用,</span><span class="typ">Onbeforeunload</span><span class="pun">是正要去服务器读取新的页面时调用,此时还没开始读取;</span>
4. <span class="pln">onunload</span><span class="pun">则已经从服务器上读到了需要加载的新的页面,在即将替换掉当前页面时调用。</span><span class="typ">Onunload</span><span class="pun">是无法阻止页面的更新和关闭的。而</span><span class="pln"> </span><span class="typ">Onbeforeunload</span><span class="pln"> </span><span class="pun">可以做到。</span><span class="pln"> </span>
5. <span class="pun">页面加载时只执行</span><span class="pln">onload </span>
6. <span class="pun">页面关闭时先执行</span><span class="pln">onbeforeunload</span><span class="pun">,最后</span><span class="pln">onunload </span>
7. <span class="pun">页面刷新时先执行</span><span class="pln">onbeforeunload</span><span class="pun">,然后</span><span class="pln">onunload</span><span class="pun">,最后</span><span class="pln">onload</span><span class="pun">。</span><span class="pln"> </span>
> >       2.如何判断页面是刷新还是关闭?         


1. <span class="pln">window</span><span class="pun">.</span><span class="pln">onbeforeunload</span><span class="pun">=</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(){</span><span class="pln"> </span>
2. <span class="kwd">if</span><span class="pun">(</span><span class="pln">event</span><span class="pun">.</span><span class="pln">clientX</span><span class="pun">&gt;</span><span class="pln">document</span><span class="pun">.</span><span class="pln">body</span><span class="pun">.</span><span class="pln">clientWidth </span><span class="pun">&amp;&amp;</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">clientY </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">altKey</span><span class="pun">){</span><span class="pln"> </span>
3. <span class="pln">alert</span><span class="pun">(</span><span class="str">"你关闭了浏览器"</span><span class="pun">);</span><span class="pln"> </span>
4. <span class="pun">}</span><span class="kwd">else</span><span class="pun">{</span><span class="pln"> </span>
5. <span class="pln">alert</span><span class="pun">(</span><span class="str">"你正在刷新页面"</span><span class="pun">);</span><span class="pln"> </span>
6. <span class="pun">}</span><span class="pln"> </span>
7. <span class="pun">}</span><span class="pln"> </span>
       3.深入思考页面的开始渲染时间


1. <span class="typ">Onunload</span><span class="pun">,</span><span class="pln">onbeforeunload</span><span class="pun">都是在刷新或关闭时调用,可以在中第一句话开始,获取当前时间作为开始时间,这样得到的时间实际上忽略了去服务器请求的时间与部分页面渲染的时间</span>
2. <span class="pun">按照</span><span class="lit">1</span><span class="pun">中说法,对于首次请求的时间应该有服务器开始处理的时间(忽略了请求时间)对于刷新页面的开始时间应该是上一个页面的关闭后开始去服务器请求的时间,也就是</span><span class="typ">Onbeforeunload</span><span class="pun">调用时间</span>


  4.前后页面的通讯方式


1. <span class="pun">如果放在同一页面中设置全局变量,刷新时无法计算,所以页面刷新的介质一般是</span><span class="pln">cookie</span><span class="pun">,需要注意的是及时对</span><span class="pln">cookie</span><span class="pun">进行清理</span>

  5.获取计算页面加载完成的时间



1. <span class="pun"><span style="color: rgb(0, 0, 0); font-family: 'Microsoft YaHei UI', 'Microsoft YaHei', SimSun, 'Segoe UI', Tahoma, Helvetica, sans-serif, 'Microsoft YaHei', Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; line-height: 16.799999237060547px; white-space: normal;">a.常用方式,页面加载完成时会调用onload函数,获取onload中时间即为结束时间,问题:若是主框架中还有异步请求服务器的请求,并不能准确方式判断异步请求的结束时间,若解决这个问题则可以采用以下方式</span> </span>
2. <span class="pun">&lt;</span><span class="pln">html</span><span class="pun">&gt;</span>
3. <span class="pun">&lt;</span><span class="pln">head</span><span class="pun">&gt;</span>
4. <span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span>
5. <span class="kwd">function</span><span class="pln"> load</span><span class="pun">()</span>
6. <span class="pun">{</span>
7. //在此处获取时间
8. <span class="pln">window</span><span class="pun">.</span><span class="pln">status</span><span class="pun">=</span><span class="str">"Page is loaded"</span>
9. <span class="pun">}</span>
10. <span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span>
11. <span class="pun">&lt;/</span><span class="pln">head</span><span class="pun">&gt;</span>
12. <span class="pun">&lt;</span><span class="pln">body onload</span><span class="pun">=</span><span class="str">"load()"</span><span class="pun">&gt;</span>
13. <span class="pun">&lt;/</span><span class="pln">body</span><span class="pun">&gt;</span>
14. <span class="pun">&lt;/</span><span class="pln">html</span><span class="pun">&gt;</span>
        


1. <span class="com"><span style="color: rgb(0, 0, 0); font-family: 'Microsoft YaHei UI', 'Microsoft YaHei', SimSun, 'Segoe UI', Tahoma, Helvetica, sans-serif, 'Microsoft YaHei', Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; line-height: 16.799999237060547px; white-space: normal;">b.基于检查的计算时间方式,确定页面全部加载完成标志元素,比如页面的某个元素加载成功,每隔一段时间去检查页面上是否已经含有此元素,若含有则停止检查,执行操作</span> </span>
2. <span class="com">/*********记录日志开始************/</span>
3. <span class="kwd">var</span><span class="pln"> ssoTime </span><span class="pun">=</span><span class="pln"> getCookie</span><span class="pun">(</span><span class="str">"enterHomeTime"</span><span class="pun">);</span><span class="pln"> </span><span class="com">//获取SSO的跳转成功的时间</span>
4. <span class="kwd">var</span><span class="pln"> freTime </span><span class="pun">=</span><span class="pln"> parent</span><span class="pun">.</span><span class="pln">freTime</span><span class="pun">;</span><span class="pln"> </span><span class="com">//获取main页面刚进入的时间</span>
5. <span class="kwd">var</span><span class="pln"> mlen </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span>
6. <span class="kwd">var</span><span class="pln"> mindex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span>
7. <span class="kwd">var</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">=</span><span class="pln">self</span><span class="pun">.</span><span class="pln">setInterval</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(){</span>
8. <span class="pln"> mlen </span><span class="pun">=</span><span class="pln"> jQuery</span><span class="pun">(</span><span class="str">".mfi_dotline"</span><span class="pun">).</span><span class="pln">length</span><span class="pun">;</span>
9. <span class="pln"> mindex</span><span class="pun">++;</span>
10. <span class="pln"> </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">mlen</span><span class="pun">&gt;</span><span class="lit">23</span><span class="pln"> </span><span class="pun">||</span><span class="pln">mindex </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">20</span><span class="pun">){</span>
11. <span class="pln"> window</span><span class="pun">.</span><span class="pln">clearInterval</span><span class="pun">(</span><span class="kwd">int</span><span class="pun">);</span><span class="pln"> </span><span class="com">//停止循环</span>
12. <span class="pln"> </span><span class="kwd">var</span><span class="pln"> curTime </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">().</span><span class="pln">getTime</span><span class="pun">();</span>
13. <span class="pln"> </span><span class="kwd">var</span><span class="pln"> loadTime </span><span class="pun">;</span>
14. <span class="pln"> alert</span><span class="pun">(</span><span class="pln">getCookie</span><span class="pun">(</span><span class="str">"refresh"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="str">'true'</span><span class="pun">)</span>
15. <span class="pln"> </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">getCookie</span><span class="pun">(</span><span class="str">"refresh"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="str">'true'</span><span class="pun">){</span>
16. <span class="pln"> loadTime </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">curTime</span><span class="pun">-</span><span class="pln">freTime</span><span class="pun">)/</span><span class="lit">1000</span><span class="pun">;</span><span class="pln"> </span>
17. <span class="pln"> log_visit</span><span class="pun">(</span><span class="str">'&lt;s:property value="serverip"/&gt;'</span><span class="pun">,</span><span class="str">'系统首页'</span><span class="pun">,</span><span class="pln">loadTime</span><span class="pun">,</span><span class="str">'后续刷新'</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">'进入'</span><span class="pun">);</span>
18. <span class="pln"> </span><span class="pun">}</span><span class="kwd">else</span><span class="pun">{</span>
19. <span class="pln"> loadTime </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">curTime</span><span class="pun">-</span><span class="pln">ssoTime</span><span class="pun">)/</span><span class="lit">1000</span><span class="pun">;</span><span class="pln"> </span><span class="com">//第一次进入</span>
20. <span class="pln"> setCookie</span><span class="pun">(</span><span class="str">"refresh"</span><span class="pun">,</span><span class="str">"true"</span><span class="pun">);</span>
21. <span class="pln"> log_visit</span><span class="pun">(</span><span class="str">'&lt;s:property value="serverip"/&gt;'</span><span class="pun">,</span><span class="str">'系统首页'</span><span class="pun">,</span><span class="pln">loadTime</span><span class="pun">,</span><span class="str">'首次进入'</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">'进入'</span><span class="pun">);</span>
22. <span class="pln"> </span><span class="pun">}</span>
23. <span class="pln"> </span><span class="pun">}</span>
24. <span class="pun">},</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span>
25.


1. <span class="kwd"><span style="color: rgb(0, 0, 0); font-family: 'Microsoft YaHei UI', 'Microsoft YaHei', SimSun, 'Segoe UI', Tahoma, Helvetica, sans-serif, 'Microsoft YaHei', Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; line-height: 16.799999237060547px; white-space: normal;">c.基于事件的计算时间方式,在业务处理的代码中添加事件,当满足某种条件则执行操作,这种做法的缺点是与业务代码耦合度过高,【注意清理<span style="color: rgb(221, 17, 68); font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; line-height: 18px; white-space: pre;">refresh</span>】</span> </span>
2. <span class="kwd">if</span><span class="pun">(</span><span class="pln">portIndex</span><span class="pun">==</span><span class="pln">portTotalNum</span><span class="pun">){ //当满足某种条件时</span>
3. <span class="pln"> portIndex </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">999</span><span class="pun">; </span>
4. <span class="pln"> var ssoTime </span><span class="pun">=</span><span class="pln"> getCookie</span><span class="pun">(</span><span class="str">"enterHomeTime"</span><span class="pun">);</span><span class="pln"> </span><span class="com">//获取SSO的跳转成功的时间</span>
5. <span class="pln"> var freTime </span><span class="pun">=</span><span class="pln"> getCookie</span><span class="pun">(</span><span class="str">"freshToHomeTime"</span><span class="pun">);</span>
6. <span class="pln"> var curTime </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">().</span><span class="pln">getTime</span><span class="pun">();</span>
7. <span class="pln"> var loadTime </span><span class="pun">;</span>
8. <span class="pln"> </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">getCookie</span><span class="pun">(</span><span class="str">"refresh"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="str">'true'</span><span class="pun">){</span>
9. <span class="pln"> loadTime </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">curTime</span><span class="pun">-</span><span class="pln">freTime</span><span class="pun">)/</span><span class="lit">1000</span><span class="pun">;</span><span class="pln"> </span>
10. <span class="pln"> log_visit</span><span class="pun">(</span><span class="pln">serverip</span><span class="pun">,</span><span class="str">'系统首页'</span><span class="pun">,</span><span class="pln">loadTime</span><span class="pun">,</span><span class="str">'后续刷新'</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">'进入'</span><span class="pun">);</span>
11. <span class="pln"> </span><span class="pun">}</span><span class="kwd">else</span><span class="pun">{</span>
12. <span class="pln"> loadTime </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">curTime</span><span class="pun">-</span><span class="pln">ssoTime</span><span class="pun">)/</span><span class="lit">1000</span><span class="pun">;</span><span class="pln"> </span><span class="com">//第一次进入</span>
13. <span class="pln"> setCookie</span><span class="pun">(</span><span class="str">"refresh"</span><span class="pun">,</span><span class="str">"true"</span><span class="pun">);</span>
14. <span class="pln"> log_visit</span><span class="pun">(</span><span class="pln">serverip</span><span class="pun">,</span><span class="str">'系统首页'</span><span class="pun">,</span><span class="pln">loadTime</span><span class="pun">,</span><span class="str">'首次进入'</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">'进入'</span><span class="pun">);</span>
15. <span class="pln"> </span><span class="pun">}</span>
16. <span class="pln"> </span><span class="pun">}</span>

  6.本次计算加载时长最终采用方案

其中主框架为同步加载,在副框架均为异步加载,首页的整个加载顺序:先加载主框架,然后加载副1,然后加载副2,最后副2中豆腐块

首次进入的时间:SSO跳转进入的时间

a. SSO登录跳转成功后 准备转向首页的代码,核心代码如下

<span class="pln">&nbsp;</span>    <script>
<span class="pln"> &nbsp;</span>    setCookie(‘enterHomeTime’,new Date().getTime());
<span class="pln"> &nbsp;</span>    window.location.href=“<s:property value=’dispatchUrl.homeUrl’/>”;
<span class="pln"><span style="font-family: Consolas; color: rgb(30, 52, 123); font-size: 13px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;</span> </span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span>

后续刷新时间采用函数Onbeforeunload,此函数在页面刷新或关闭时调用,是正要去服务器读取新的页面时调用,此时还没开始读取,刷新的时候直接覆盖SSO写过来的时间

<span class="pln">&nbsp;</span>     <head>
<span class="pln"> </span><span class="pun">&lt;</span><span class="pln">script</span><span class="pun">&gt;</span><span class="pln"> </span>
<span class="pln"> </span><span class="kwd">function</span><span class="pln"> writestarttime</span><span class="pun">(){</span><span class="pln"> </span><span class="com">//当刷新的时候去执行</span>
<span class="pln"> </span><span class="kwd">var</span><span class="pln"> freshToHomeTime </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">().</span><span class="pln">getTime</span><span class="pun">();</span>
<span class="pln"> delCookie</span><span class="pun">(</span><span class="str">"enterHomeTime"</span><span class="pun">);</span>
<span class="pln"> setCookie</span><span class="pun">(</span><span class="str">"enterHomeTime"</span><span class="pun">,</span><span class="pln">freshToHomeTime</span><span class="pun">);</span>
<span class="pln"> </span><span class="pun">}</span><span class="pln"> </span>
<span class="pln"> </span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span>
<span class="pln"> </span><span class="pun">&lt;/</span><span class="pln">head</span><span class="pun">&gt;</span>
<span class="pln"> </span><span class="pun">&lt;</span><span class="pln">body loadWebUI</span><span class="pun">=</span><span class="str">"SplitBar"</span><span class="pln"> scroll</span><span class="pun">=</span><span class="str">"no"</span><span class="pln"> onbeforeunload </span><span class="pun">=</span><span class="pln"> </span><span class="str">"writestarttime()"</span><span class="pun">&gt;</span>
<span class="pln"> </span><span class="pun">&lt;/</span><span class="pln">body</span><span class="pun">&gt;</span>

结束时间为,基于事件的记录方式,在页面上所有的豆腐块加载完后进行记录,精确到最后一个加载才开始记录
cent.jsp中
       if(portIndex==portTotalNum){

1. <span class="pln"> portIndex </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">999</span><span class="pun">;</span>
2. <span class="pln"> </span><span class="kwd">var</span><span class="pln"> ssoTime </span><span class="pun">=</span><span class="pln"> getCookie</span><span class="pun">(</span><span class="str">"enterHomeTime"</span><span class="pun">);</span><span class="pln"> </span>
3. <span class="pln"> </span><span class="kwd">var</span><span class="pln"> curTime </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">().</span><span class="pln">getTime</span><span class="pun">();</span>
4. <span class="pln"> </span><span class="kwd">var</span><span class="pln"> loadTime </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">curTime</span><span class="pun">-</span><span class="pln">ssoTime</span><span class="pun">)/</span><span class="lit">1000</span><span class="pun">;</span>
5. <span class="pln"> log_visit</span><span class="pun">(</span><span class="pln">serverip</span><span class="pun">,</span><span class="str">'系统首页'</span><span class="pun">,</span><span class="pln">loadTime</span><span class="pun">,</span><span class="str">'首次进入'</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">''</span><span class="pun">,</span><span class="str">'进入'</span><span class="pun">);</span>
6. <span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"进入首页持续时间"</span><span class="pun">+</span><span class="pln">loadTime</span><span class="pun">);</span>
7. <span class="pun"><font face="Consolas">&nbsp;&nbsp;&nbsp;&nbsp;</font><font face="Consolas">&nbsp;&nbsp;&nbsp;&nbsp;</font>}</span>


 7.与真实时间的差异性对比































































































所处环 境    



日志记录时间



实际时间



脚本下载时间



网页渲染时间



误差



准确性



 

 

动态页面



13.016s



11.54s



11.54s



3.99s



+1.476



88%



10.879s



11.87s



11.87s



3.77s



-0.991



92%



12.835s



13.04s



13.04s



4.27s



-0.161



98%



12.516s



11.67



11.67s



3.65s



+0.846



93%



12.888s



12.36



12.36s



3.97s



+1.528



95%



 

 

静态页面



4.757s



4.64s



4.64s



3.39s



+0.117



97%



7.358s



7.54s



7.54s



3.64s



-0.182



97%



4.164s



3.65s



3.65s



2.83s



+0.154



87%



4.768s



4.32s



4.32s



3.71s



+0.448



90%



2.464s



3.03s



3.03s



2.99s



-0.566



81%



 

备注:

a测试环境为北京PC机访问福州的数据库和缓存。浏览器为IE9



b.在页面加载的过程中,实际是一边下载一边渲染,渲染时间远小于下载时间,所以取下载时间作为实际时间

c.特殊说明:由于存在工作台的自刷新的情况,若记录的时间有超过5分钟的情况,请自行舍弃

结论:按照此思路设计的日志时间准确性平均在90%以上,符合设计要求

  




























your support will encourage me to continue to create!
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)