背景
客戶使用我們的oss js sdk開發應用産品時,一旦産品面向廣大使用者,由于産品運作在不同的終端,使用者的操作千差萬異,使用者一旦在前端遇到問題時,回報給客戶,客戶由于沒有相關日志資訊隻能靠猜測,而且很難模拟使用者當時的操作環境,問題也很難定位,站在客戶角度很希望有一套東西能夠協助解決這種場景。對于SDK提供方來說,我們堅決不收集使用者資訊,這是我們的責任。但是客戶希望使用者操作發生異常的時候,能夠把相關資訊進行收集,友善問題定位和重制。事實上我們提供的調試資訊也是客戶需求的。是以我們提供方案,把調試資訊的接口報漏出來。至于如何收集這些資訊,如何上傳這些資訊,這些都是客戶需要做的東西,我們可以提供參考代碼,客戶根據自己的場景自由選擇,自己收集自己上傳,至于上傳到哪裡,哪個日志平台還是客戶自己的日志分析平台,他們自主選擇。這樣無疑會給客戶提供一定幫助。
解決方案
在js sdk原來的調試資訊裡面把調試資訊加入級别備注,比如warning 、error、success等,然後挂載到我們js sdk暴露出的對象原型上,業務方(也就是我們的客戶)在業務代碼中劫持debug函數資訊,如何劫持看下文,然再結合第三方日志收集工具比如logline把日志收集到localstoreage 、indexed db 、或者websql中,客戶可以根據logline提供的功能,可以選擇存儲日志的方式、記錄日志、讀取日志、清除日志等,關于如何上傳日志,隻需要通過擷取日志後,業務方自己寫邏輯就可以了,當然建議使用阿裡雲的STS服務,更加強大、穩定、可靠。
JS SDK改動
在js sdk把debug函數暴露到執行個體原型上,同時debug函數裡面把調試資訊加入級别備注,比如warning 、error、success等,目前已經代碼送出到6.X系列版本。
客戶改動
- ali-oss的版本必須是6.X系列版本。
- 開發者在業務代碼裡劫持debug函數,重寫,擷取裡面的debug資訊,然後可以配合第三方日志工具進行本地存儲,比如logine,具體文檔可移步: https://github.com/latel/logline
示例
下面是基于ali-oss 6.x版本,告訴使用者如何收集日志,可控制存儲什麼級别的日志,如何擷取日志為例進行示範,使用者擷取日志後可自行撰寫上傳邏輯。注意:js sdk源碼中debug函數最後一個參數是控制日志的級别的目前就三個info、waring 、error三種。
1. 開發環境中使用6.X系列版本
劫持debug資訊
同時調用logine并選擇一種方式存儲日志資訊。示例代碼如下。
/ 引入ali-oss 6.X
const OSS = require('ali-oss');
// 日志收集引入第三方日志收集工具logline
const Logline = require('logline');
// 選擇日志協定,web端主要有三種存儲方式:websql、indexeddb、localstorage
Logline.using(Logline.PROTOCOL.LOCALSTORAGE)
const sdkLog = new Logline('sdk');
// 劫持OSS.prototype.debug上的日志
const _debug = OSS.prototype.debug;
OSS.prototype.debug = (...params) => {
console.log(...params);
// 擷取params最後一個參數的數值是info還是error,如果是info就調用sdkLog.info error的話就調用 sdkLog.error
const info = params[params.length - 1];
// 解析params參數 ["request %s %s, with headers %j, !!stream: %s", "GET", "http://luozhang002.oss-cn-zhangjiakou.aliyuncs.com/?max-keys=100", {…}, false, "info"]
// 規則是 %s 或者%s, 替換 字元, %j 或者%j ,替換為對象, 或者把%j對象單獨列印出來
// 解析邏輯 (開發者也可以自己寫,這裡先提供簡單的解析代碼,可供參考)
// 最終要存儲的總的資訊 params.length的長度約定的至少為2,為2 直接取第一個,其他的長度需要另外處理
let resultInfo = '';
if (params.length === 2) {
resultInfo = params[0];
} else {
let k = 1;
const firstInfo = params[0].split(' ');
const newInfo = [];
for (let j = 0; j < firstInfo.length; j++) {
if (firstInfo[j] === '%s' || firstInfo[j] === '%s,') {
newInfo.push(params[k]);
k++;
} else if (firstInfo[j] === '%j' || firstInfo[j] === '%j,') {
newInfo.push(JSON.stringify(params[k]));
k++;
} else {
newInfo.push(firstInfo[j]);
}
}
resultInfo = newInfo.join(' ');
} // end else
if (info === 'info') {
sdkLog.info('info', resultInfo);
} else {
sdkLog.error('error', resultInfo);
}
// 之前debug的邏輯還是保留的,localstoreage.debug = 'ali-oss'
_debug(...params);
};
3. 擷取日志資訊并上傳
collect all logs
Logline.all(function(logs) {
// process logs here這裡可以擷取到所有的日志是一個大數組,使用者可以自行把資料上傳到任何地方OSS、STS或者其他日志分析系統
console.log(logs)
});
// collet logs within .3 days
Logline.get('.3d', function(logs) {
// process logs here
});
4. 收集的日志
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLkFGZiF2YlFzYlRDM5I2N3EmMkBjZyUjY2UzNkVjM3gTYxcjN1UGOx8CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
總結
在浏覽器端客戶如果想收集日志資訊,開發者需要在業務代碼中劫持debug函數資訊,再結合第三方日志收集工具比如logline把日志收集到localstoreage 、indexed db 、或者websql中,然後再擷取日志。