亚洲日本永久一区二区_国产精品k频道网址导航_首页aⅴ色老汉中文字幕_免费深夜全片观看_9久久9毛片又大又硬又粗_国产精品成亚洲电影_日韩不用播放器的av_欧美特色特黄视频

淺談前端異常監控平臺實現方案

淺談前端異常監控平臺實現方案

異常捕獲是改善軟件質量的跟蹤手段之一,常見的方式是記錄日志,從日志分析異常問題進而跟進。對于前端項目來說,異常可能是后端接口數據導致,可能是前端本身業務邏輯問題導致,不管是什么導致的異常,只要能夠精準的捕獲到就能夠分析出問題所在。可能有小伙說有測試階段,全面的測試機制的確能夠降低異常的出現,但是測試大部份情況是在非生產環境上進行的,覆蓋面有限。

日志是收集異常的最佳方式,一個異常監控平臺就需要包括異常采集、異常存儲、異常統計與分析、異常報告、異常告警,而對于一個通用平臺來說,就需要項目管理、版本管理、團隊管理、倉庫管理等等。本文主要介紹一下異常采集需要考慮的問題,并跟大家分享兩種現成的解決方案。

異常介紹

異常,是每種編程語言都需要考慮的一種結構,如何友好的跟蹤異常而不影響生產環境上的業務,這就需要從項目開發到上線整個過程做一定的規范。下面就來談談前端的異常及處理方式。

異常分類

先來說說JavaScript的錯誤類型,ECMA-262 定義了 7 種錯誤類型,說明如下:

Error:普通異常,通常與 throw 語句和try/catch 語句一起使用,利用屬性 name 可以聲明或了解異常的類型,利用message 屬性可以設置和讀取異常的詳細信息。

EvalError:Eval 函數執行異常。

SyntaxError:語法解析不合理,即語法錯誤。

RangeError:在數字超出合法范圍時拋出,比如數組下標越界就會報這種錯誤。

ReferenceError:在讀取不存在的變量時拋出,比如沒定義變量 a,后面卻使用這個變量 a,就會報這種錯。

TypeError:當一個值的類型錯誤時拋出該異常,比如傳遞給函數的參數與預期的不符,就會報這種錯誤。

URIError:以一種錯誤的方式使用全局 URI 處理函數而產生的錯誤

異常處理

前端捕獲異常分為全局捕獲和單點捕獲。全局捕獲代碼集中,易于管理;單點捕獲作為補充,對某些特殊情況進行捕獲,但分散,不利于管理,容易遺漏。在項目開發過程中,定義一個錯誤捕獲模塊,將項目所有的異常(全局異常和單點異常)都交給錯誤模塊來統一處理,這就需要項目約定。

try-catch

try-catch 語句,是 JavaScript 處理異常的一種標準方式。基本語法如下:

try {
    
} catch (error) {
    // 錯誤處理
}

try 塊中的代碼發生了錯誤,就會立即退出代碼執行過程,然后執行 catch 塊。catch 塊會接收到一個包含錯誤信息的對象。一般是error.message

finally

finallytry-catch 語句中是可選的,如果 finally 子句已經使用,則其代碼無論如何都會執行。無論 trycatch 語句塊中包含什么代碼——甚至 return 語句,都不會阻止 finally 子句的執行。只要代碼中包含 finally 子句,那么無論 try 還是 catch 語句塊中的 return 語句都將被忽略。因此,在使用 finally 子句之前,一定要非常清楚想讓代碼怎么樣。看下面這個函數:

const errorHelper = () => {
    try {
        return devpoint;
    } catch (error) {
        return "error";
    } finally {
        return "不管有無錯誤,我都執行了!";
    }
};
console.log(errorHelper());  // 函數本身是發生了異常,但是最終打印的結果為:不管有無錯誤,我都執行了!

上面的函數代碼實際上是有異常的,因為變量 devpoint 并沒有定義,不過最終執行了 finally 子句輸出了 不管有無錯誤,我都執行了!

throw

try-catch 語句相配的 throw 操作符,用于隨時的主動拋出自定義錯誤。

const errorHelper = () => {
    try {
        return devpoint;
    } catch (error) {
        return "error";
    } finally {
        throw new Error("devpoint變量未定義");
    }
};
console.log(errorHelper());
window.onerror

window.onerror,是全局異常捕獲,對于單點異常捕獲不到的異常就到這里了。

異常采集

觸發異常有很多原因,為了更好的分析,除了捕獲程序的錯誤信息外,還需要采集執行程序的外部環境,對于前端項目,外部環境就包括系統(Window、IOS、Android)和系統版本、瀏覽器(Chrome、IE、火狐等)和版本、IP地址、用戶信息、運行的頁面、網絡環境、API接口數據。針對這些信息就需要設計采集的日志結構。

在采集異常日志的時候,有個原則需要注意:采集日志行為不影響用戶體驗及應用本身的性能

下面是一個參考的日志結構:

  • projectId:項目信息
  • eventId:事件ID,日志的唯一標志
  • stack:錯誤stack信息
  • requestId:開發者定義的異常標志
  • level:異常級別,可以是 error、info、warn
  • browser:瀏覽器信息
  • device:設備信息
  • os:操作系統信息
  • release:應用版本信息
  • url:異常觸發頁面url
  • user:用戶信息,可以是iP
  • createAt:異常產生時間
  • network:網絡信息
  • eventKey:觸發的鍵
  • dataRes:API響應數據
  • screenWidth:屏幕寬度
  • screenHeight:屏幕高度
  • message:異常詳細信息

異常上報

收集到異常數據如何上報呢?即需要將異常日志收集到云端存儲,供項目開發跟進分析,一種方式是直接通過API異步上報,在捕獲信息比較多的情況下,還是會占用網絡請求,影響應用本身。可以考慮將采集的異常日志存儲在本地,最佳的選擇是IndexedDB,容量大,支持異步操作,可以自定義查詢。

IndexedDB 是WEB離線存儲的一種方式,因此存儲只是暫時的,還需要設計一個同步機制,將本地存儲的日志同步到云端服務器上。為了更好的同步,就需要設計暫存區、歸檔區,新產生的日志存儲在暫存區,已成功同步的日志存儲在歸檔區。有了本地存儲,同步的過程批量同步。

后端存儲,可以考慮使用leveldb,在性能方面,基本可以碾壓了mongodbsqlite

LevelDB是google公司開發出來的一款超高性能kv存儲引擎,以其驚人的讀性能和更加驚人的寫性能在輕量級nosql數據庫中鶴立雞群,此開源項目目前是支持處理十億級別規模Key-Value型數據持久性存儲的C++ 程序庫。在優秀的表現下對于內存的占用也非常小,大量數據都直接存儲在磁盤上,可以理解為以空間換取時間。

第三方平臺

上面簡單介紹實現異常監控平臺的幾個關鍵點,現在就跟大家分享兩個可以用于前端異常跟蹤的工具Google Analytics 和 Sentry 。

Google Analytics

沒錯,Google Analytics一般想到的是用于網站流量統計分析。可以借助Google Analytics的事件統計來跟蹤異常,下面是簡單的方法:

function postEvents(error) {
    var category = error.level || "warn",
        action = error.action || "",
        label = error.message || "";
    ga("send", "event", category, action, label);
}

缺點就是無法方便的確定觸發異常的環境條件,后續也無法跟蹤版本等等。

Sentry

sentry 是一個實時事件日志記錄和聚合平臺。它專門用于監視錯誤和提取執行適當的事后操作所需的所有信息, 而無需使用標準用戶反饋循環的任何麻煩。

這是一個比較專業的異常監控工具,基本支持所有主流編程語言,這里只是簡單介紹一個前端的使用。

首先在頁面上加入以下腳本:

<script src="https://cdn.ravenjs.com/3.20.1/raven.min.js" crossorigin="anonymous"></script>
<script type="text/javascript">
  try {
    if ((typeof Raven) != "undefined"){
      Raven.config('https://ffd39f4582184540a7214fb82bb3e888@sentry.io/248888',{
        release: 'release_0.0.5',
        allowSecretKey: true
      }).install()
    }
  } catch (error) {
    
  }
</script>

然后項目中可以寫一個統一的入口:

function ExceptionJs() {
    const ravenJs = typeof Raven != "undefined" ? Raven : {};
    this.capture = function (error) {
        try {
            if (!(error instanceof Error)) {
                if (typeof error === "object") {
                    error = JSON.stringify(error);
                }
            }
            if (typeof ravenJs.captureException === "function") {
                ravenJs.captureException(error);
            }
        } catch (e) {
            // 這里是確保異常跟蹤腳本出錯了不至于影響應用程序
        }
    };
}

在需要的位置加入以下代碼:

const exceptionHelper = new ExceptionJs(),
try {
} catch (error) {
    exceptionHelper.capture(error);
}

現在來看看收集上來的異常信息:

下面這個是異常的統計

異常統計

異常列表

異常列表

異常詳情

異常詳情

sentry 工具還提供了異常跟蹤處理的功能,有興趣的小伙伴可以去嘗試體驗一下。