diff --git a/pom.xml b/pom.xml index f39ae57..1c17bd3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 io.github.delirius325 jmeter.backendlistener.elasticsearch - 2.7.0 + 2.8.0 jar jmeter.backendlistener.elasticsearch diff --git a/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetric.java b/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetric.java index a996092..47850d5 100644 --- a/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetric.java +++ b/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetric.java @@ -32,10 +32,14 @@ public class ElasticSearchMetric { private Set fields; private boolean allReqHeaders; private boolean allResHeaders; + private boolean parseSampleLabel; + private String sampleLabelDelimiter; + private String parseSampleLabelKeyValueDelimiter; public ElasticSearchMetric( SampleResult sr, String testMode, String timeStamp, int buildNumber, - boolean parseReqHeaders, boolean parseResHeaders, Set fields) { + boolean parseReqHeaders, boolean parseResHeaders, Set fields, boolean parseSampleLabel, + String parseSampleLabelDelimiter, String parseSampleLabelKeyValueDelimiter) { this.sampleResult = sr; this.esTestMode = testMode.trim(); this.esTimestamp = timeStamp.trim(); @@ -44,6 +48,9 @@ public ElasticSearchMetric( this.allReqHeaders = parseReqHeaders; this.allResHeaders = parseResHeaders; this.fields = fields; + this.parseSampleLabel = parseSampleLabel; + this.sampleLabelDelimiter = parseSampleLabelDelimiter; + this.parseSampleLabelKeyValueDelimiter = parseSampleLabelKeyValueDelimiter; } /** @@ -98,6 +105,9 @@ public Map getMetric(BackendListenerContext context) throws Exce addAssertions(); addElapsedTime(); addCustomFields(context); + if (parseSampleLabel) { + addSplittedSampleLabel(); + } parseHeadersAsJsonProps(this.allReqHeaders, this.allResHeaders); return this.json; @@ -282,4 +292,24 @@ public Date getElapsedTime(boolean forBuildComparison) { } } + /** + * Adds key-value pairs which are split from SampleLabel by delimiters + * Eg. SampleLabel "Id:01_Transaction:Login" is parsed as: + * field name "Id" with value "01" + * field name "Transaction" with value "Login" + * (if default delimiters are used) + */ + private void addSplittedSampleLabel() { + if (this.sampleResult.getSampleLabel().contains(this.sampleLabelDelimiter) + || this.sampleResult.getSampleLabel().contains(this.parseSampleLabelKeyValueDelimiter) ) { + String[] sampleLabelParams = this.sampleResult.getSampleLabel().split(this.sampleLabelDelimiter); + for (String param : sampleLabelParams) { + if (param.contains(this.parseSampleLabelKeyValueDelimiter)) { + String[] splitParams = param.split(this.parseSampleLabelKeyValueDelimiter); + addFilteredJSON(splitParams[0], splitParams[1]); + } + } + } + } + } diff --git a/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetricSender.java b/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetricSender.java index bbeecaa..774465b 100644 --- a/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetricSender.java +++ b/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticSearchMetricSender.java @@ -39,7 +39,7 @@ public ElasticSearchMetricSender(RestClient cli, String index, String user, Stri /** * This method returns the current size of the ElasticSearch documents list - * + * * @return integer representing the size of the ElasticSearch documents list */ public int getListSize() { @@ -62,7 +62,7 @@ public void clearList() { /** * This method adds a metric to the list (metricList). - * + * * @param metric * String parameter representing a JSON document for ElasticSearch */ @@ -95,50 +95,50 @@ public void createIndex() { logger.info("Index already exists!"); } } - + public int getElasticSearchVersion() { - Request request = new Request("GET", "/" ); - int elasticSearchVersion = -1; - try { - Response response = this.client.performRequest(setAuthorizationHeader(request)); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK && logger.isErrorEnabled()) { - logger.error("Unable to perform request to ElasticSearch engine for index {}. Response status: {}", - this.esIndex, response.getStatusLine().toString()); - }else { - String responseBody = EntityUtils.toString(response.getEntity()); - JSONObject elasticSearchConfig = new JSONObject(responseBody); - JSONObject version = (JSONObject) elasticSearchConfig.get("version"); - String elasticVersion = version.get("number").toString(); - elasticSearchVersion = Integer.parseInt(elasticVersion.split("\\.")[0]); - logger.info("ElasticSearch Version : " + Integer.toString(elasticSearchVersion)); - } - } catch (Exception e) { - if (logger.isErrorEnabled()) { - logger.error("Exception" + e); - logger.error("ElasticSearch Backend Listener was unable to perform request to the ElasticSearch engine. Check your JMeter console for more info."); - } - } - return elasticSearchVersion; + Request request = new Request("GET", "/" ); + int elasticSearchVersion = -1; + try { + Response response = this.client.performRequest(setAuthorizationHeader(request)); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK && logger.isErrorEnabled()) { + logger.error("Unable to perform request to ElasticSearch engine for index {}. Response status: {}", + this.esIndex, response.getStatusLine().toString()); + }else { + String responseBody = EntityUtils.toString(response.getEntity()); + JSONObject elasticSearchConfig = new JSONObject(responseBody); + JSONObject version = (JSONObject) elasticSearchConfig.get("version"); + String elasticVersion = version.get("number").toString(); + elasticSearchVersion = Integer.parseInt(elasticVersion.split("\\.")[0]); + logger.info("ElasticSearch Version : " + Integer.toString(elasticSearchVersion)); + } + } catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error("Exception" + e); + logger.error("ElasticSearch Backend Listener was unable to perform request to the ElasticSearch engine. Check your JMeter console for more info."); + } + } + return elasticSearchVersion; } - + /** * This method sends the ElasticSearch documents for each document present in the list (metricList). All is being * sent through the low-level ElasticSearch REST Client. */ public void sendRequest(int elasticSearchVersionPrefix) { - Request request; - StringBuilder bulkRequestBody = new StringBuilder(); - String actionMetaData; - if(elasticSearchVersionPrefix < 7) { - request = new Request("POST", "/" + this.esIndex + "/SampleResult/_bulk"); - actionMetaData = String.format(SEND_BULK_REQUEST, this.esIndex, "SampleResult"); - } - else { - request = new Request("POST", "/" + this.esIndex + "/_bulk"); - actionMetaData = String.format(SEND_BULK_REQUEST, this.esIndex); - } - + Request request; + StringBuilder bulkRequestBody = new StringBuilder(); + String actionMetaData; + if(elasticSearchVersionPrefix < 7) { + request = new Request("POST", "/" + this.esIndex + "/SampleResult/_bulk"); + actionMetaData = String.format(SEND_BULK_REQUEST, this.esIndex, "SampleResult"); + } + else { + request = new Request("POST", "/" + this.esIndex + "/_bulk"); + actionMetaData = String.format(SEND_BULK_REQUEST, this.esIndex); + } + for (String metric : this.metricList) { bulkRequestBody.append(actionMetaData); bulkRequestBody.append(metric); @@ -154,10 +154,10 @@ public void sendRequest(int elasticSearchVersionPrefix) { if (logger.isErrorEnabled()) { if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { logger.error("ElasticSearch Backend Listener failed to write results for index {}. Response status: {}", - this.esIndex, response.getStatusLine().toString()); + this.esIndex, response.getStatusLine().toString()); } else { logger.debug("ElasticSearch Backend Listener has successfully written to ES instance [{}] _bulk request {}", - client.getNodes().iterator().next().getHost().toHostString(), request.toString()); + client.getNodes().iterator().next().getHost().toHostString(), request.toString()); } } } catch (Exception e) { diff --git a/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticsearchBackendClient.java b/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticsearchBackendClient.java index 2fe23ee..e629d2c 100644 --- a/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticsearchBackendClient.java +++ b/src/main/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/ElasticsearchBackendClient.java @@ -1,4 +1,4 @@ - package io.github.delirius325.jmeter.backendlistener.elasticsearch; +package io.github.delirius325.jmeter.backendlistener.elasticsearch; import java.util.*; import java.util.regex.Matcher; @@ -46,6 +46,9 @@ public class ElasticsearchBackendClient extends AbstractBackendListenerClient { private static final String ES_SSL_TRUSTSTORE_PW = "es.ssl.truststore.pw"; private static final String ES_SSL_KEYSTORE_PATH = "es.ssl.keystore.path"; private static final String ES_SSL_KEYSTORE_PW = "es.ssl.keystore.pw"; + private static final String ES_PARSE_SAMPLE_LABEL = "es.parse.samplelabel"; + private static final String ES_PARSE_SAMPLE_LABEL_DELIMITER = "es.parse.samplelabel.delimiter"; + private static final String ES_PARSE_SAMPLE_LABEL_KEY_VALUE_DELIMITER = "es.parse.samplelabel.keyvalue.delimiter"; private static final long DEFAULT_TIMEOUT_MS = 200L; private static final String SERVICE_NAME = "es"; private static RestClient client; @@ -73,6 +76,10 @@ public class ElasticsearchBackendClient extends AbstractBackendListenerClient { DEFAULT_ARGS.put(ES_SSL_TRUSTSTORE_PW, ""); DEFAULT_ARGS.put(ES_SSL_KEYSTORE_PATH, ""); DEFAULT_ARGS.put(ES_SSL_KEYSTORE_PW, ""); + DEFAULT_ARGS.put(ES_PARSE_SAMPLE_LABEL, "false"); + DEFAULT_ARGS.put(ES_PARSE_SAMPLE_LABEL_DELIMITER, "_"); + DEFAULT_ARGS.put(ES_PARSE_SAMPLE_LABEL_KEY_VALUE_DELIMITER, ":"); + } private ElasticSearchMetricSender sender; private Set modes; @@ -104,7 +111,7 @@ public void setupTest(BackendListenerContext context) throws Exception { this.timeoutMs = Integer.parseInt((context.getParameter(ES_TIMEOUT_MS))); this.buildNumber = (JMeterUtils.getProperty(ElasticsearchBackendClient.BUILD_NUMBER) != null && !JMeterUtils.getProperty(ElasticsearchBackendClient.BUILD_NUMBER).trim().equals("")) - ? Integer.parseInt(JMeterUtils.getProperty(ElasticsearchBackendClient.BUILD_NUMBER)) : 0; + ? Integer.parseInt(JMeterUtils.getProperty(ElasticsearchBackendClient.BUILD_NUMBER)) : 0; setSSLConfiguration(context); @@ -213,7 +220,11 @@ public void handleSampleResults(List results, BackendListenerConte ElasticSearchMetric metric = new ElasticSearchMetric(sr, context.getParameter(ES_TEST_MODE), context.getParameter(ES_TIMESTAMP), this.buildNumber, context.getBooleanParameter(ES_PARSE_REQ_HEADERS, false), - context.getBooleanParameter(ES_PARSE_RES_HEADERS, false), fields); + context.getBooleanParameter(ES_PARSE_RES_HEADERS, false), fields, + context.getBooleanParameter(ES_PARSE_SAMPLE_LABEL, false), + context.getParameter(ES_PARSE_SAMPLE_LABEL_DELIMITER), + context.getParameter(ES_PARSE_SAMPLE_LABEL_KEY_VALUE_DELIMITER) + ); if (validateSample(context, sr)) { try { @@ -248,7 +259,7 @@ public void teardownTest(BackendListenerContext context) throws Exception { /** * This method checks if the test mode is valid - * + * * @param mode * The test mode as String */ @@ -266,7 +277,7 @@ private void checkTestMode(String mode) { /** * This method will validate the current sample to see if it is part of the filters or not. - * + * * @param context * The Backend Listener's context * @param sr diff --git a/src/test/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/TestElasticSearchBackend.java b/src/test/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/TestElasticSearchBackend.java index 6968d42..a347156 100644 --- a/src/test/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/TestElasticSearchBackend.java +++ b/src/test/java/io/github/delirius325/jmeter/backendlistener/elasticsearch/TestElasticSearchBackend.java @@ -18,9 +18,9 @@ public class TestElasticSearchBackend { @Before public void setUp() throws Exception { metricCI = new ElasticSearchMetric(new SampleResult(), "info", "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", 1, false, false, - new HashSet()); + new HashSet(), false, "_", ":"); metricNoCI = new ElasticSearchMetric(new SampleResult(), "info", "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", 0, false, - false, new HashSet()); + false, new HashSet(), false, "_", ":"); } @Test