以下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