背景
此次因为多了一些需要过滤排除的错误(数量很少),还需要修改下JMeter的jtl文件输出数据(后续统计数据需要)
所以只涉及到JSR脚本的一些改动(此部分改动并不会影响到JMeter的HTML报告)
改动
主要通过设置JMeter中prev输出数据变量threadName为appName这样的方法,来控制jtl的数据。
prev.setThreadName(vars.get(“xxx”) + “^” + vars.get(“xxx”));
脚本如下:
具体改动可以对比自动化2.0
要注意一些响应信息自带的换行符(\n),可能会影响到后续处理jtl文件的数据,目前用的是将\n更换为"-" 或者 “”
import org.apache.jmeter.samplers.SampleResult;
import org.json.JSONObject;
import org.json.JSONException;// 每次脚本执行前需要重置的变量
private void init(){// 添加APPID信息vars.put("APPID",vars.get("appId"));// 每次重置isExist的值,避免上次结果影响本次vars.put("isExist", "true");// 每次重置断言输出信息vars.put("response_type","");vars.put("error_msg", "");vars.put("actual_msg", "");// 设置threadName为appNameprev.setThreadName(vars.get("appName") + "^" + vars.get("xxx"));}// 判断是否是流式响应
private Boolean isStreamingResponse(String response) {return response.contains("data: {");
}// 非流式响应处理,即HTTP请求错误处理
private void errorResponse(String response) {log.info("进入errorResponse处理!!!"); // 判断是不是json格式的响应,first == { ? 是 : 不是response = response.replace("\n","");String first = response.substring(0,1);if("{".equals(first)) {// json格式的错误响应jsonErrorResponse(response);}else {// 非json格式的错误响应noJsonErrorResponse(response);}
}// json格式的错误响应处理
private void jsonErrorResponse(String response) throws Exception {JSONObject jsonResponse = new JSONObject(response);String msg = jsonResponse.get("msg");if ("智能体不存在".equals(msg)) {setAssertMsg("xxx",msg);} else {setAssertMsg("服务器错误",msg);}
}// 非json格式的错误响应处理
private void noJsonErrorResponse(String response) throws Exception {String mainMag = response.substring(0,response.indexOf("at "));setAssertMsg("服务器/其他错误",mainMag);}// 处理SSE响应数据,以data: 为分隔符,输出结果到String[] 中
private String[] splitResponse(String resp) {try {return resp.split("data: ");}catch(Exception e) {log.error("拆分resp为String数组失败!xxx:" + vars.get("appName"));}
}// 获取event信息
private String getEvent(String resp) {try {String ret = resp.substring(resp.indexOf("\"", 8)+1, resp.indexOf("\"", 12));return ret;}catch(Exception e) {log.error("获取event的字段内容失败!");return "Unknow";}
}// 处理event = error 的响应
private void errorResp(String resp) {try{JSONObject jsonResponse = new JSONObject(resp);String errorMsg = jsonResponse.get("message");setAssertMsg("xxx",errorMsg);}catch(Exception e) {log.error("处理 error 响应信息失败");}
}// 判断有无特定target
private Boolean hasTarget(String resp) {String targetStr = vars.get("target");// 每次执行后重置target,避免影响下次target的值vars.put("target", "");return resp.contains(targetStr);
}// 断言参数设置
private void setAssertMsg(String response_type,String error_msg){vars.put("response_type",response_type);vars.put("error_msg", error_msg);vars.put("isExist", "false");
}
private void setAssertMsg(String resp){//此方法用于无目标值的断言参数设置//获取answer中的信息,实际msgJSONObject jsonResp = new JSONObject(resp);String answer = jsonResp.get("data").get("outputs").optString("answer");vars.put("response_type","输出结果与预期不符");vars.put("actual_msg", answer);vars.put("isExist", "false");
}/**正确响应结果获取正常响应的最终结果,并设置到ResponseMessage,以供后续使用
*/
private void setTrueResp(String resp){//获取answer中的信息,实际msgJSONObject jsonResp = new JSONObject(resp);String answer = jsonResp.get("data").get("outputs").optString("answer");String s = answer.replace("\n","-");prev.setResponseMessage(s);vars.put("isExist", "true");}// 是否需要判断 特定target
private Boolean needCheckTarget(String resp) {if(vars.get("target") != null || !"".equals(vars.get("target"))) {// 有target,需要判断特定targetreturn hasTarget(resp);}else {// 无需判断特定targetreturn true;}
}// 过滤器,过滤白名单
private void filter(String resp) {try {Set<String> whiteSet = vars.getObject("whiteSet");String appId = vars.get("APPID");if(whiteSet.contains(appId)) {vars.put("isExist", "true");}else {// 非白名单errorResp(resp);}} catch (Exception e) {setAssertMsg("过滤器失效!","xxx");log.warn("过滤白名单失败!");}
}/**每次执行后,处理变量避免下次空变量的值 受上次的影响变量:mustParam
*/
private void afterHandle(){vars.put("mustParam","");vars.put("target","");
}SampleResult prev = ctx.getPreviousResult();String response = prev.getResponseDataAsString();// 执行前重置变量
init();// 判断是不是SSE响应
try {if (!isStreamingResponse(response)) {// 非SSE响应errorResponse(response);} else {// SSE响应// 拆分String[] respArray = splitResponse(response);// 获取event,进行判断String event = getEvent(respArray[respArray.length - 1]);if("message_end".equals(event)) {// 没有错误,判断 workflow_finished 响应中含有目标字段if(needCheckTarget(respArray[respArray.length - 2])){setTrueResp(respArray[respArray.length - 2]);}else {// 无目标字段,更新断言信息setAssertMsg(respArray[respArray.length - 2]);}}else if("error".equals(event)) {// 有报错,进入过滤器,过滤白名单filter(respArray[respArray.length - 1]);}else if("Unknow".equals(event)) {// 获取event的字段内容失败!setAssertMsg("xxx","xxx");}else {// 未知错误setAssertMsg("xxx!","xxx");}}
} catch (Exception e) {log.error("处理响应失败!", e);setAssertMsg("xxx!","xxx");prev.setSuccessful(false);
}finally {afterHandle();
}