前端日誌打印收集 - 前端監控之數據收集篇

日誌,通常你們聽到的都是後臺的日誌概念。html

前端因爲其特殊性,console輸出的咱們認爲是控制檯調試信息前端

不少時候本地開發,咱們定位問題仍是須要debug模式進行逐行定位,可是當線上問題發生時,咱們並不具有遠程debug的能力或條件,那麼如何進行快速問題定位呢?chrome

分析問題

  1. 由js錯誤引起,這種能夠經過js堆棧還原 解決大部分問題api

  2. 因爲後臺服務異常致使的, 這種能夠經過數據分析請求 解決問題服務器

  3. 還有一些多是因爲用戶操做的緣由,並無明確的異常發生, 這時候就須要經過日誌的方式記錄關鍵節點的操做session

什麼是前端日誌

日誌至少應該具有如下幾個要素app

①. 分級別

日誌,是咱們用於輸出系統消息的一些節點, 可是因爲業務、編碼優先級的不一樣,日誌須要經過定義不一樣的基原本進行輸出post

chrome上能夠看到對級別作了幾個劃分測試

在console的api中,咱們能夠將類別劃分紅一下ui

②. 多種記錄方式

開發時: 咱們使用console輸出,便於調試

測試時:通常能夠關閉輸出

生產時:應該須要輸出到服務端,用於定位

③. 輸出級別

可第一點的級別不一樣,輸出級別用於咱們對日誌的輸出作更詳細的控制

生產時:咱們一般只須要輸出級別較高的日誌, 這時候咱們會發現上表中的級別並不夠用,這時候咱們能夠對輸出級別在進行劃分

④. 控制開關

用於控制日誌的開啓關閉

如何記錄前端日誌

1. 經過自定義代理

function wrapConsole(console, level, callback) {
    var originalConsoleLevel = console[level];
    var originalConsole = console;
 
    if (!(level in console)) {
        return;
    }
 
    console[level] = function() {
        var args = [].slice.call(arguments);
 
        var msg = '' + args.join(' ');
        var data = {level: level, extra: {arguments: args}};
 
        if (level === 'assert') {
            if (args[0] === false) {
                msg = 'Assertion failed: ' + (args.slice(1).join(' ') || 'console.assert');
                data.extra.arguments = args.slice(1);
                callback && callback(level,msg, data);
            }
        } else {
            callback && callback(level,msg, data);
        }
 
        if (originalConsoleLevel) {
        Function.prototype.apply.call(originalConsoleLevel, originalConsole, args);
        }
    };
};
複製代碼

或者使用proxy

function warpConsole(console, level, callback) {
let handler = {
  apply (target, ctx, arg) {
       var args = [].slice.call(arg);
 
        var msg = '' + args.join(' ');
        var data = {level: level, extra: {arguments: args}};
 
        if (level === 'assert') {
            if (args[0] === false) {
                msg = 'Assertion failed: ' + (args.slice(1).join(' ') || 'console.assert');
                data.extra.arguments = args.slice(1);
                callback && callback(level,msg, data);
            }
        } else {
            callback && callback(level,msg, data);
        }
       return Reflect.apply(...arguments);
  }
};
console[level] = new Proxy(console[level], handler)
}
複製代碼

2. 加入分級管理

首先定義級別

const levelMap = {trace: 5, log:5, dir:5, debug: 10, info: 15, warn: 25, error: 30, fatal: 40}
複製代碼

定義控制開關

this.consoleSettings= utils.objectMerge({
            clientOn: false,
            serverOn: false,
            level: "error"
        }, options.console || {})
複製代碼

代碼中加入控制點 在warpConsole中回調源方法處加入級別和開關判斷

let limitLevel = levelMap[reporter.consoleSettings.level] || 0
            if(reporter.consoleSettings.clientOn && levelMap[level] >= limitLevel ) {
   // 回調源方法
}
複製代碼

在發送到服務端的方法中一樣加入開關

var consoleMethodCallback = function(level, msg, data) {
           let limitLevel = levelMap[reporter.consoleSettings.level] || 0
           if(reporter.consoleSettings.serverOn && levelMap[level] >= limitLevel ) {
               if(data.extra) {
                   try {
                       data.extra = JSON.stringify(data.extra)
                   }catch(e){
                       data.extra = JSON.stringify({arguments: msg})
                   }
               }
               var session = reporter._getSessionId();
               data.m_uuid = session.sid;               // 發送到服務器
               reporter.captureInfo("console_data", data, {category: "console", filter: "track"})
           }
       };
 
       utils.each(['debug', 'info', 'warn', 'error', 'log'], function(_, level) {
           wrapMethod(console, level, consoleMethodCallback);
       });

複製代碼

3. 數據收集

console數據只是用於輔助的數據, 建議使用批量發送的方式收集(收集方式由後續文章分享~)

閱讀原文

相關文章
相關標籤/搜索