成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

教你如何打造出一個(gè)前端可視化監(jiān)控系統(tǒng)

Java_oldboy / 1801人閱讀

摘要:擼起袖子,教你干一個(gè)前端監(jiān)控系統(tǒng)還記得在我上一家公司中,某一大佬做了一個(gè)監(jiān)控系統(tǒng),牛逼哄哄,挺想研究他到底是怎么搞出來(lái)的。開(kāi)始基于以上我們就開(kāi)始搭建一個(gè)前端監(jiān)簡(jiǎn)易控平臺(tái)。收集信息要做監(jiān)控系統(tǒng),首先我們得有一個(gè)對(duì)象。

擼起袖子,教你干一個(gè)前端監(jiān)控系統(tǒng)

還記得在我上一家公司中,某一大佬做了一個(gè)監(jiān)控系統(tǒng),牛逼哄哄,挺想研究他到底是怎么搞出來(lái)的。當(dāng)然我們也不是拍拍腦袋干活的人,總不能人家咋干我們就咋干。下面先就介紹下,這樣的平臺(tái)到底有啥好處。

背景

首先我們?yōu)槭裁匆銮岸讼到y(tǒng)呢,先看下面這張表,可以很顯然的看出,前端的性能對(duì)于產(chǎn)品的價(jià)值提升還是蠻有幫助的,但是這些信息如果我們能實(shí)時(shí)的采集到,并且實(shí)施以監(jiān)控,讓整個(gè)產(chǎn)品在產(chǎn)品線上一直保持高效的運(yùn)作,這才是我們的目的。

性能 收益
Google 延遲 400ms 搜索量下降 0.59%
Bing 延遲 2s 收入下降 4.3%
Yahoo 延遲 400ms 流量下降 5-9%
Mozilla 頁(yè)面打開(kāi)減少 2.2s 下載量提升 15.4%
Netflix 開(kāi)啟 Gzip 性能提升 13.25% 帶寬減少50%

其次,也有利于我們發(fā)布的產(chǎn)品,能夠及時(shí)發(fā)現(xiàn)我們的錯(cuò)誤。如果一個(gè)產(chǎn)品在新的迭代中,發(fā)生不可描述的錯(cuò)誤。

對(duì)!就是不可描述。我們總不可能等待用戶的反饋投訴,到那個(gè)時(shí)候黃花菜都涼了。

開(kāi)始

基于以上我們就開(kāi)始搭建一個(gè)前端監(jiān)簡(jiǎn)易控平臺(tái)。(雖然現(xiàn)在市面上有很多這樣的系統(tǒng)比如ELK,但是還是忍不住自己擼一個(gè))

只能是簡(jiǎn)易了。

兄弟們?cè)徫?,只能幫你們到這里了。

接下來(lái)請(qǐng)看。

以上是我們需要做的一些事情。

收集信息

要做監(jiān)控系統(tǒng),首先我們得有一個(gè)對(duì)象。我們監(jiān)控的對(duì)象!對(duì)象!對(duì)象!對(duì)象。

我在我的系統(tǒng)寫了一個(gè)這樣的頁(yè)面,


    
2
2
2
2
2
2

沒(méi)錯(cuò)這就是我們要監(jiān)控的頁(yè)面。這個(gè).....真不是我懶。

然后接下來(lái)我一共設(shè)計(jì)了3塊數(shù)據(jù)

頁(yè)面加載時(shí)間

統(tǒng)計(jì)用戶使用設(shè)備

錯(cuò)誤量的統(tǒng)計(jì)

頁(yè)面加載時(shí)間

window.logInfo = {};  //統(tǒng)計(jì)頁(yè)面加載時(shí)間
window.logInfo.openTime = performance.timing.navigationStart;
window.logInfo.whiteScreenTime = +new Date() - window.logInfo.openTime;
document.addEventListener("DOMContentLoaded",function (event) {
  window.logInfo.readyTime = +new Date() - window.logInfo.openTime;
});
window.onload = function () {
  window.logInfo.allloadTime = +new Date() - window.logInfo.openTime;
  window.logInfo.nowTime = new Date().getTime();
  var timname = {
    whiteScreenTime: "白屏?xí)r間",
    readyTime: "用戶可操作時(shí)間",
    allloadTime: "總下載時(shí)間",
    mobile: "使用設(shè)備",
    nowTime: "時(shí)間",
  };
  var logStr = "";
  for (var i in timname) {
    console.warn(timname[i] + ":" + window.logInfo[i] + "ms");
    if (i === "mobile") {
      logStr += "&" + i + "=" + window.logInfo[i];
    } else {
      logStr += "&" + i + "=" + window.logInfo[i];
    }

  }
  (new Image()).src = "/action?" + logStr;
};

統(tǒng)計(jì)用戶使用設(shè)備

window.logInfo.mobile = mobileType();
function mobileType() {
  var u = navigator.userAgent, app = navigator.appVersion;
  var type =  {// 移動(dòng)終端瀏覽器版本信息
    ios: !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/), //ios終端
    iPad: u.indexOf("iPad") > -1, //是否iPad
    android: u.indexOf("Android") > -1 || u.indexOf("Linux") > -1, //android終端或者uc瀏覽器
    iPhone: u.indexOf("iPhone") > -1 || u.indexOf("Mac") > -1, //是否為iPhone或者QQHD瀏覽器
    trident: u.indexOf("Trident") > -1, //IE內(nèi)核
    presto: u.indexOf("Presto") > -1, //opera內(nèi)核
    webKit: u.indexOf("AppleWebKit") > -1, //蘋果、谷歌內(nèi)核
    gecko: u.indexOf("Gecko") > -1 && u.indexOf("KHTML") == -1, //火狐內(nèi)核
    mobile: !!u.match(/AppleWebKit.*Mobile/i) || !!u.match(/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/), //是否為移動(dòng)終端
    webApp: u.indexOf("Safari") == -1 //是否web應(yīng)該程序,沒(méi)有頭部與底部
  };
  var lists = Object.keys(type);
  for(var i = 0; i < lists.length; i++) {
    if(type[lists[i]]) {
      return lists[i];
    }
  }  
}

錯(cuò)誤量的統(tǒng)計(jì)

window.onload = function () {
        window.logInfo.allloadTime = +new Date() - window.logInfo.openTime;
        window.logInfo.nowTime = new Date().getTime();
        var timname = {
            whiteScreenTime: "白屏?xí)r間",
            readyTime: "用戶可操作時(shí)間",
            allloadTime: "總下載時(shí)間",
            mobile: "使用設(shè)備",
            nowTime: "時(shí)間",
        };
        var logStr = "";
        for (var i in timname) {
            console.warn(timname[i] + ":" + window.logInfo[i] + "ms");
            if (i === "mobile") {
                logStr += "&" + i + "=" + window.logInfo[i];
            } else {
                logStr += "&" + i + "=" + window.logInfo[i];
            }
            
        }
        (new Image()).src = "/action?" + logStr;
    };
      
    var defaults = {
        msg:"",  // 錯(cuò)誤的具體信息
        url:"",  // 錯(cuò)誤所在的url
        line:"", // 錯(cuò)誤所在的行
        col:"",  // 錯(cuò)誤所在的列
        nowTime: "",// 時(shí)間
    };
    window.onerror = function(msg,url,line,col,error) {
        col = col || (window.event && window.event.errorCharacter) || 0;

        defaults.url = url;
        defaults.line = line;
        defaults.col =  col;
        defaults.nowTime = new Date().getTime();

        if (error && error.stack){
            // 如果瀏覽器有堆棧信息,直接使用
            defaults.msg = error.stack.toString();

        }else if (arguments.callee){
            // 嘗試通過(guò)callee拿堆棧信息
            var ext = [];
            var fn = arguments.callee.caller;
            var floor = 3;  
            while (fn && (--floor>0)) {
                ext.push(fn.toString());
                if (fn  === fn.caller) {
                    break;
                }
                fn = fn.caller;
            }
            ext = ext.join(",");
            defaults.msg = error.stack.toString();
        }
        var str = ""
        for(var i in defaults) {
            // console.log(i,defaults[i]);
            if(defaults[i] === null || defaults[i] === undefined) {
                defaults[i] = "null"; 
            }
            str += "&"+ i + "=" + defaults[i].toString();
        }
        srt = str.replace("&", "").replace("
","").replace(/s/g, "");
        (new Image()).src = "/error?" + srt;
    }

以上就是收集數(shù)據(jù)的全部,通過(guò)發(fā)送/action請(qǐng)求或者是/error請(qǐng)求,這些都是可以自定義的,我講的只是整個(gè)過(guò)程是如何實(shí)現(xiàn)的。

然后通過(guò)我的的一個(gè)后臺(tái)express.js把所有的請(qǐng)求處理并都記錄下來(lái),記錄好后的數(shù)據(jù)是這樣子的。

user_ip=127.0.0.1&whiteScreenTime=185&readyTime=192&allloadTime=208&mobile=webKit&nowTime=1513071388941
數(shù)據(jù)處理

這里我是通過(guò)自己寫的一段腳本進(jìn)行解析,parse.js,這里不具體講解,看源碼即可。我展現(xiàn)下解析好的數(shù)據(jù)。

我以cvs的數(shù)據(jù)格式儲(chǔ)存,因?yàn)楹竺鎴D表的需要,我也支持json格式方式導(dǎo)出,只不過(guò)后面就需要你自己來(lái)配置可視化的界面了。

數(shù)據(jù)是這樣的。

charts/csvData/2017-12-16time.csv

時(shí)間,白屏?xí)r間,用戶可操作時(shí)間,總下載時(shí)間
1513427051482,137,137,153
1513427065080,470,471,507
1513427080040,127,127,143
1513428714345,274,275,323
1513428733583,267,268,317
1513428743167,268,268,317
1513428754796,276,276,328
數(shù)據(jù)展示

這里我用的是highcharts.js

具體的配置我不進(jìn)行講解,可以自己到官網(wǎng)進(jìn)行查看。

下面是可視化的圖表,顯示的是每天各個(gè)時(shí)間段的信息。

界面可能不是特別美觀,還請(qǐng)見(jiàn)諒。

環(huán)境

node >= 6.0.0

redis >= 2.6.0

在這里我說(shuō)明下,因?yàn)槿绻@個(gè)部署在線上環(huán)境的時(shí)候,如果每次記錄都進(jìn)行記錄的話,會(huì)消耗大量的內(nèi)存,所以我架設(shè)了一層redis,為了防止大流量的沖擊,然后可以每隔一段時(shí)間進(jìn)行存儲(chǔ)。

const express = require("express");
const performance = require("./lib/performance.js");
const app = express();
const router = express.Router();
router.get("/", function (req, res, next) {
  req.url = "./index.html";
  next();
});
app.use(router);
app.use(performance({
    time: 10, // 秒為單位
    originalDir: "./originalData", // 數(shù)據(jù)的目錄
    errorDir: "./errorData" // 報(bào)錯(cuò)的目錄
}))
app.use(express.static("./"));
const server = app.listen(3000)

這里可以設(shè)置默認(rèn)的時(shí)間,我這里以10秒為單位,為了demo的效果起見(jiàn)。一般我采用的是一分鐘進(jìn)行一次存儲(chǔ)。

github地址:https://github.com/hua1995116/mcharts

如有好的建議以及優(yōu)化的方案,還請(qǐng)各位在Issues上提給我,喜歡的話可以點(diǎn)個(gè)star。

進(jìn)階(一個(gè)利用監(jiān)控平臺(tái)的實(shí)戰(zhàn)栗子)

我利用這個(gè)平臺(tái)對(duì)我的一個(gè)項(xiàng)目進(jìn)行了監(jiān)控。如果你只是純粹玩的話,還請(qǐng)只閱讀上面的原系統(tǒng)地址,可以忽視我這一段,畢竟我這個(gè)系統(tǒng)還不夠完善。

項(xiàng)目線上地址:http://www.qiufengh.com/#/

項(xiàng)目監(jiān)控地址:http://qiufengh.com:8080/

此項(xiàng)目代碼地址:https://github.com/hua1995116/webchat/tree/monitoring

在這里我設(shè)置了每過(guò)1分鐘記錄一次日志。

// 監(jiān)控引入
app.use(performance({
    time: 60, // 秒為單位
    originalDir: "./originalData", // 數(shù)據(jù)的目錄
    errorDir: "./errorData" // 報(bào)錯(cuò)的目錄
}))

以及每隔10分鐘進(jìn)行一次解析。

function setPrase() {
    setInterval(function(){
        parseData();
      }, 1000 * 60 * 10);
}

原文鏈接: http://yifenghua.win/html/2017-12-16.html (更完美的閱讀體驗(yàn)哦)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92215.html

相關(guān)文章

  • 前端之從零開(kāi)始系列

    摘要:只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙只有動(dòng)手,你才能真正掌握一門技術(shù)持續(xù)更新中項(xiàng)目地址求求求源碼系列跟一起學(xué)如何寫函數(shù)庫(kù)中高級(jí)前端面試手寫代碼無(wú)敵秘籍如何用不到行代碼寫一款屬于自己的類庫(kù)原理講解實(shí)現(xiàn)一個(gè)對(duì)象遵循規(guī)范實(shí)戰(zhàn)手摸手,帶你用擼 Do it yourself!!! 只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙 只有動(dòng)手,你才能真正掌握一門技術(shù) 持續(xù)更新中…… 項(xiàng)目地址 https...

    Youngdze 評(píng)論0 收藏0
  • 個(gè)人分享--web前端學(xué)習(xí)資源分享

    摘要:前言月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議那么今天我就把看過(guò)的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多9月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議!那么今天我就...

    sherlock221 評(píng)論0 收藏0
  • SVG

    摘要:目前只提供了一些基礎(chǔ)功能。中與的區(qū)別開(kāi)發(fā)者第一次接觸手寫那種,雖然很多情況都有設(shè)計(jì)師使用來(lái)完成這項(xiàng)工作,但還是不排除需要利用到的每個(gè)元素。輕量級(jí),具備靈活的來(lái)自團(tuán)隊(duì),全球非常出名的可視化團(tuán)隊(duì)。于是筆者嘗試著把移植到中。 使用SVG + CSS實(shí)現(xiàn)動(dòng)態(tài)霓虹燈文字效果 早上無(wú)意間進(jìn)入一個(gè)網(wǎng)站,看到他們的LOGO效果略屌,如圖: 剛開(kāi)始以為是gif動(dòng)畫之類的,審查元素發(fā)現(xiàn)居然是用SVG + ...

    104828720 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.35 - WebGL:打開(kāi)網(wǎng)頁(yè)看大片

    摘要:在文末,我會(huì)附上一個(gè)可加載的模型方便學(xué)習(xí)中文藝術(shù)字渲染用原生可以很容易地繪制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以說(shuō)是 HTML5 技術(shù)生態(tài)鏈中最為令人振奮的標(biāo)準(zhǔn)之一,它把 Web 帶入了 3D 的時(shí)代。 初識(shí) WebGL 先通過(guò)幾個(gè)使用 Web...

    objc94 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<