项目中需要一个统计接口量的脚本,于是尝试着写了第一个awk脚本。
过程不轻松,但是写完了觉得很爽。哈哈
-----------------------------------------------------------------------------------------------------------------------------------
?
#########################################
####思路:
####1 按行读取,需要判断每条记录的归属线程,并缓存起来,
####2 每个线程的记录打印都是有顺序的,输入报文>异常>输出报文
####3 将输入报文覆盖缓存,当第一次读取到Exception时,认为异常开始,将最近一次的输入报文打印,
####4 异常全部打印完毕后,打印输入报文
####注意:
####所有的缓存都是按照线程名称做得,类似于线程变量,互不影响,通过数组实现
####
####使用:
####1 THREAD_KEY需要替换,不同的日志不一样
####2 INPUT_KEY和OUTPUT_KEY如不同也替换
####3 isExclude函数,如有需要可以修改不同的排除条件
#########################################
BEGIN{
# 变量是不带双引号的,变量值需要带着双引号
THREAD_KEY = "@HttpThreadPool";
INPUT_KEY = "输入报文";
OUTPUT_KEY = "输出报文";
ROW_CACHE = "ROW_CACHE";
THREAD_NAME = "THREAD_NAME";
FILE_NAME = "XXXXX";
}
#获取线程名
function getThreadName(str){
# 线程名称开始索引
THREAD_KEY_END_INDEX = index($0, THREAD_KEY);
if(THREAD_KEY_END_INDEX > 0){
# 获取线程名称
THREAD_NAME_T = substr($0, THREAD_KEY_END_INDEX - 9, 9 );
if(THREAD_NAME_T != "") {
THREAD_NAME= THREAD_NAME_T;
}
}
return THREAD_NAME;
}
#判断此行是否需要排除,后续可增加条件
function isExclude(str){
return index(str, "通过HTTP方式获取缓存失败");
}
#判断不需打印输入输出报文的异常
function needRequestMsg(str){
return index(str, "未找到相应文件") + index(str, "没有生成密钥");
}
{
if(FILE_NAME != FILENAME){
if(FILE_NAME != "XXXXX" ){
printf("+++++++++++++++++文件处理完成[%s]+++++++++++++++++++\n", FILE_NAME);
}
printf("+++++++++++++++++开始处理文件[%s]+++++++++++++++++++\n", FILENAME);
FILE_NAME = FILENAME;
}
# 获取线程名
THREAD_NAME = getThreadName($0);
# 处理不需要打印输入输出报文的部分
if(needRequestMsg($0) > 0){
printf("---------Begin Exception-%s-[%d]------------\n", THREAD_NAME, ++THREAD_EXCEPTION_NUM[THREAD_NAME]);
printf("%s\n", ROW_CACHE);
printf("%s\n", $0);
getline ;
while (index($0, "at ") > 0 && index($0, "(") > 0 ){
printf("%s\n", $0);
getline;
}
printf("---------End Exception-%s-[%d]------------\n", THREAD_NAME, THREAD_EXCEPTION_NUM[THREAD_NAME]);
}
# 当此行中有关键字Exception
if(index($0, "Exception") > 0 && isExclude($0) == 0) {
# BEGIN_EXCEPTION_FLAG是一个key为线程名称的数组缓存,记录当前线程是否开始一个Exception
if((BEGIN_EXCEPTION_FLAG[THREAD_NAME] == "" || BEGIN_EXCEPTION_FLAG[THREAD_NAME] == "0")){
# 当没有开始时,将缓存的输入报文打印,同时记录状态为已开始
BEGIN_EXCEPTION_FLAG[THREAD_NAME] = "1";
}
# 当此行没有线程名称,且不存在Caused by关键字时,说明为异常被换行,打印上一行
if(index($0, THREAD_NAME) == 0 && index($0, "Caused") == 0 && index($0, "at ") == 0){
BODY_EXCEPTION[THREAD_NAME] = sprintf("%s\n%s", BODY_EXCEPTION[THREAD_NAME], ROW_CACHE);
}
# 所有Exception的行都打印
BODY_EXCEPTION[THREAD_NAME] = sprintf("%s\n%s", BODY_EXCEPTION[THREAD_NAME], $0);
}
# 存在关键字"at "的行打印
if(index($0, "at ") > 0 && index($0, "(") > 0){
BODY_EXCEPTION[THREAD_NAME] = sprintf("%s\n%s", BODY_EXCEPTION[THREAD_NAME], $0);
}
# 当此行中存在输出报文关键字,且已经开始一个Exception,打印输入报文,Exception体,输出报文
if(index($0, OUTPUT_KEY) > 0 && BEGIN_EXCEPTION_FLAG[THREAD_NAME] == "1"){
printf("---------Begin Exception-%s-[%d]------------\n", THREAD_NAME, ++THREAD_EXCEPTION_NUM[THREAD_NAME]);
printf("%s\n", INPUT_MSG[THREAD_NAME]);
printf("%s\n", BODY_EXCEPTION[THREAD_NAME]);
# 有可能输出报文有换行,目前处理换行一次的情况,判断行尾是"?>"时,读取下一行并打印
printf("%s", $0);
if(substr($0, length($0)-1) == "?>"){
getline t;
printf("%s\n", t);
} else {
print "\n";
}
printf("---------End Exception-%s-[%d]------------\n", THREAD_NAME, THREAD_EXCEPTION_NUM[THREAD_NAME]);
# 输出报文已打印,Exception结束
BEGIN_EXCEPTION_FLAG[THREAD_NAME] = "0";
BODY_EXCEPTION[THREAD_NAME] = "";
INPUT_MSG[THREAD_NAME] = "";
}
# 当此行中存在输入报文关键字时
if(index($0, INPUT_KEY) > 0){
# 缓存此行,并判断是否存在报文换行的情况
INPUT_MSG[THREAD_NAME] = $0;
if(substr($0, length($0)-1) == "?>"){
getline t;
INPUT_MSG[THREAD_NAME] = sprintf("%s%s", INPUT_MSG[THREAD_NAME], t);
}
}
# 缓存当前行
ROW_CACHE = $0;
}
END{
printf("+++++++++++++++++文件处理完成[%s]+++++++++++++++++++\n", FILENAME);
}
?
原文:http://z1041950008.iteye.com/blog/2190857