项目中需要一个统计接口量的脚本,于是尝试着写了第一个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