1. 程式人生 > >Node.js躬行記(4)——自建前端監控系統

Node.js躬行記(4)——自建前端監控系統

  這套前端監控系統用到的技術棧是:React+MongoDB+Node.js+Koa2。將效能和錯誤量化。因為自己平時喜歡吃菠蘿,所以就取名叫菠蘿系統。其實在很早以前就有這個想法,當時已經實現了前端的引數蒐集,只是後臺遲遲沒有動手,也就拖著。

  • 目前完成的還只是個雛形,僅僅是蒐集了錯誤和相關的效能引數。

  • 後臺樣式採用了封裝過的matrix。

  • 分析功能還很薄弱,只是做了簡單的演示,並且各種基礎功能還有待完善。

  • 後面打算強化資料分析,並且還要實現錯誤的回放機制,思路的話以前也調研過,參考之前的一篇文章。

  現在的這個系統還只能算是個玩具,後期還需要雕琢雕琢。下面是這套系統的目錄結構。

├── pingapple --------------------------------- 菠蘿監控系統
│   ├── client -------------------------------- 系統的前端部分
│   ├── sdk ----------------------------------- 資訊蒐集程式碼庫
│   ├── server -------------------------------- 系統的後端部分

一、SDK

1)primus.js

  在之前的《前端頁面效能引數蒐集》一文中,詳細記載了各類效能指標的計算規則,並整理到了primus.js中。

  本次將在primus.js的基礎上做適當的修改,包括刪除代理、測速、資源資訊等功能,改變部分效能指標的計算規則,例如從瀏覽器發起HTTP請求算起,忽略瀏覽器重定向的時間等。

2)錯誤處理

  完善錯誤處理,將錯誤分成三類:runtime、load和Promise。在window的error事件中,處理前兩種錯誤。像img元素載入的圖片地址不存在,就會執行formatLoadError()函式;像變數未定義,就會執行formatRuntimerError()函式。

window.addEventListener("error", function (event) {
    var errorTarget = event.target;
    // 過濾 target 為 window 的異常
    if (
      errorTarget !== window &&
      errorTarget.nodeName &&
      LOAD_ERROR_TYPE[errorTarget.nodeName.toUpperCase()]
    ) {
      handleError(formatLoadError(errorTarget));
    } else {
      handleError(
        formatRuntimerError(
          event.message,
          event.filename,
          event.lineno,
          event.colno,
          event.error
        )
      );
    }
  }, true
);

  將window繫結unhandledrejection事件後,就會在Promise被拒絕且沒有reject的回撥函式時觸發。

window.addEventListener(
  "unhandledrejection",
  function (event) {
    // console.log('Unhandled Rejection at:', event.promise, 'reason:', event.reason);
    handleError({
      type: ERROR_PROMISE,
      desc: event.reason,
      stack: "no stack"
    });
  },
  true
);

3)初始化

  由於要計算白屏時間,DOM時間等,所以位置不能隨便放,得要放在head的最後面。

<head>
  <script>
    window.pineapple || (pineapple = {});
    pineapple.param = {
      "token": "dsadasd2323dsad23dsada"
    };
  </script>
  <script src="js/pineapple.js"></script>
</head>

二、服務端

1)Koa

  Koa是由Express原班人馬打造的Web輕量框架,通過組合各種中介軟體來避免繁瑣的回撥函式巢狀,當前使用的版本是V2。

npm install --save koa

  使用的Koa腳手架:koa-generator,建立專案的結構,並且在此基礎上做了調整(目錄如下所示)。暫時還不會用到靜態資源和檢視層。

npm install -g koa-generator
├── server --------------------------------- 服務端
│   ├── bin -------------------------------- 命令
│   ├── config ----------------------------- 配置目錄
│   ├── controllers ------------------------ MVC中的邏輯層
│   ├── db --------------------------------- MVC中的資料層
│   ├── public ----------------------------- 靜態資源
│   ├── routes ----------------------------- 路由
│   ├── utils ------------------------------ 工具庫
│   ├── views ------------------------------ MVC中的檢視層
│   ├── app.js ----------------------------- 入口檔案

  為了區分開發環境和生產環境,通過cross-env統一不同系統設定環境變數的方式。

npm install --save cross-env

  package.json中的命令如下,添加了環境配置。

"scripts": {
  "start": "node bin/www",
  "dev": "cross-env NODE_ENV=development ./node_modules/.bin/nodemon bin/www",
  "prd": "cross-env NODE_ENV=production pm2 start bin/www"
}

  prd按字面意思應該是生產環境的命令,其中使用了pm2,預設沒有安裝。還沒部署過Node.js,還不清楚裡面有多少坑。

npm install --save pm2

2)MongoDB

  MongoDB是一個開源的非關係型資料庫(圖1是下載介面),既沒有表、行等概念,也沒有固定的模式和結構,所有的資料以文件(一個物件)的形式儲存。但其使用方式和關係型資料庫相似,並且還支援對資料建立索引,適用於高併發讀寫、海量資料儲存和實時分析等。

圖1

  注意,在安裝時預設會下載MongoDB Compress(一個視覺化的MongoDB工具),預設下載會非常慢,建議自行下載,該工具的介面還是蠻清爽的,如圖2所示。

圖2

  在Mac上配置MongoDB比較麻煩,不像Windows那樣一件安裝,需要一些步驟,廢了點力氣才裝好,下面是執行的命令。

sudo mongod --dbpath=/Users/pw/data

3)Mongoose

  Mongoose是MongoDB的一個ORM(Object-Document Mapper,物件文件對映)工具,可在Node.js環境中執行,封裝了MongoDB操作文件的常用方法,包括引入資料庫連線(connect),定義模型(model),宣告文件結構(scheme),例項化模型等操作資料庫的方法。

npm install --save mongoose

  借鑑了以前PHP資料分層的思想,單獨分離出資料庫的連線,並抽象通用的Model層(如下所示)。

const mongoose = require("./db");
class Mongodb {
  constructor(name, schema) {
    //宣告結構
    const mySchema = new mongoose.Schema(schema, { typeKey: "$type" });
    this.model = mongoose.model(name, mySchema);
  }
  //儲存
  save(obj) {
    obj.created = Date.now();         //日期
    const doc = new this.model(obj);
    return new Promise((resolve, reject) => {
      doc.save((err, row) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(row);
      });
    });
  }
}
module.exports = {
  model: Mongodb,
  mongoose
};

4)路由

  由於傳送的地址是一張gif圖片,因此在處理路由時,返回本地的一張gif圖,如下所示,影象地址得是絕對路徑,否則無法讀取。

router.get('/pa.gif', async (ctx, next) => {
  const ctr = new indexController();
  ctr.collect(ctx);
  const url = path.resolve(__dirname, "../public/images/blank.gif");
  ctx.body = fs.readFileSync(url);    //空白gif圖
});

5)代理分析

  在接收引數的時候分析代理所帶的資訊,例如瀏覽器、作業系統、裝置等。使用的是一個第三方庫:UAParser.js,四年前就關注過,當時GitHub上只有1K多個關注量,現在已經翻了4倍。

npm install --save ua-parser-js

6)假資料

  製作一套合適的假資料,新增命令“npm run data”,初始化資料,便於展示。

三、後臺

1)UI

  後臺模板採用了之前封裝過的Matrix,但不會依賴Bootstrap框架。

  將整個頁面分成五塊,分別是導航、側邊欄、麵包屑、底部欄以及主體。

  安裝react-router的history,用於路由。

npm install --save history

  期間也會安裝各類依賴包,例如不支援在類中直接宣告屬性等。

  在使用的過程中,ESLint會不時的彈出各種錯誤和警告,期間就不停的修改問題或查詢相關配置忽略部分限制。

  後臺的側邊欄和麵包屑等部分,會隨著URL的不同而發生狀態變化,本來想用多頁實現,但配置要改很多,就依然做成一個SPA,只是稍微做了些改動。

  元件庫採用了流行的Ant Design,呼叫了按鈕、單選框、日期等元件。

npm install --save antd

  圖表庫使用的是ECharts,目前只用到了折線圖和餅圖。在引用圖表時,為了優化構建,採取了按需引用的手段。

npm install --save echarts

2)專案管理

  首先建立一個專案,然後才能分析該專案的效能和錯誤,如圖3所示。

圖3

  用彈框的形式來建立專案,使用了Ant Design的Model、Form等元件,如圖4所示。

圖4

3)效能分析

  在第一個折線圖標籤中的過濾條件包括專案、欄位、日期等,效能指標按平均值呈現,可看到每個效能指標的趨勢,如圖5所示。

圖5

  按分時日統計效能平均數,在MongoDB中計算。原先建立日期是以時間戳的形式儲存的,為了便於使用Aggregate,改成字串形式。碰到一個坑,MongoDB中的Date型別採用的是格林尼治時間,而不是當前時區的時間,也就是說存在資料庫中的時間會比當前時間早8小時。

  在第二個列表標籤中,可以詳細看到每條記錄的資訊,包括代理、網路等,便於在瞭解趨勢的前提下,獲悉更為細節的內容,如圖6所示。

圖6

  點選ajax那一列,可彈出具體的非同步請求資訊,如圖7所示。

圖7

4)錯誤分析

  有三個標籤,第一個也是折線圖,描繪的是某個時間的錯誤個數;第二個是錯誤列表,會給出具體的錯誤資訊,如圖8所示。

圖8

  第三個是餅圖,餅圖主要體現的是發生錯誤的瀏覽器分佈情況(如圖9所示),點選某一塊可檢視瀏覽器的具體版本(如圖10所示)。

圖9

圖10

 

 

【參考資料】
PerformanceTiming

unhandledrejection 處理沒有顯式捕獲的 Promise 異常

狼書(卷2)

Node-區分環境

Koa從零搭建到Api實現—專案部署

koa如何連線MongoDB

Koa2進階學習筆記

如何計算首屏載入時間 

Mongoose Schema Error: “Cast to string failed for value” when pushing object to empty array

Support for the experimental syntax 'classProperties' isn't currently enabled

Template string failing with Cannot read property 'range' of null

Disallow JSX props spreading (react/jsx-props-no-spreading)

TypeError: Cannot read property 'range' of null from template-curly-spacing

echarts專案的優化

使用 happypack 提升 Webpack 專案構建速度

mac下的mongoDB的安裝和啟動

安裝MongoDB報錯 mkdir: /data/db: Read-only file system

$sum mongoose

&n