11package net .delirius .jmeter .backendlistener .elasticsearch ;
22
3+ import java .net .InetAddress ;
4+ import java .text .ParseException ;
5+ import java .text .SimpleDateFormat ;
6+ import java .util .Calendar ;
7+ import java .util .Date ;
8+ import java .util .HashMap ;
9+ import java .util .List ;
10+ import java .util .Map ;
11+
12+ import org .apache .commons .io .IOUtils ;
313import org .apache .commons .lang .StringUtils ;
414import org .apache .jmeter .assertions .AssertionResult ;
515import org .apache .jmeter .config .Arguments ;
1020import org .apache .jmeter .visualizers .backend .BackendListenerContext ;
1121import org .elasticsearch .action .bulk .BulkRequestBuilder ;
1222import org .elasticsearch .client .Client ;
13- import org .elasticsearch .common .transport .InetSocketTransportAddress ;
1423import org .elasticsearch .common .settings .Settings ;
24+ import org .elasticsearch .common .transport .InetSocketTransportAddress ;
25+ import org .elasticsearch .common .unit .TimeValue ;
1526import org .elasticsearch .common .xcontent .XContentType ;
1627import org .elasticsearch .transport .client .PreBuiltTransportClient ;
17- import java .net .InetAddress ;
18- import java .text .SimpleDateFormat ;
19- import java .util .*;
28+ import org .slf4j .Logger ;
29+ import org .slf4j .LoggerFactory ;
2030
2131/**
2232 *
2636 * @source_2: https://github.com/zumo64/ELK_POC
2737 */
2838public class ElasticsearchBackend extends AbstractBackendListenerClient {
39+ private static final String BUILD_NUMBER = "BuildNumber" ;
2940 private static final String ES_HOST = "es.host" ;
3041 private static final String ES_PORT = "es.transport.port" ;
3142 private static final String ES_INDEX = "es.index" ;
3243 private static final String ES_TIMESTAMP = "es.timestamp" ;
3344 private static final String ES_STATUS_CODE = "es.status.code" ;
3445 private static final String ES_CLUSTER = "es.cluster" ;
3546 private static final String ES_BULK_SIZE = "es.bulk.size" ;
47+ private static final String ES_TIMEOUT_MS = "es.timout.ms" ;
48+ private static final long DEFAULT_TIMEOUT_MS = 200L ;
49+ private static final Logger logger = LoggerFactory .getLogger (ElasticsearchBackend .class );
3650
3751 private Client client ;
38- private Settings settings ;
3952 private String index ;
40- private String host ;
41- private int port ;
4253 private int buildNumber ;
4354 private int bulkSize ;
4455 private BulkRequestBuilder bulkRequest ;
56+ private long timeoutMs ;
4557
4658 @ Override
4759 public Arguments getDefaultParameters () {
@@ -53,23 +65,28 @@ public Arguments getDefaultParameters() {
5365 parameters .addArgument (ES_STATUS_CODE , "531" );
5466 parameters .addArgument (ES_CLUSTER , "elasticsearch" );
5567 parameters .addArgument (ES_BULK_SIZE , "100" );
68+ parameters .addArgument (ES_TIMEOUT_MS , Long .toString (DEFAULT_TIMEOUT_MS ));
5669 return parameters ;
5770 }
5871
5972 @ Override
6073 public void setupTest (BackendListenerContext context ) throws Exception {
6174 try {
6275 this .index = context .getParameter (ES_INDEX );
63- this .host = context .getParameter (ES_HOST );
6476 this .bulkSize = Integer .parseInt (context .getParameter (ES_BULK_SIZE ));
65- this .port = Integer .parseInt (context .getParameter (ES_PORT ));
66- this .buildNumber = (JMeterUtils .getProperty ("BuildNumber" ) != null && JMeterUtils .getProperty ("BuildNumber" ).trim () != "" ) ? Integer .parseInt (JMeterUtils .getProperty ("BuildNumber" )) : 0 ;
67- this .settings = Settings .builder ().put ("cluster.name" , context .getParameter (ES_CLUSTER )).build ();
68- this .client = new PreBuiltTransportClient (this .settings ).addTransportAddress (new InetSocketTransportAddress (InetAddress .getByName (this .host ), this .port ));
77+ this .timeoutMs = JMeterUtils .getPropDefault (ES_TIMEOUT_MS , DEFAULT_TIMEOUT_MS );
78+ this .buildNumber = (JMeterUtils .getProperty (ElasticsearchBackend .BUILD_NUMBER ) != null
79+ && JMeterUtils .getProperty (ElasticsearchBackend .BUILD_NUMBER ).trim () != "" )
80+ ? Integer .parseInt (JMeterUtils .getProperty (ElasticsearchBackend .BUILD_NUMBER )) : 0 ;
81+ Settings settings = Settings .builder ().put ("cluster.name" , context .getParameter (ES_CLUSTER )).build ();
82+ String host = context .getParameter (ES_HOST );
83+ int port = Integer .parseInt (context .getParameter (ES_PORT ));
84+ this .client = new PreBuiltTransportClient (settings ).addTransportAddress (
85+ new InetSocketTransportAddress (InetAddress .getByName (host ), port ));
6986 this .bulkRequest = this .client .prepareBulk ();
7087 super .setupTest (context );
7188 } catch (Exception e ) {
72- e . printStackTrace ( );
89+ throw new IllegalStateException ( "Unable to setup connectivity to ES" , e );
7390 }
7491 }
7592
@@ -81,57 +98,64 @@ public void handleSampleResults(List<SampleResult> results, BackendListenerConte
8198
8299 if (this .bulkRequest .numberOfActions () >= this .bulkSize ) {
83100 try {
84- this .bulkRequest .get ();
85- this .bulkRequest = this .client .prepareBulk ();
101+ this .bulkRequest .get (TimeValue .timeValueMillis (timeoutMs ));
86102 } catch (Exception e ) {
87- e .printStackTrace ();
103+ logger .error ("Error sending data to ES, data will be lost" , e );
104+ } finally {
105+ this .bulkRequest = this .client .prepareBulk ();
88106 }
89107 }
90108 }
91109
92110 @ Override
93111 public void teardownTest (BackendListenerContext context ) throws Exception {
94- if (this .bulkRequest .numberOfActions () > 0 )
112+ if (this .bulkRequest .numberOfActions () > 0 ) {
95113 this .bulkRequest .get ();
96-
97- this . client . close ( );
114+ }
115+ IOUtils . closeQuietly ( client );
98116 super .teardownTest (context );
99117 }
100118
101- public HashMap <String , Object > getElasticData (SampleResult sr , BackendListenerContext context ) {
102- HashMap <String , Object > jsonObject = new HashMap <String , Object >();
119+ public Map <String , Object > getElasticData (SampleResult sr , BackendListenerContext context ) {
120+ HashMap <String , Object > jsonObject = new HashMap <>();
103121 SimpleDateFormat sdf = new SimpleDateFormat (context .getParameter (ES_TIMESTAMP ));
104122
105123 //add all the default SampleResult parameters
106124 jsonObject .put ("AllThreads" , sr .getAllThreads ());
107- jsonObject .put ("BodySize" , sr .getBodySize ());
108- jsonObject .put ("Bytes" , sr .getBytes ());
125+ jsonObject .put ("BodySize" , sr .getBodySizeAsLong ());
126+ jsonObject .put ("Bytes" , sr .getBytesAsLong ());
127+ jsonObject .put ("SentBytes" , sr .getSentBytes ());
109128 jsonObject .put ("ConnectTime" , sr .getConnectTime ());
110129 jsonObject .put ("ContentType" , sr .getContentType ());
111130 jsonObject .put ("DataType" , sr .getDataType ());
112131 jsonObject .put ("ErrorCount" , sr .getErrorCount ());
113132 jsonObject .put ("GrpThreads" , sr .getGroupThreads ());
114133 jsonObject .put ("IdleTime" , sr .getIdleTime ());
115134 jsonObject .put ("Latency" , sr .getLatency ());
116- jsonObject .put ("ResponseTime" , ( sr .getEndTime () - sr . getStartTime () ));
135+ jsonObject .put ("ResponseTime" , sr .getTime ( ));
117136 jsonObject .put ("SampleCount" , sr .getSampleCount ());
118137 jsonObject .put ("SampleLabel" , sr .getSampleLabel ());
119138 jsonObject .put ("StartTime" , sdf .format (new Date (sr .getStartTime ())));
120139 jsonObject .put ("EndTime" , sdf .format (new Date (sr .getEndTime ())));
121140 jsonObject .put ("ThreadName" , sr .getThreadName ());
122141 jsonObject .put ("URL" , sr .getURL ());
123142 jsonObject .put ("Timestamp" , sdf .format (new Date (sr .getTimeStamp ())));
124- jsonObject .put ("BuildNumber" , this .buildNumber );
125- jsonObject .put ("ElapsedTime" , getElapsedDate ());
126- jsonObject .put ("ResponseCode" , (sr .isResponseCodeOK () && StringUtils .isNumeric (sr .getResponseCode ())) ? sr .getResponseCode () : context .getParameter (ES_STATUS_CODE ));
143+ jsonObject .put (ElasticsearchBackend .BUILD_NUMBER , this .buildNumber );
144+ Date elapsedDate = getElapsedDate ();
145+ if (elapsedDate != null ) {
146+ jsonObject .put ("ElapsedTime" , elapsedDate );
147+ }
148+ jsonObject .put ("ResponseCode" , (sr .isResponseCodeOK () &&
149+ StringUtils .isNumeric (sr .getResponseCode ())) ?
150+ sr .getResponseCode () : context .getParameter (ES_STATUS_CODE ));
127151
128152 //all assertions
129153 AssertionResult [] assertionResults = sr .getAssertionResults ();
130154 if (assertionResults != null ) {
131155 HashMap <String , Object > [] assertionArray = new HashMap [assertionResults .length ];
132156 Integer i = 0 ;
133157 for (AssertionResult assertionResult : assertionResults ) {
134- HashMap <String , Object > assertionMap = new HashMap <String , Object >();
158+ HashMap <String , Object > assertionMap = new HashMap <>();
135159 boolean failure = assertionResult .isFailure () || assertionResult .isError ();
136160 assertionMap .put ("failure" , failure );
137161 assertionMap .put ("failureMessage" , assertionResult .getFailureMessage ());
@@ -146,24 +170,27 @@ public HashMap<String, Object> getElasticData(SampleResult sr, BackendListenerCo
146170
147171 public Date getElapsedDate () {
148172 //Calculate the elapsed time (Starting from midnight on a random day - enables us to compare of two loads over their duration)
173+ long start = JMeterContextService .getTestStartTime ();
174+ long end = System .currentTimeMillis ();
175+ long elapsed = (end - start );
176+ long minutes = (elapsed / 1000 ) / 60 ;
177+ long seconds = (elapsed / 1000 ) % 60 ;
178+
179+ Calendar cal = Calendar .getInstance ();
180+ cal .set (Calendar .HOUR_OF_DAY , 0 ); //If there is more than an hour of data, the number of minutes/seconds will increment this
181+ cal .set (Calendar .MINUTE , (int ) minutes );
182+ cal .set (Calendar .SECOND , (int ) seconds );
183+ String sElapsed = String .format ("2017-01-01 %02d:%02d:%02d" ,
184+ cal .get (Calendar .HOUR_OF_DAY ),
185+ cal .get (Calendar .MINUTE ),
186+ cal .get (Calendar .SECOND ));
187+ SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-mm-dd HH:mm:ss" );
149188 try {
150- SimpleDateFormat formatter = new SimpleDateFormat ("YYYY-mm-dd HH:mm:ss" );
151- long start = JMeterContextService .getTestStartTime ();
152- long end = System .currentTimeMillis ();
153- long elapsed = (end - start );
154- long minutes = (elapsed / 1000 ) / 60 ;
155- long seconds = (elapsed / 1000 ) % 60 ;
156-
157- Calendar cal = Calendar .getInstance ();
158- cal .set (Calendar .HOUR_OF_DAY , 0 ); //If there is more than an hour of data, the number of minutes/seconds will increment this
159- cal .set (Calendar .MINUTE , (int ) minutes );
160- cal .set (Calendar .SECOND , (int ) seconds );
161- String sElapsed = String .format ("2017-01-01 %02d:%02d:%02d" , cal .get (Calendar .HOUR_OF_DAY ), cal .get (Calendar .MINUTE ), cal .get (Calendar .SECOND ));
162- Date elapsedDate = formatter .parse (sElapsed );
163- return elapsedDate ;
164- } catch (Exception e ) {
165- e .printStackTrace ();
189+ return formatter .parse (sElapsed );
190+ } catch (ParseException e ) {
191+ logger .error ("Unexpected error occured computing elapsed date" , e );
166192 return null ;
167193 }
194+
168195 }
169196}
0 commit comments