linux-實現日誌分析--python

liu4356發表於2024-03-19

linux-實現日誌分析--python

涉及到的主要python包和系統命令:

1. datetime #用於處理時間
2. subprocess #用於呼叫命令列工具
3. tail -f logFile #獲取logFile新增內容

廢話不多說,下面說一下場景需求和具體解決方案。

1. [場景需求]

一個區塊鏈專案,在專案測試過程中,透過日誌發現出塊不穩定,為了定位問題,需要精確的統計出塊時間。擷取一段日誌如下:

I[2019-07-11|16:57:24.139][45712] reapMaxBytesMaxGas                           module=mempool mempoolTxNum=0 reapTxNum=0 maxNumPerBlock=2000
I[2019-07-11|16:57:24.220][45712] [60]---------- BeginBlock[4367] ----------   module=main
I[2019-07-11|16:57:24.224][45712] Executed block                               module=state height=4367 validTxs=0 invalidTxs=0
D[2019-07-11|16:57:24.307][45712] Commit synced                                module=main commit=436F6D6D697449447B5B333520342031383720363120343120313336203137312031203137302032343120323220313230203836203233382031333120313634203231302031323420313530203233322036203434203130342033322036302031303220343120323530203131352031323720313138203134355D3A313130467D
I[2019-07-11|16:57:24.307][45712] BlockHeight<4367>, BeginBlock<0ms>, DeliverTx<0ms>, EndBlock<0ms>, Commit<82ms>, Tx<0> module=main
I[2019-07-11|16:57:24.307][45712] BlockHeight<4367>, Abci<82ms>, Tx<0>, fullfilled<0>, pending<0>, canceled<0>, expired<0>, partialfilled<0> module=main
I[2019-07-11|16:57:24.307][45712] Committed state                              module=state height=4367 txs=0 appHash=2304BB3D2988AB01AAF1167856EE83A4D27C96E8062C68203C6629FA737F7691
I[2019-07-11|16:57:25.208][45712] reapMaxBytesMaxGas                           module=mempool mempoolTxNum=0 reapTxNum=0 maxNumPerBlock=2000
I[2019-07-11|16:57:25.284][45712] [60]---------- BeginBlock[4368] ----------   module=main

2. [日誌分析]

日誌中Committed state代表狀態持久化,也就是區塊生命週期的末尾。 因此我們使用Committed state來對日誌進行過濾,並用最新一條日誌的時間戳減去上條日誌時間戳作為本區塊出塊時間。

3. [程式碼]

#!/usr/bin/python
#encoding=utf-8
#Filename: block_time.py

import subprocess
from datetime import datetime
import time

logFile = "./blockchain.log"
lastDateTime = datetime.now()

#主程式
def monitorLog(logFile):
   print("monitor logFile: %s" % logFile)
   stopTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()+100)) #指令碼100秒後退出
   popen = subprocess.Popen(["tail", "-f", logFile], stdout=subprocess.PIPE, stderr=subprocess.PIPE) #啟動子程序執行tail命令
   while True:
      line = popen.stdout.readline().strip() #按行獲取日誌
      if line:
         if 'Committed state' in line:
            getBlockInterval(line)  #分析日誌
      now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) #當前時間
      if now >= stopTime: #如果當前時間超過stopTime,表示不再分析日誌,退出程式
           popen.kill()
           print("kill subprocess")
           break

#計算連續兩條日誌的時間差
def getBlockInterval(line): 
   t = getDateTime(line)
   global lastDateTime
   blockInterval = (t-lastDateTime).total_seconds() #將datetime時間差用seconds計算
   blockHeight = getBlockHeight(line)

   lastDateTime = t
   print('%s, interval=%s' % (blockHeight, blockInterval)) #列印結果

#獲取區塊高度
def getBlockHeight(line): 
   return line.split('module')[1].split(' ')[1]

#獲取每行日誌的時間戳
def getDateTime(line): 
   line = line.split('[')[1][:-1].split('.')[0].replace('|', ' ')
   t = datetime.strptime(line, "%Y-%m-%d %H:%M:%S")
   return t

if __name__ == '__main__':
   monitorLog(logFile)

4. [日誌分析結果]

height=4343, interval=1.0
height=4344, interval=1.0
height=4345, interval=1.0
height=4346, interval=1.0
height=4347, interval=1.0
height=4348, interval=1.0
height=4349, interval=2.0
height=4350, interval=1.0
height=4351, interval=1.0

5.[總結-指令碼詳細註解]

這個Python指令碼,其主要目的是監視一個名為blockchain.log的日誌檔案,並分析其中包含特定字串('Committed state')的行。該指令碼的主要功能和步驟如下:

初始化:

匯入所需的模組。
設定日誌檔案的路徑為./blockchain.log。
獲取當前時間,並設定為lastDateTime。
主程式(monitorLog函式):

定義一個停止時間(當前時間加上100秒)。
使用subprocess.Popen啟動一個子程序來執行tail -f命令,該命令會實時顯示日誌檔案的最新內容。
進入一個無限迴圈,從子程序的輸出中按行讀取日誌。
如果讀取到的行包含'Committed state'字串,則呼叫getBlockInterval函式來分析該日誌行。
檢查當前時間是否超過定義的停止時間。如果超過,則殺死子程序並退出迴圈。
分析日誌(getBlockInterval函式):

從日誌行中提取時間戳,並轉換為datetime物件。
計算當前時間與上次記錄的時間之間的差值(以秒為單位)。
從日誌行中提取區塊高度。
更新lastDateTime為當前時間戳。
列印區塊高度和時間間隔。
輔助函式:

getBlockHeight: 從日誌行中提取區塊高度。
getDateTime: 從日誌行中提取時間戳,並轉換為datetime物件。
執行主程式:

如果該指令碼作為主程式執行(而不是被其他指令碼匯入),則呼叫monitorLog函式開始監視日誌檔案。
總的來說,這個指令碼的主要目的是監視區塊鏈日誌,並在找到包含'Committed state'的行時,計算連續兩條此類日誌之間的時間間隔,並列印出相應的區塊高度和時間間隔。這對於分析區塊鏈的效能和穩定性可能非常有用。

相關文章