2010-11-19 60 views
0

什麼是解析多行日誌文件的最佳方式,需要在php和/或Python中的前面的行的上下文知識?多線程日誌解析服務時間在PHP/Python

ex。

Date Time ID Call 

1/1/10 00:00:00 1234 Start 
1/1/10 00:00:01 1234 ServiceCall A Starts 
1/1/10 00:00:05 1234 ServiceCall B Starts 
1/1/10 00:00:06 1234 ServiceCall A Finishes 
1/1/10 00:00:09 1234 ServiceCall B Finishes 
1/1/10 00:00:10 1234 Stop 

每個日誌行必須把它綁定到一個會話,但每個連續的套系是不能保證是從同一個會話的唯一ID。

最終目標是找出每筆交易花費多長時間以及每筆交易花費多長時間。

我很樂意使用一個庫,如果一個已經存在。

回答

0

我可以想到兩種不同的方法來做到這一點。

1)您可以使用finite state machine來逐行處理文件。當你點擊開始行時,標記時間。當您使用相同的ID點擊停止線時,請區分時間並報告。

2)使用帶有m修飾符的PHP Perl-Compatible Regular Expressions來匹配每個開始/停止行集合中的所有文本,然後查看返回的每個匹配字符串的第一行和最後一行。

在這兩種情況下,我會驗證ID匹配以防止匹配不同的集合。

0

我的第一個想法是創建對象,每次我的解析器遇到一個新的密鑰的開始模式。我假設,從你的例子來看,1234是一個關鍵,所有必須關聯在一起的日誌行可以映射到一個「事物」(對象)的狀態。

所以你看到模式開始跟蹤其中之一,並且每當你看到一個與之相關的日誌條目時,你就會調用這些後續行代表的事件類型(狀態改變)的方法。

在你的例子中,這些「日誌狀態」對象(缺少更多的apropos術語)可能包含每個ServiceCall(我期望它會是另一類對象)的列表或字典(或其他容器)。因此,總體設計將是讀取日誌的分析器/分派器,如果日誌項目涉及某個現有對象(鍵),則該項目被分派到對象,然後該對象可以進一步創建它自己的(ServiceCall或其他)對象和/或將事件分派給這些對象或引發異常,或根據需要調用回調或調用其他功能。

大概你還需要有一些收集或最終處置處理程序,當停止事件發送給它們時,可以被你的日誌對象調用。

我想你還想支持某種排序或狀態報告方法,以便應用程序可以枚舉所有活的(未收集的)對象以響應某些其他通道中的信號或命令(可能來自非易失性存儲器)通過解析器/調度程序執行阻塞檢查)

0

這是我前段時間根據日誌格式量身定製的日誌解析器的一種變體。 (一般方法跟Jim Dennis的描述非常接近,儘管我使用了列表的defaultdict來累積任何給定會話的所有條目。)

from pyparsing import Suppress,Word,nums,restOfLine 
from datetime import datetime 
from collections import defaultdict 

def convertToDateTime(tokens): 
    month,day,year,hh,mm,ss = tokens 
    return datetime(year+2000, month, day, hh,mm,ss) 

# define building blocks for parsing and processing log file entries 
SLASH,COLON = map(Suppress,"/:") 
integer = Word(nums).setParseAction(lambda t:int(t[0])) 
date = integer + (SLASH + integer)*2 
time = integer + (COLON + integer)*2 
timestamp = date + time 
timestamp.setParseAction(convertToDateTime) 

# define format of a single line in the log file 
logEntry = timestamp("timestamp") + integer("sessionid") + restOfLine("descr") 

# summarize calls into single data structure 
calls = defaultdict(list) 
for logline in log: 
    entry = logEntry.parseString(logline) 
    calls[entry.sessionid].append(entry) 

# first pass to find start/end time for each call 
for sessionid in sorted(calls): 
    calldata = calls[sessionid] 
    print sessionid, calldata[-1].timestamp - calldata[0].timestamp 

爲您的數據,這樣打印出:

1234 0:00:10 

可以處理條目的每個會話的列表,並附有類似的方法來梳理出的子事務。