Previous Topic

Next Topic

Book Contents

Book Index

Use Case 3: Sending my load test data to a third-party tool

For this use case, we will see how to send test data (number of VUs, response times, etc.) to a third party. The third party in our case will be Amazon CloudWatch. This will help the operations to see what is tested in their usual monitoring environment.

What we need:

In This Chapter

Preparing the Advanced action

Configure the interface with NeoLoad

Code the behavior of the Advanced action

See Also

How to extend NeoLoad capacities using Custom Advanced Actions

Understand the Use Cases

Set up the environment for Advanced actions

Use Case 1: Handling an MD5 authentication

Use Case 2: Load testing a non-http protocol

Preparing the Advanced action

We will first create a new Advanced action with Maven. The method is the same as in the previous use cases (for more details, see Preparing the action).

As NeoLoad already uses Jackson, we do not need to load it from the AWS dependencies. We can exclude them with the following block:

<dependency>
	<groupId>com.amazonaws</groupId>
    	<artifactId>aws-java-sdk-cloudwatch</artifactId>
    	<version>1.11.221</version>
	<exclusions>
		<exclusion>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
		</exclusion>
		<exclusion>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
		</exclusion>
	</exclusions>
</dependency>

We will also force the Maven project to use version 2.9.0 of Jackson with the following block at the end of the "pom.xml" file (after the repositories):

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.0</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-cbor</artifactId>
			<version>2.9.0</version>
		</dependency>
	</dependencies>
</dependencyManagement>

You can find the "pom.xml" file of your Advanced action here: https://github.com/ttheol/NeoLoadTutorials/blob/master/neotys-advanced-action-aws-integration/pom.xml

NL-Tuto-javaclient

Configure the interface with NeoLoad

Now that we have everything set up, we can start coding our Advanced action. The interface is quite straightforward. Input parameters are:

Our getDefaultActionParameter() function will then look like this:

@Override
public List<ActionParameter> getDefaultActionParameters() {
  final List<ActionParameter> parameters = new ArrayList<ActionParameter>();
  parameters.add(new ActionParameter("AWS Region", "eu-west-1"));
  parameters.add(new ActionParameter("accessKey", ""));
  parameters.add(new ActionParameter("secretKey", ""));
  return parameters;
}

As we did for the last use cases, you will need to change the "bundle.properties" file, and you can eventually change the icon of the Advanced action. The "bundle.properties" file used contains this:

displayName=CloudWatch Integration
displayPath=Monitoring/Cloud
iconFile=AWS-icon.png

Code the behavior of the Advanced action

The behavior of the Advanced action will be coded in 2 steps:

  1. Getting data from NeoLoad Web.
  2. Sending the data we need to CloudWatch.
Get data from NeoLoad Web

You can declare variables to store the parsed parameters, and create a function to go through them. It would be something like this:

private static String awsRegion;
private static String awsAccessKey;
private static String awsSecretKey;
private static String nlWebHost;
private static String nlWebToken;

private static void parseParameters(Context context, List<ActionParameter> parameters) {
	//Initialise the parameters
	nlWebHost = "neoload-api.saas.neotys.com";
	nlWebToken = context.getAccountToken();
	
	//Parse the advanced actions parameters
	for (ActionParameter temp:parameters) {
		switch (temp.getName().toLowerCase()) {
		case "aws region" :
			awsRegion = temp.getValue();
			break;
		case "accesskey":
			awsAccessKey = temp.getValue();
			break;
		case "secretkey":
			awsSecretKey = temp.getValue();
			break;
		case "neoload web host":
			nlWebHost = temp.getValue();
			break;
		case "neoload web token":
			nlWebToken = temp.getValue();
			break;
		default:
			break;
		}
	}
}

You should now have generated a swagger client and imported it in you project. We will add a new constructor to instantiate an API client in the ResultsApi class (in the "io.swagger.client.api" package):

    public ResultsApi(String basePath, String token) {
        this(Configuration.getDefaultApiClient());
    	apiClient.setBasePath(basePath);
    	apiClient.addDefaultHeader("", token);
    }

We can now go back to the execute() function of the ActionEngine, and add the following code:

	//Parse the parameters
	parseParameters(context, parameters);

	//Instantiate a NL Web API client		
	String nlWebPath = String.format("https://%s/v1",nlWebHost);		
	ResultsApi nlWebClient = new ResultsApi(nlWebPath,nlWebToken);

We will then get the test id we will use when calling the NeoLoad Web API, and log that in the check VU:

String testId = context.getTestId();
appendLineToStringBuilder(requestBuilder,String.format("Test Id:%s",testId));

We can now call our API and get test information:

//Get the test information
TestDefinition definition = nlWebClient.getTest(testId);	

We will now log all that information in the request of the check VU:

//Log the information of the test
appendLineToStringBuilder(requestBuilder,String.format("Name:%s",definition.getName()));			
appendLineToStringBuilder(requestBuilder,String.format("Description:%s",definition.getDescription()));
appendLineToStringBuilder(requestBuilder,String.format("Author:%s",definition.getAuthor()));
appendLineToStringBuilder(requestBuilder,String.format("Termination Reason:%s",definition.getTerminationReason()));
appendLineToStringBuilder(requestBuilder,String.format("LG count:%d",getLgCount()));
appendLineToStringBuilder(requestBuilder,String.format("Project Name:%s",definition.getProject()));
appendLineToStringBuilder(requestBuilder,String.format("Scenario Name:%s",definition.getScenario()));
appendLineToStringBuilder(requestBuilder,String.format("Status:%s",definition.getStatus()));
appendLineToStringBuilder(requestBuilder,String.format("Quality Status:%s",definition.getQualityStatus()));
appendLineToStringBuilder(requestBuilder,String.format("Start Date:%tc",new Date(definition.getStartDate())));
appendLineToStringBuilder(requestBuilder,String.format("Duration:%tT",new Date(definition.getDuration())));

//Build the request for the check VU
sampleResult.setRequestContent(requestBuilder.toString());

We will now also get some statistics from NeoLoad Web. We can get and log them this way:

//Get the latest test statistics
TestStatistics stats = nlWebClient.getTestStatistics(testId);
int countVU = stats.getLastVirtualUserCount();			
float requestsPerSec = stats.getLastRequestCountPerSecond();

//Log the latest test statistics
appendLineToStringBuilder(responseBuilder,String.format("Number of Virtual Users: %d",countVU));			
appendLineToStringBuilder(responseBuilder,String.format("Requests per second: %f",requestsPerSec));

Send the data to CloudWatch

In order to send data to CloudWatch you need:

We will create here three functions, to be able to create an AWS Client, add dimensions, and send the request. The three functions are the following:

private AmazonCloudWatch createNewAWSClient(String accessKey, String secretKey, String region) {
	BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);				
	AmazonCloudWatch client = AmazonCloudWatchClientBuilder.standard()		
		.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
		.withRegion(region)
		.build();
	
	return client;
}

private void addDimension(java.util.Collection<Dimension> dimensions, String dimensionName, String dimensionValue) {
	dimensions.add(
			new Dimension()
			.withName(dimensionName)
			.withValue(dimensionValue));
}

private void AWSPutRequest(AmazonCloudWatch client, java.util.Collection<Dimension> dimensions, String nameSpace, String metricName, Double value, StandardUnit unit) {
	MetricDatum datum = new MetricDatum()
		.withDimensions(dimensions)
		.withMetricName(metricName)
		.withUnit(unit)
		.withValue(value);			
	
	PutMetricDataRequest request = new PutMetricDataRequest()
		.withNamespace(nameSpace)
		.withMetricData(datum);
		
	client.putMetricData(request);
}

We can now call those functions in the execute():

If you need to see how those were done in the project, you can get the final Action Engine here: https://github.com/ttheol/NeoLoadTutorials/blob/master/neotys-advanced-action-aws-integration/src/main/java/com/neotys/ps/aws/integration/CloudWatchIntegrationActionEngine.java

Push the action to NeoLoad

Once you have finished developing your Advanced action, you can push it to NeoLoad and try it as explained in Check the behavior of the advanced action.