以下awk
腳本解析日誌文件,並且執行時間增量的計算(間隔)
#!/usr/bin/awk -f
# converts milliseconds to HH:MM:SS,mmm format
function msecs2date(msc) {
h = msc/3600000
m = (msc%3600000)/60000
s = (msc%60000)/1000
ms = msc%1000
printf("%02d:%02d:%02d,%03d\n", h, m, s, ms)
}
# converts HH:MM:SS,mmm to milliseconds
function date2msecs(dat) {
split(dat,d,":")
split(d[3],sx,",")
return d[1]*3600000 + d[2]*60000 + sx[1]*1000 + sx[2]
}
# parses the logfile and generates 2 space-separated columns:
# Col.1 > displays the get/release pair REQUEST_CODE
# Col.2 > displays the time delta between the 'get' and 'release'
# events for the respective REQUEST_CODE in Col.1
BEGIN {FS=" "}
{
one = $1
ten = $NF
getline
if ($10 == ten){
printf("%s ",ten)
msecs2date(date2msecs($1)-date2msecs(one))
}
}
您可以將其保存爲使用它,例如,logdelta,然後使其可執行文件並運行它:
$ chmod +x logdelta
$ ./logdelta logfile > outputfile
這是輸出當你的日誌文件提取物(保存爲日誌)被送入腳本:
$ ./logdelta log
wCv4cbch 00:00:00,006
sZhegruu 00:00:00,007
這個腳本做什麼,本質上,是很簡單的(檢查也是在腳本中的註釋):
它分析日誌文件裏NE-通過線使用空格爲定界符(FS=" "
),獲取從該相關的一個特定的代碼(使用getline
特技)兩者線的適當的令牌,然後,轉移到檢查從兩條線的請求代碼是否相等。如果他們是它首先計算在利用兩個時間戳date2msecs
功能毫秒的時間差,然後這個時間差轉換回HH:MM:使用msecs2date
功能SS,嗯格式,依此類推,直到日誌文件結束。
這兩個轉換器功能非常簡單,您可以在split()
函數here以及here中找到更多信息。現在
,如果你要使用這個腳本生產服務器日誌文件,有一些事情值得一提:
一個 - 不能完全信任的代碼在互聯網上找到(和這也適用於這個非常腳本)
這意味着一兩件事:一次又一次的測試,通過各種角落案件像損壞的日誌文件s和其他畸形或異常,然後再採用任何解決方案(見注)。
乙 - 性能事項
這就是我爲什麼選擇awk
來執行這個腳本。爲了測試它的性能,我創建基於您提供的提取物的整天日誌文件,使用以下c++
(當然,c
實際上)程序:
#include <cstdio>
#include <algorithm> // for rand()
# creates len-sized random alphanumeric codes
void gen_random(char* s, const int len) {
static const char alphanum[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
s[len] = 0;
}
int main(int argc, char* argv[]){
char* filler="INFO [...] (http--0.0.0.0-8443-17) User xxx";
char* coda="REQUEST_CODE =";
char* action;
char gc[9];
for (int i=0;i<24;i++){
for (int j=0;j<60;j++){
for (int k=0;k<60;k++){
for (int l=0;l<1001;l=l+7){
l % 2 == 0 ? (action="get", gen_random(gc,8)):(action="release", void(0));
printf("%02d:%02d:%02d,%003d %s %s %s %s\n",i,j,k,l,filler,action,coda,gc);
};
printf("%02d:%02d:%02d,999 %s release %s %s\n",i,j,k,filler,coda,gc);
};
};
};
return 0;
}
建立這樣的:
$ g++ -o logen logen.cpp
和運行:
$ ./logen > logfile
它創建了一個1.1GB(12441600線)人造日誌文件:
$ head -n 4 logfile
00:00:00,000 INFO [...] (http--0.0.0.0-8443-17) User xxx get REQUEST_CODE = fa37JncC
00:00:00,007 INFO [...] (http--0.0.0.0-8443-17) User xxx release REQUEST_CODE = fa37JncC
00:00:00,014 INFO [...] (http--0.0.0.0-8443-17) User xxx get REQUEST_CODE = HryDsbza
00:00:00,021 INFO [...] (http--0.0.0.0-8443-17) User xxx release REQUEST_CODE = HryDsbza
...
$ tail -n 4 logfile
23:59:59,980 INFO [...] (http--0.0.0.0-8443-17) User xxx get REQUEST_CODE = AI9xRoPQ
23:59:59,987 INFO [...] (http--0.0.0.0-8443-17) User xxx release REQUEST_CODE = AI9xRoPQ
23:59:59,994 INFO [...] (http--0.0.0.0-8443-17) User xxx get REQUEST_CODE = LEAeMTva
23:59:59,999 INFO [...] (http--0.0.0.0-8443-17) User xxx release REQUEST_CODE = LEAeMTva
具有(或多或少)一個真正的日誌文件的代表尺寸。
當供給到腳本它有,性能明智的,結果如下:
$ time ./logdelta logfile > ouputfile
real 0m35.776s
user 0m30.364s
sys 0m2.312s
即〜35秒1.1 GB日誌文件,這是一個相當令人滿意的性能(在單核測試運行Xubuntu 14.04的2GB虛擬機)。
這裏也是一些樣本輸出:
$ head -n 2 outputfile
fa37JncC 00:00:00,007
HryDsbza 00:00:00,007
...
$ tail -n 2 outputfile
AI9xRoPQ 00:00:00,007
LEAeMTva 00:00:00,005
注:我發佈了代號爲人造日誌生成的原因是爲了鼓勵你修改它並嘗試將各種人工錯誤合併到生成的日誌文件中,以便能夠測試此腳本(原樣或與您的修改)的對應方式與其他角落案件。
即使是相同的用戶,每個獲取/釋放對都有唯一的代碼嗎? – sokin
是的,即使在同一用戶上,代碼也是唯一的。 – stegada