JMeter-SSE响应数据自动化3.0

背景

此次因为多了一些需要过滤排除的错误(数量很少),还需要修改下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();
}
相关推荐
VisionDataLab1 小时前
老旧产线机器视觉技改难点剖析:基于布线干扰、通讯不稳定、空间受限的落地优化方案
自动化·视觉检测
实点科技1 小时前
实点科技IO-Link在锂电自动化物流线上的应用
科技·自动化
乐橙开放平台1 小时前
通道国标 ID 贴反会串店:海康大华宇视摄像头怎么用 GB28181 统一接入?
网络·笔记·物联网·自动化·音视频·智能家居
做个有深度的老李2 小时前
中小机加工车间协作机器人落地难点|从集成交付能力角度选型
大数据·人工智能·机器人·自动化·柔性机器人
zuozewei2 小时前
第00篇-为什么是-k6-AI-时代的工具选型
软件测试·jmeter·性能测试·ai测试·k6
德思特3 小时前
德思特混频器参数详解:5MHz–40GHz 宽频段与低噪声 LO 设计
测试工具·自动化·射频工程
慧都小项13 小时前
从原理图到 PCB 制造数据:设计交付的 4 个核对关口
程序人生·自动化·pcb工艺·电子设计
qq_2842740514 小时前
机械原理笔记:平面机构自由度计算(复合铰链、局部自由度、虚约束)与四杆机构入门(含考点)
笔记·学习·平面·自动化·制造
qq_2842740516 小时前
数控铣床与加工中心笔记:铣刀与刀柄系统、G54试切对刀、镜像加工指令、孔加工工艺(钻扩铰镗)与固定循环G73/G83/G81/G76/G87/G84
笔记·学习·自动化·制造
qq_白羊座16 小时前
Jmeter 使用自增参数
jmeter