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
相关产品推荐
相关产品推荐

