You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JMeter自定义Groovy监听器无法移除采样器空格致InfluxDB上报失败

JMeter自定义监听器上报InfluxDB空格问题修复

问题描述

用Groovy开发JMeter自定义监听器,用于将测试结果上报到InfluxDB,但当采样器或事务控制器名称包含空格时,脚本执行失败。尝试添加移除空格的容错逻辑,但未生效。

原脚本

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.util.EntityUtils;
import org.apache.jmeter.samplers.SampleResult;

try {

Metrics = new StringBuilder();
 String status = "Failure";
  if (sampleResult.isSuccessful())
      status = "Success";
 if (sampleResult.getSampleLabel().startsWith("/"))
      Metrics.append("Requests")
 else
 Metrics.append("JMeter_Result")
 Metrics.append(",requestName=")
 .append(escapeValue(sampleResult.getSampleLabel()))
 .append(",httpstatuscode=")
 .append(sampleResult.getResponseCode())
 .append(",status=")
 .append(status)
 .append(",ScenarioID=")
 .append('${__groovy(vars.get("uniqueScenario_Id"),)}')
 .append(" responseTime=")
 .append(sampleResult.getTime())
 .append(",responsecode=")
 .append("\"${(sampleResult.getResponseCode())}\"")
 .append(",sentBytes=")
 .append(sampleResult.getSentBytes())
 .append(",receivedBytes=")
 .append(sampleResult.getBytesAsLong())
 .append( ",responseMessage=")
 .append("\"${(sampleResult.getResponseMessage())}\"")
 .append(",samplecount=")
 .append(sampleResult.getSampleCount())
 .append(",errorCount=")
 .append(sampleResult.getErrorCount())
 .append(" ")
 .append(sampleResult.getTimeStamp())
 .append("000000");
     if(sampleResult.getSampleLabel().equals("UserIdleTime"))
        {
        }
    else {
        PostMeasurement(Metrics.toString());
        }
} catch (Exception e) {
     log.error("Error in Grafana Metrics Listener : " +e );
}
//Escape the string values before posting the data
String escapeValue(String val) {
 val = val.replaceAll(",", "\\,")
 .replaceAll(" ", "\\")
 .replaceAll("=", "\\=")
 .trim();
    if(val.matches(".*\\s.*")) {
        val = val.replaceAll("\\s","");
        return val;
    }
    else {
        return val;
    }
 // return val;

}

// Post the result to influxDB
void PostMeasurement(String Metrics) {
 def httpclient = new DefaultHttpClient(new BasicHttpParams());
 def httpPost = new HttpPost();
 httpPost.setURI(new URI(vars.get("InfluxDBAPI")));
 httpPost.setEntity(new StringEntity(Metrics));
 HttpResponse response = httpclient.execute(httpPost);
 EntityUtils.consumeQuietly(response.getEntity());
}

问题原因

原escapeValue函数逻辑错误:

  • 先执行replaceAll(" ", "\\")将空格替换为单个反斜杠,导致原空格被替换,后续val.matches(".*\\s.*")无法检测到空格,移除空格的逻辑不会触发。
  • 这种替换方式不符合InfluxDB行协议要求,反斜杠无法正确转义空格,导致InfluxDB解析失败。

解决方案

修正escapeValue函数,选择以下两种方式之一:

方式1:直接移除所有空格

如果不需要保留名称中的空格,直接移除所有空格即可:

String escapeValue(String val) {
    // 先移除所有空格,再处理逗号和等号的转义
    val = val.replaceAll("\\s", "")
             .replaceAll(",", "\\,")
             .replaceAll("=", "\\=")
             .trim();
    return val;
}

方式2:按InfluxDB行协议正确转义空格

如果需要保留名称中的空格,按照InfluxDB规范,可选择转义空格或用双引号包裹标签值:

转义空格

String escapeValue(String val) {
    // 转义逗号、等号、空格
    val = val.replaceAll(",", "\\,")
             .replaceAll("=", "\\=")
             .replaceAll(" ", "\\ ")
             .trim();
    return val;
}

双引号包裹标签值(推荐)

用双引号包裹后,内部的特殊字符无需额外转义,逻辑更简单:

String escapeValue(String val) {
    val = val.trim();
    return "\"${val}\"";
}

补充说明

InfluxDB行协议中,标签值的特殊字符(空格、逗号、=)必须转义或用双引号包裹,否则会导致解析错误。优先推荐双引号包裹的方式,避免转义逻辑出错。

内容的提问来源于stack exchange,提问作者Jyoti Prakash Mallick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 09:17:00