背景
此次因为多了一些需要过滤排除的错误(数量很少),还需要修改下JMeter的jtl文件输出数据(后续统计数据需要)
所以只涉及到JSR脚本的一些改动(此部分改动并不会影响到JMeter的HTML报告)
改动
主要通过设置JMeter中prev输出数据变量threadName为appName这样的方法,来控制jtl的数据。
prev.setThreadName(vars.get("xxx") + "^" + vars.get("xxx"));
脚本如下:
具体改动可以对比自动化2.0
要注意一些响应信息自带的换行符(\n),可能会影响到后续处理jtl文件的数据,目前用的是将\n更换为"-" 或者 ""
java
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为appName
prev.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中的信息,实际msg
JSONObject 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中的信息,实际msg
JSONObject 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,需要判断特定target
return hasTarget(resp);
}else {
// 无需判断特定target
return 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();
}