日志系統(tǒng)的建設要點

前言:主要事項

1、異常數(shù)據(jù)的發(fā)現(xiàn)及補充烙肺、日志分類優(yōu)化
2纳猪、日志數(shù)據(jù)的文件保存、滾動存儲
3桃笙、日志文件上傳
4氏堤、日志回撈

一、日志收集

1搏明、日志分類

1.1鼠锈、日志目標

序號 目標(Target)
1 app
2 sdk 三方庫
3 h5 網(wǎng)頁

<a name="日志類型"></a>

1.2、日志類型

序號 類型 描述
1 api_app app中的網(wǎng)絡請求
2 api_app_cache app中的網(wǎng)絡請求的網(wǎng)絡緩存請求
3 api_buriedPoint 埋點的網(wǎng)絡請求
4 sdk_other sdk的各種事件(初始化等)
5 sdk_api sdk中的網(wǎng)絡請求
6 dart 語法
7 widget 視圖(布局像素越界等)
8 click_other 點擊星著、
9 click_share 分享
10 native_route 路由/跳轉(zhuǎn)
11 h5_route 與網(wǎng)頁跳轉(zhuǎn)有關
12 h5_js js交互
13 monitor_network 監(jiān)控:網(wǎng)絡類型變化
14 monitor_lifecycle 監(jiān)控:生命周期變化
15 buriedPoint_other 埋點數(shù)據(jù)生成等
16 im IM
17 heartbeat 心跳
18 other 其他

2购笆、日志等級

序號 目標(Level) 描述
1 Normal 正常信息(目前用于請求開始)
2 Success 成功信息(目前用于請求結(jié)束:成功)
3 Warning 警告信息(目前用于請求結(jié)束:報錯)
4 Error 錯誤日志(目前用于請求結(jié)束:失敗)
5 Dangerous 危險(處理白屏等) 一般會進行額外的埋點

<a name="日志整合歸類"></a>

3、日志整合歸類

序號 列表 標志 包含
1 全部 all 所有
2 警告 warning 所有的警告
3 錯誤 error 所有的錯誤
4 接口 api api_app虚循、api_cache(不包括sdk_api同欠、api_buriedPoint)
5 點擊 click click_share样傍、click_other、h5_js
6 路由 route navite_route铺遂、h5_route
7 網(wǎng)頁 H5 h5_route衫哥、h5_js
8 sdk sdk sdk_api、sdk_other
9 code code dart襟锐、widget
10 埋點 buriedPoint api_buriedPoint炕檩、buriedPoint_other
11 監(jiān)控 monitor monitor_lifecycle、monitor_network
12 其他 other other
13 api結(jié)果 api_result type=api_app & level != Normal
14 im im 本地緩存消息捌斧、歷史消息笛质、收到的消息等
15 心跳 heartbeat

<img src="日志系統(tǒng)/devtool_log_home_page.gif" alt="devtool_log_home_page" style="zoom:50%;" />

4、日志的補充收集及其策略

要收集的數(shù)據(jù)已在上述《1.2捞蚂、日志類型》中說明妇押。

4.1、頁面跳轉(zhuǎn)

詳見上述 《3姓迅、日志整合歸類》中的"路由"

4.2敲霍、截斷的收集

序號 關鍵字 場景
1 break for 、 swtich
2 return

4.3丁存、用戶關鍵行為

序號 行為 用途的場景說明
1 用戶的資源選擇 判斷選擇的本地資源是否上傳到錯誤的存儲桶

二肩杈、日志數(shù)據(jù)的文件保存、滾動存儲

1解寝、數(shù)據(jù)的文件保存

寫入xlog文件中扩然。

2、數(shù)據(jù)的文件滾動存儲

2.1聋伦、日志的過期清理

1夫偶、本地日志文件結(jié)構

-- Document
    -- log
        -- 2020-10-01
            -- xlog_2020-10-01_1.xlog
            -- xlog_2020-10-01_2.xlog
        -- 2020-10-18
            -- xlog_2020-10-18_1.xlog

2、日志保留清理的配置信息(摘自/同 下文的日志接口中的《日志文件配置信息》)

序號 說明 字段 示例
接口回值1 最多保留幾個天的日志目錄 maxDayDirCount 7
接口回值2 最多每天保留幾個文件 maxDayFileCount 10
接口回值3 每個日志文件超過多少后創(chuàng)建新文件 perFileMaxMB 5

3觉增、清理方案

清理時機:在切換前后臺的時候兵拢,

  • 日志配置信息的更新
  • 根據(jù)最新的日志配置信息,延遲10s后(避免影響啟動)逾礁,進行清理判斷及清理
    • 遍歷總?cè)罩灸夸?Document/log 下的所有日志文件夾
    • 如果天日志文件夾個數(shù)超過保留個數(shù)(避免是用保留時間说铃,導致保留時間內(nèi)只有一個日志,也被刪掉)嘹履,則按順序刪除早期日志
      • 遍歷天日志目錄 Document/log/yyyy-MM-dd 下的所有日志文件夾
      • 如果天日志文件夾個數(shù)超過保留個數(shù)(避免是用保留時間腻扇,導致保留時間內(nèi)只有一個日志,也被刪掉)植捎,則按順序刪除早期日志

2.2衙解、日志文件的滾動寫入

要增加的日志記錄,如果添加后會超過日志文件的大小焰枢,則使用新文件寫入蚓峦。

細節(jié)點
1舌剂、日志文件的大小判斷,不要每次都去讀取文件暑椰,而是記錄住大小變化
2霍转、日志不要有一條寫一條,而是使用寫入緩沖區(qū)+定時器一汽,5s嘗試寫入一次

3避消、數(shù)據(jù)的加密、解密

1召夹、加密:

寫入日志字符串時候岩喷,對編碼后的字節(jié)數(shù)據(jù),額外增加一個三位隨機值监憎。

  /// 使用 GZip 壓縮算法將字符串進行壓縮纱意,并返回壓縮后的字節(jié)數(shù)據(jù)(List<int> 類型)。
  List<int> _gzipCompressString(String inputString) {
    final codec = GZipCodec();
    
    // 將輸入字符串 inputString 編碼為 UTF-8 格式的字節(jié)數(shù)據(jù)
    final encoded = utf8.encode(inputString);
    
    // 對編碼后的字節(jié)數(shù)據(jù)進行壓縮鲸阔,并返回壓縮后的字節(jié)數(shù)據(jù)偷霉。
    final compressedData = codec.encode(encoded);
    
    return compressedData;
  }

  /// 加密日志字符串
  String _encryptLogString(String logString) {
    final compressedData = _gzipCompressString(logString); // 壓縮字符串,并返回壓縮后的字節(jié)數(shù)據(jù)(List<int> 類型)
    final randomNumber = Random().nextInt(800) + 100;
    final confound = compressedData.toString().substring(0, compressedData.toString().length - 1) + ", $randomNumber]"; // 在壓縮后的字符串尾部加上一個隨機字符串

    return confound;
  }

2褐筛、解密:

使用python腳本對log文件進行解密

import sys
import os
import gzip

# 讀取.clog文件并解析數(shù)據(jù)
def parse_clog_file(input_file):
    parsed_data = []

    with open(input_file, 'r') as clog_file:
        current_data = ""
        for line in clog_file:
            if current_data:
                parsed_data.append(current_data)
            binary_data = line[:-6] + ']' # 去除加密時候額外添加的三位隨機數(shù)
            byte_data = bytes(eval(binary_data))
            decompressed_data = gzip.decompress(byte_data)
            # current_data = byte_data.decode('utf-8')
            print(decompressed_data)
            current_data = decompressed_data.decode('utf-8')

        # 添加最后一個數(shù)據(jù)條目
        if current_data:
            parsed_data.append(current_data)

    return parsed_data

# 將解析后的數(shù)據(jù)寫入與輸入文件同名的.log文件
def write_to_log_file(parsed_data, input_file):
    base_name = os.path.splitext(input_file)[0]
    output_file = base_name + ".log"

    with open(output_file, 'w') as log_file:
        for data in parsed_data:
            log_file.write(data + "\n")
            log_file.write("\n")
            log_file.write("=================================================================================================" + "\n")
            log_file.write("\n")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python script.py <clogFileName>")
        sys.exit(1)

    input_clog_file = sys.argv[1]

    # 解析.clog文件
    parsed_data = parse_clog_file(input_clog_file)

    # 將解析后的數(shù)據(jù)寫入與輸入文件同名的.log文件
    write_to_log_file(parsed_data, input_clog_file)

    print(f"Log data parsed from {input_clog_file} and written to {input_clog_file}.log.")

三类少、日志文件上傳

1、日志文件命名及目錄規(guī)范

以用戶10000012020-01時候上傳聲音文件 beautiful_scenery.aac為例渔扎,其路徑完整示例如下:

https://media.xxx.com/app1_test1/audio/1/1000001/2020-01/beautiful_scenery.aac

要上傳的存儲桶:

序號 說明 參數(shù) 約定值示例
1 存儲桶region
regionGetFunction
網(wǎng)絡環(huán)境 ap-shanghai
2 存儲桶bucket
bucketGetFunction
網(wǎng)絡環(huán)境 xxx-pro-image-1302324914
3 上傳成功后硫狞,桶的映射路徑值
cosFileUrlPrefixGetFunction
1、圖片桶:https://images.xxx.com/
2赞警、媒體桶:https://media.xxx.com/
3妓忍、日志桶:https://static.xxx.com/
4 要上傳到桶的哪個相對路徑下
cosFileRelativePathGetFunction
上傳成功后完整路徑=以上桶值+此相對路徑
見下文 見下文
eg:app1_test1/audio/1/1000001/2020-01/beautiful_scenery.aac

《要上傳到桶的哪個相對路徑下 cosFileRelativePathGetFunction 》的文件路徑分批說明:

序號 層次說明 層次值算法 層次值描述
1.1 存儲桶里相對路徑的前綴 app標志_環(huán)境標志
eg:app1_pro、app1_test1愧旦、app1_dev1
文件區(qū)分
1.2 是否在存儲桶里進行進一步路徑區(qū)分(可選) 根據(jù)場景決定是否對桶進行進一步分類。
if ( mediaType == xxx ) {
if(mediaScene == yyy) {

}
}

1定罢、都是圖片笤虫,但自拍圖片要求獨立出來
2、都是多媒體祖凫,但音視頻要區(qū)分開
2.1 用戶1級 int.parse(uid) % 1000; // 取余數(shù) 用戶名取余琼蚯,有效減少同層上文件夾個數(shù)
2.2 用戶2級 uid 用戶名
3 年月 DateTime.now().toString().substring(0, 7); 年-月
4 文件名 {fileOriginName}_<br>{DateTime.now().microsecondsSinceEpoch}
.$fileExtensionType
文件名

附1:MediaType 媒體類型

序號 UploadMediaType 媒體類型 描述
1 unkonw 未知(默認值)
2 image 圖片
3 audio 音頻
4 video 視頻
5 xlog 日志文件

附2:MediaScene場景 說明

序號 UploadMediaScene場景 描述
1 unkonw 未知(默認值)
2 selfie 自拍(安全等級較多)
3 im 會話聊天
4 live 直播

四、日志接口

1惠况、日志記錄接口(區(qū)別于回撈接口遭庶,需要在回撈前就有日志信息)

1、是否記錄日志的開關及其配置信息

序號 說明 字段 示例
網(wǎng)頁配置1 是否開啟日志記錄 isLogOn 1:開啟稠屠、其他:關
網(wǎng)頁配置2 要開啟日志的用戶(灰度上線)
(當且僅當開啟上述日志記錄時有效)
??:未配置但開關為開時為全記錄
logUserids ["101", "102"]
網(wǎng)頁配置3 要開啟日志的設備(灰度上線)
(當且僅當開啟上述日志記錄時有效)
??:未配置但開關為開時為全記錄
logDeviceIds ["udid001", "udid002"]
接口回值1 是否進行日志記錄(灰度上線) needLog 1:記錄峦睡、其他:不記錄

2翎苫、不需要記錄什么日志信息

序號 說明 字段 示例
接口回值1 不需要記錄的日志類型 ignoreLogLevel ["Normal", "Success"]
接口回值2 不需要記錄的日志等級 ignoreLogType ["api_buriedPoint", "buriedPoint_other"]

3、日志文件配置信息

序號 說明 字段 示例
接口回值1 最多保留幾個天的日志目錄 maxDayDirCount 7
接口回值2 最多每天保留幾個文件 maxDayFileCount 10
接口回值3 每個日志文件超過多少后創(chuàng)建新文件 perFileMaxMB 5

4榨了、日志文件問題回滾

序號 說明 字段 示例
網(wǎng)頁配置1 強制刪除什么時間前的日志 removeLogBeforeDate 2020-12-31
網(wǎng)頁配置2 強制刪除哪個用戶的日志 removeUserids ["101", "102"]
網(wǎng)頁配置2 強制刪除哪個設備的日志 logDeviceIds ["udid001", "udid002"]
接口回值1 強制刪除什么時間前的日志(不刪除時空) removeLogBeforeDate 2020-12-31 或 空值

接口名定義:

function getLoggerConfig(userid, deviceId)

接口結(jié)果的json示例如下:

{
    "logConfig": {
        "needLog": 1,
        "ignoreLogLevel": ["Normal", "Success"],
        "ignoreLogType": ["api_buriedPoint", "buriedPoint_other"],
        "maxDayDirCount": 7,
        "maxDayFileCount": 10,
        "perFileMaxMB": 5
    },
    "logRevert": {
        "removeLogBeforeDate": "2020-12-31"
    }
}

2煎谍、日志回撈及問題回滾接口

1、日志回撈

序號 說明 字段 示例
網(wǎng)頁配置1 要回撈日志的用戶 salvageUserids ["101", "102"]
網(wǎng)頁配置2 要回撈日志的設備 salvageDeviceIds ["udid001", "udid002"]
網(wǎng)頁配置3 日志回撈的開始時間 salvageStartDate 2020-01-01
網(wǎng)頁配置4 日志回撈的結(jié)束時間 salvageEndDate 2020-01-07
接口回值1 此用戶此設備日志回撈的開始時間 salvageStartDate 2020-01-01
接口回值1 此用戶此設備日志回撈的結(jié)束時間 salvageEndDate 2020-01-07

2龙屉、日志文件問題回滾

序號 說明 字段 示例
網(wǎng)頁配置1 強制刪除什么時間前的日志 removeLogBeforeDate 2020-12-31
網(wǎng)頁配置2 強制刪除哪個用戶的日志 removeUserids ["101", "102"]
網(wǎng)頁配置2 強制刪除哪個設備的日志 logDeviceIds ["udid001", "udid002"]
接口回值1 強制刪除什么時間前的日志(不刪除時空) removeLogBeforeDate 2020-12-31 或 空值

接口名定義:

function getLoggerSalvageAndRevert(salvageUserids, salvageDeviceIds)

接口結(jié)果的json示例如下:

{
  "salvageId": "1001", 
    "salvageStartDate": "2020-01-01",
  "salvageEndDate": "2020-01-07",
    "removeLogBeforeDate": "2020-12-31"
}

3呐粘、日志文件上傳到cos后同步給后臺

用途:日志文件上傳到cos后同步給后臺,后臺數(shù)據(jù)庫記錄每個用戶转捕,每個設備都撈到了什么數(shù)據(jù)作岖。

接口名定義:

function addLoggerFile(userid, deviceId)

接口結(jié)果的json示例如下:

{

}

四、日志回撈

1五芝、后臺通過接口返回要回撈的信息痘儡。

2、前端用戶在下次使用与柑,收到后臺信息時候谤辜,進行本地日志的上傳。在騰云存儲桶能收到對應日志价捧,即代表成功丑念。

五、方案實施

灰度方案:請參照 灰度系統(tǒng) 结蟋。(附:日志記錄開關里目前已有灰度策略脯倚。)

目的:避免功能異常,出現(xiàn)集體性問題嵌屎。

End

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末推正,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宝惰,更是在濱河造成了極大的恐慌植榕,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尼夺,死亡現(xiàn)場離奇詭異尊残,居然都是意外死亡,警方通過查閱死者的電腦和手機淤堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門寝衫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拐邪,你說我怎么就攤上這事慰毅。” “怎么了扎阶?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵汹胃,是天一觀的道長婶芭。 經(jīng)常有香客問我,道長统台,這世上最難降的妖魔是什么雕擂? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮贱勃,結(jié)果婚禮上井赌,老公的妹妹穿的比我還像新娘。我一直安慰自己贵扰,他們只是感情好仇穗,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著戚绕,像睡著了一般纹坐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舞丛,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天耘子,我揣著相機與錄音,去河邊找鬼球切。 笑死谷誓,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的吨凑。 我是一名探鬼主播捍歪,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鸵钝!你這毒婦竟也來了糙臼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤恩商,失蹤者是張志新(化名)和其女友劉穎变逃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怠堪,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡韧献,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了研叫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡璧针,死狀恐怖嚷炉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情探橱,我是刑警寧澤申屹,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布绘证,位于F島的核電站,受9級特大地震影響哗讥,放射性物質(zhì)發(fā)生泄漏嚷那。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一杆煞、第九天 我趴在偏房一處隱蔽的房頂上張望魏宽。 院中可真熱鬧,春花似錦决乎、人聲如沸队询。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚌斩。三九已至,卻和暖如春范嘱,著一層夾襖步出監(jiān)牢的瞬間送膳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工丑蛤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叠聋,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓盏阶,卻偏偏與公主長得像晒奕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子名斟,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容