log + ajax,前端日誌解決方案。
lajax 試著解決這些問題:
前端無日誌,或有日誌也無持久化,導致難以追溯線上問題分析;
就算使用了前端日誌庫,通常也依賴開發人員手動記日誌,不可靠;
生產環境中未捕獲的異常往往都被忽略了;
手機端瀏覽器看不到console
列印的日誌,在過去通常使用alert
或vConsole 定位問題,但缺陷是需要專門為此修改源碼;
對於伺服器動態產生的網頁,系統原有的服務端日誌無法和前端日誌進行關聯。
功能特性
線上範例
快速開始
Api
日誌格式
請求id
伺服器範例
測試
授權
手動記錄日誌,支援info
, warn
, error
3 種日誌等級;
日誌會以最佳化後的格式列印在瀏覽器控制台;
自動記錄未捕獲的腳本錯誤;
自動記錄未捕獲的Promise 異常;
自動記錄ajax 請求的開始和完成;
自動產生請求id,方便日誌定位和關聯;
日誌會定時批次傳送到配置的日誌伺服器;
良好的兼容與異常處理機制。
http://eshengsky.github.io/lajax/
> npm install lajax
script
標籤引入 < script src =" ./dist/build.min.js " > </ script >
import Lajax from './src/lajax-module' ;
// 传入接口服务器地址进行实例化
const logger = new Lajax ( 'https://path/to/your/log/server' ) ;
// 记录一条信息日志
const num = parseInt ( Math . random ( ) * 100 ) ;
logger . info ( '这是一条info日志' , '会产生一个随机数:' , num ) ;
// 记录一条警告日志
logger . warn ( '这是一条警告日志!' ) ;
try {
JSON . parse ( undefined ) ;
} catch ( err ) {
// 记录一条错误日志
logger . error ( '这是一条error日志' , '捕获到一个错误:' , err ) ;
}
詳細文件請查看Api。
lajax 使用了ES2015 語法,需要使用webpack + babel 進行打包。
> npm install
> webpack
打包後的檔案目錄是./dist
,其中build.js
是未壓縮版本, build.min.js
是壓縮版本。
初始化插件,傳回一個插件的實例。
Options
: 字串或物件。如果傳入的是字串,會被當作日誌伺服器位址:
const logger = new Lajax ( 'https://path/to/your/log/server' ) ;
如果你想自訂一些配置,請傳入一個物件:
const logger = new Lajax ( {
url : 'https://path/to/your/log/server' ,
interval : 5000
} ) ;
物件支援的全部屬性如下:
屬性名 | 說明 | 值類型 | 預設值 |
---|---|---|---|
url | 日誌伺服器的URL | string | null |
autoLogError | 是否自動記錄未捕獲錯誤 | boolean | true |
autoLogRejection | 是否自動記錄Promise 錯誤 | boolean | true |
autoLogAjax | 是否自動記錄ajax 請求 | boolean | true |
logAjaxFilter | ajax 自動記錄條件過濾函數,函數傳參是該次請求的url 和method,若傳回true 代表記錄日誌,false 代表不記錄日誌 | function | /**
* @param {string} ajaxUrl - 请求url
* @param {string} ajaxMethod - 请求方式
*/
function ( ajaxUrl , ajaxMethod ) {
return true ;
} |
stylize | 是否要格式化console 列印的內容 | boolean | true |
showDesc | 是否顯示描述資訊(初始化完成時列印在控制台) | boolean | true |
customDesc | 產生自訂描述訊息的函數,傳參為上次頁面卸載前未發送的日誌數、目前請求id、請求id 是否來自服務端,傳回字串 | function | /**
* @param {number} lastUnsend - 上次页面卸载前未发送的日志数
* @param {string} reqId - 请求id
* @param {boolean} idFromServer - 请求id是否来自服务器
*/
function ( lastUnsend , reqId , idFromServer ) {
return ` lajax 前端日志模块加载完成。
自动记录页面错误: ${ this . autoLogError ? '✔' : '✘' }
自动记录Promise异常: ${ this . autoLogRejection ? '✔' : '✘' }
自动记录Ajax请求: ${ this . autoLogAjax ? '✔' : '✘' }
当前页面请求id: ${ reqId } ${ idFromServer
? ' (来自服务端)'
: ' (自动生成)' } ` ;
} |
interval | 日誌傳送到服務端的間隔時間(毫秒) | number | 10000 |
maxErrorReq | 發送日誌請求連續出錯的最大次數,超過此次數則不再發送請求(但仍會記錄請求到佇列中) | number | 5 |
實例方法,記錄訊息日誌,可以傳入任意型別、任意數量的參數。
const num = parseInt ( Math . random ( ) * 100 ) ;
logger . info ( '这是一条info日志' , '会产生一个随机数:' , num ) ;
實例方法,同info
。
const num = parseInt ( Math . random ( ) * 100 ) ;
logger . log ( '这是一条log日志' , '会产生一个随机数:' , num ) ;
實例方法,記錄警告日誌,可以傳入任意類型、任意數量的參數。
logger . warn ( '这是一条警告日志!' ) ;
實例方法,記錄一條錯誤日誌,可以傳入任意型別、任意數量的參數。
try {
JSON . parse ( undefined ) ;
} catch ( err ) {
// 记录一条错误日志
logger . error ( '这是一条error日志' , '捕获到一个错误:' , err ) ;
}
array 類型屬性,目前待傳送的日誌佇列。
logger . queue
string 類型屬性,目前頁面的請求id。
logger . reqId
boolean 類型屬性,請求id 是否來自於服務端產生。
logger . idFromServer
靜態對象,日誌顏色的枚舉,如果你想自訂日誌顏色,可以在呼叫實例方法之前修改該對象的屬性。預設物件:
Lajax . colorEnum = {
/**
* 信息日志颜色,默认宝蓝色
*/
info : 'DodgerBlue' ,
/**
* 警告日志颜色,默认橘黄色
*/
warn : 'orange' ,
/**
* 错误日志颜色,默认红色
*/
error : 'red' ,
/**
* ajax分组颜色,默认紫色
*/
ajaxGroup : '#800080' ,
/**
* 日志发送成功颜色,默认绿色
*/
sendSuccess : 'green' ,
/**
* 描述文字颜色,默认粉红色
*/
desc : '#d30775' ,
}
透過ajax 發送給伺服器的日誌,一定是一個非空數組。這裡同時記錄2 個日誌:
logger . info ( '这是一条info日志' , 'Hello' , 'lajax' ) ;
logger . warn ( '这是一条warn日志' ) ;
實際發送的日誌資料將如下:
[{
"time" : " 2017-08-23 16:35:01.989 " ,
"level" : " info " ,
"messages" : [ " {44b53aba-1970-4bd1-b741-ed1ae5a5051e} " , "这是一条info日志" , " Hello " , " lajax " ],
"url" : " http://127.0.0.1:5500/demo/index.html " ,
"agent" : " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36 "
}, {
"time" : " 2017-08-23 16:35:02.369 " ,
"level" : " warn " ,
"messages" : [ " {44b53aba-1970-4bd1-b741-ed1ae5a5051e} " , "这是一条warn日志" ],
"url" : " http://127.0.0.1:5500/demo/index.html " ,
"agent" : " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36 "
}]
各字段說明:
time
: 字串,該筆日誌記錄的時間
level
: 字串,該條日誌的級別,分為info
、 warn
、 error
3 種
messages
: 數組,數組的第一個元素是大括號包裹的唯一請求id,之後的所有元素對應調用logger[level]
依次傳入的日誌內容
url
: 字串,該條日誌所在頁面的URL
agent
: 字串,該條日誌所在頁面的使用者代理
發送到伺服器的每一條日誌,都包含一個請求id。在同一次請求中,所有日誌的請求id 一定相同;在不同請求中,各自記錄的日誌的請求id 一定不同。
例如:用戶甲存取index.html 過程中lajax 記錄並發送了10 個日誌,這10 個日誌的請求id 是相同的;用戶乙也訪問了該頁面,同樣產生了10 個日誌,這些日誌的請求id也一定是相同的,但和用戶甲的請求id 不同。
請求id 的主要目的:讓你能夠在服務端精確定位到某次請求過程中的所有相關日誌。
請求id 的產生和發送:
如果你的頁面是伺服器端動態產生的,你想將服務端的日誌和前端的日誌串連起來,你可以在服務端產生一個請求id,並傳送到前端。 lajax 會依序嘗試從頁面的<meta name="_reqId" content="xxxx-xxx">
內容或window._reqId
尋找請求id;
如果上述的尋找失敗了,則認為你的頁面是一個純前端的頁面,lajax 將會在初始化時產生一個基於時間的唯一id 來作為請求id,在頁面卸載之前,所有的日誌都將包含該請求id;
對於監聽到的ajax 請求,上述請求id 會被加入到X-Request-Id
請求頭中,你可以在服務端日誌中記錄該請求id 以做關聯。
在./demo
目錄中,包含了一個基於node.js 的簡單的日誌伺服器範例server.js。
啟動日誌伺服器:
> node server.js
日誌介面執行在http://127.0.0.1:2017/log,本地測試時,將Lajax 的初始化參數設為該位址即可:
const logger = new Lajax ( 'http://127.0.0.1:2017/log' ) ;
此範例伺服器支援ajax 跨網域請求:)
本機存取./test/index.html
頁面以執行測試。
The MIT License (MIT)
Copyright (c) 2017 孫正華
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to , copyge , publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIEVTNESS FOR A PPYLAR PURURC 2ONIN FRING LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER