JSR223¶
There are two types of JSR223:
- Actions: can be dropped anywhere,
- Pre/Post processors: can be dropped under HTTP Request Actions. These are like JSR223 actions but executed right before or after the enclosing HTTP action.
Purpose¶
As OctoPerf is a GUI driven tool, you might encounter some limitation. The JSR223 component opens a new world of possibilities by giving you control of everything through a script:
- Concatenate values
- Find the next working day
- Manipulate variables
Configuration¶
Parameter name | Description | Required |
---|---|---|
Name | Descriptive name for this script. | No |
Language | All languages supported by JMeter out of the box are also currently supported by OctoPerf. | Yes |
Parameters | Values to be passed to the script, space separated. Automatically split into an array of strings namedargs[] |
No |
Script | The script executed each time the Virtual User comes to this action. | Yes |
File | If provided, will override the Script with the content of the file. | No |
Tip
JSR223 Action are samplers, and as such have an Ok/Ko result and a response time. If you do not want any of this, you can add the following inside the JSR223 action: SampleResult.setIgnore();
.
Language¶
The JSR223 allows you to execute a script, written in various languages:
More information is available in the JMeter documentation.
Note
In this page, we will focus on Groovy, Java and JavaScript as they are the most common languages.
Parameters¶
Let's take an example to understand how these work:
We have 3 parameters, separated by spaces:
- first
- second
- last
Script and its resulting log messages
log.info("Number of parameters: " + args.length);
log.info("Parameters array: " + args);
log.info("All parameters: " + Parameters);
log.info("First parameter: " + args[0]);
log.info("Second parameter: " + args[2]);
INFO JSR223: Number of parameters: 3
INFO JSR223: Parameters array: [first, second, last]
INFO JSR223: All parameters: first second last
INFO JSR223: First parameter: first
INFO JSR223: Second parameter: last
Variables¶
The following variables can be used in any JSR223 script:
name | Description | Example |
---|---|---|
ctx | Execution context | ctx.isSamplingStarted(); |
vars | Variables in the scope | vars.get("counter"); |
props | System properties | props.get("START.HMS"); |
log | Log messages in the log file | log.info("Hello World!"); |
SampleResult | Points to the current SampleResult | SampleResult.setIgnore(); |
OUT | Console output | OUT.println("Hello World!"); |
sampler | Pointer to the current Sampler. | sampler.addArgument("name", "value"); |
JMeter variables and functions¶
The underlying JMeter will process variables and functions before passing the script field to the interpreter.
We always cache-compile groovy scripts for performance, and you should be extra careful with that language.
Before and after cache-compilation
int starttime = ${__time()};
int starttime = 1604320548420;
It may not seem like much but after this, the cache-compiled version is going to be used for the rest of the test. Which means the date is not updated anymore.
In this situation it is recommended to achieve the same either through:
- Groovy code,
- Parameters.
Warning
Additionally, a function even if commented out in your script might cause an error if it is not properly configured. The reason being that JMeter will process it before the script is interpreted, not knowing if it is commented out.
Pre/Post processors¶
Order¶
Script processors can be attached to a request, in which case the order of actions will be:
- Pre-processors from top to bottom
- HTTP Request
- Post processors from top to bottom
Here's an example with a bunch of processors:
Each processor will log its name to the standard log, and the result is:
Processors order log
ERROR o.a.j.m.J.77b6b9ab-54b7-40be-a219-f3cefa0a0f62: Pre Processor 1
ERROR o.a.j.m.J.ab0724ab-6845-4ef9-aa05-52d75ab18e3f: Pre Processor 2
INFO o.a.j.r.Summariser: summary = 1 in 00:00:01 = 0.8/s Avg: 186 Min: 186 Max: 186 Err: 1 (100.00%)
ERROR o.a.j.e.J.e00f2117-6910-4298-89ab-c384dfc50d6c: Post Processor 1
ERROR o.a.j.e.J.5b3e7453-7082-417f-a79a-3724e75768fc: Post Processor 2
ERROR o.a.j.e.J.1a99c95a-265c-4156-8083-6ce438b3e91b: Post Processor 3
Scope¶
Processors will apply to all the requests that are at the same level than them or below.
To fully understand the meaning of this sentence, we need to understand that these situations are equivalent:
Identical situations
Since there's only one request on the same level or one level below in all these situations it doesn't matter where the processor is.
And another example where the situation is not equivalent:
Different situations
Here the processor applies only to the first request, but if we move it at the same level then it applies to both:
What can be counter intuitive is that its vertical position doesn't matter (it could be first or last, the effect would be the same), only its horizontal (indentation) position enters into account.
Basic samples¶
This section lists various samples for JSR223 action scripts that you can use in your Virtual Users. Note that the Groovy, Java and JavaScript versions are sometimes identical but we provided them all anyway as examples of what can be achieved.
Log a Message¶
This script is an example of how to log a message and the logging levels available. Note that the resulting message will be visible in the JMeter log file after the test only.
Log a message
log.info("This is the log for INFOR level");
log.warn("This is the log for WARNING level");
log.error("This is the log for ERROR level");
log.info("This is the log for INFOR level");
log.warn("This is the log for WARNING level");
log.error("This is the log for ERROR level");
log.info("This is the log for INFOR level");
log.warn("This is the log for WARNING level");
log.error("This is the log for ERROR level");
Manipulate a Variable¶
This script shows how to get variables from JMeter using the vars
preconfigured variable and write them back afterwards.
Manipulate a variable
String my_var = vars.get("MY_VARIABLE");
log.info("The value of my_var is " + my_var);
vars.put("VARIABLE_NAME","VALUE");
String my_var = vars.get("MY_VARIABLE");
log.info("The value of my_var is " + my_var);
vars.put("VARIABLE_NAME","VALUE");
String my_var = vars.get("MY_VARIABLE");
log.info("The value of my_var is " + my_var);
vars.put("VARIABLE_NAME","VALUE");
You'll notice that variables are read and written as strings, so make sure to convert them to the right format before/after using them. There's plenty of examples below with integers.
Note
Although vars.put
will create the variable if it does not exist, it will not be available in the autocompletion unless you also create it in the variables screen.
Increment an Integer¶
A simple script to add a value to an integer.
This is an interesting example to have since vars.get
and vars.put
work with strings.
Increment
int my_number = vars.get("MY_NUMBER").toInteger();
int add = my_number + 3;
vars.put("MY_NUMBER", add.toString());
int my_number = Integer.parseInt(vars.get("MY_NUMBER"));
int add = my_number + 3;
vars.put("MY_NUMBER", add.toString());
int my_number = vars.get("MY_NUMBER").toInteger();
int add = my_number + 3;
vars.put("MY_NUMBER", add.toString());
Replace String in a Variable¶
This quick script will replace a set of chars by another, here \/
is replaced by \
:
Increment
String my_var = vars.get("MY_VARIABLE");
vars.put("MY_VARIABLE",my_var.replace("\\/","/"));
String my_var = vars.get("MY_VARIABLE");
vars.put("MY_VARIABLE",my_var.replace("\\/","/"));
String my_var = vars.get("MY_VARIABLE");
vars.put("MY_VARIABLE",my_var.replace("\\/","/"));
Random¶
This script puts a random value between 50 and 100 in the variable random
:
Random
int random = new java.util.Random().nextInt(50) + 50;
vars.put("MY_NUMBER", random.toString());
int random = new java.util.Random().nextInt(50) + 50;
vars.put("MY_NUMBER", random.toString());
var random = new java.util.Random().nextInt(50) + 50;
vars.put("MY_NUMBER", random.toString());
Log Sampler Info¶
Using JMeter's API it is possible to log information:
Sampler info
log.info( "The Sample Label is : " + SampleResult.getSampleLabel() );
log.info( "The Start Time in miliseconds is : " + SampleResult.getStartTime() );
log.info( "The Response Code is : " + SampleResult.getResponseCode() );
log.info( "The Response Message is : " + SampleResult.getResponseMessage() );
log.info( "The Sample Label is : " + SampleResult.getSampleLabel() );
log.info( "The Start Time in miliseconds is : " + SampleResult.getStartTime() );
log.info( "The Response Code is : " + SampleResult.getResponseCode() );
log.info( "The Response Message is : " + SampleResult.getResponseMessage() );
log.info( "The Sample Label is : " + SampleResult.getSampleLabel() );
log.info( "The Start Time in miliseconds is : " + SampleResult.getStartTime() );
log.info( "The Response Code is : " + SampleResult.getResponseCode() );
log.info( "The Response Message is : " + SampleResult.getResponseMessage() );
More options regarding the SampleResult
class is available in the API documentation.
Date and time scripts¶
Timestamp, formatting and time offsets¶
While it is possible to use __time() and __timeShift() we do not recommend it for reasons explained above. Instead, it is possible to rely on the following code:
Date functions
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
Date now = new Date();
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
cal.setTime(now);
log.error("Timestamp now: " + cal.getTimeInMillis().toString());
cal.add(Calendar.MINUTE, 5);
log.error("Timestamp in 5 min: " + sdf.format(cal.getTime()));
cal.add(Calendar.DATE, +1);
log.error("Tomorrow: " + sdf.format(cal.getTime()));
cal.add(Calendar.MONTH, -1);
log.error("Last month: " + sdf.format(cal.getTime()));
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
Date now = new Date();
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
cal.setTime(now);
log.error("Timestamp now: " + cal.getTimeInMillis().toString());
cal.add(Calendar.MINUTE, 5);
log.error("Timestamp in 5 min: " + sdf.format(cal.getTime()));
cal.add(Calendar.DATE, +1);
log.error("Tomorrow: " + sdf.format(cal.getTime()));
cal.add(Calendar.MONTH, -1);
log.error("Last month: " + sdf.format(cal.getTime()));
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
Date now = new Date();
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
cal.setTime(now);
log.error("Timestamp now: " + cal.getTimeInMillis().toString());
cal.add(Calendar.MINUTE, 5);
log.error("Timestamp in 5 min: " + sdf.format(cal.getTime()));
cal.add(Calendar.DATE, +1);
log.error("Tomorrow: " + sdf.format(cal.getTime()));
cal.add(Calendar.MONTH, -1);
log.error("Last month: " + sdf.format(cal.getTime()));
Warning
The dates and times generated in OctoPerf will always be in the UTC+0 timezone. This way all the load generators share the same time.
Next Working Day¶
This one is a bit more complex. It will create a new date and then proceed to compute the next working day and store it into the nextworkingday
variable.
This can be usefull when you have to enter an attendance or any work related date in a calendar.
Next working day
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public boolean isWorkingDay(Date date, Calendar calendar) {
// set calendar time with given date
calendar.setTime(date);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
// check if it is Saturday(day=7) or Sunday(day=1)
if ((dayOfWeek == 7) || (dayOfWeek == 1)) {
return false;
}
return true;
}
Calendar c = Calendar.getInstance();
Date now = new Date();
c.setTime(now);
c.add(Calendar.DAY_OF_WEEK, 1);
while(!isWorkingDay(c.getTime(), c)) {
c.add(Calendar.DAY_OF_WEEK, 1);
}
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
vars.put("nextworkingday", df.format(c.getTime()));
Pre-processors¶
Because of references to the current sampler, these scripts only works as Pre-processors.
Variable number of parameters¶
This script adds a new parameter to the request:
Add parameter
sampler.addArgument("name", "value");
sampler.addArgument("name", "value");
sampler.addArgument("name", "value");
This allows you to render the number of parameters variable, for instance using a loop and a regex.
Cookies¶
This script adds a cookie named "foo" with the value " bar" for the server "my server". If you leave the cookie settings by default, the new value will be picked by the cookie manager and automatically sent in further requests:
Add cookie
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.Cookie;
Cookie cookie = new Cookie("name","value","octoperf.com","/",false,-1);
CookieManager manager = ctx.getCurrentSampler().getProperty("HTTPSampler.cookie_manager").getObjectValue();
manager.add(cookie);
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.Cookie;
Cookie cookie = new Cookie("name","value","octoperf.com","/",false,-1);
CookieManager manager = ctx.getCurrentSampler().getProperty("HTTPSampler.cookie_manager").getObjectValue();
manager.add(cookie);
Do not store large response contents¶
Very large response content can have a negative impact on JMeter memory. To minimize it, you can activate the storage of a particular response as a MD5 Hash. Just put a Pre-Processor under your request with this script:
MD5 Hash
sampler.setMD5(true);
sampler.setMD5(true);
sampler.setMD5(true);
Warning
Hashing the response cannot be reversed. Once activated, even the error table will only be able to display the hashed body for the response.
Overwrite a header for all requests¶
This script allows to overwrite any header, even the user-agent that we normally change at runtime.
Place it as a Pre-processor script at the root level or on the specific requests you want to override:
Replace header
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
HeaderManager manager = ctx.getCurrentSampler().getHeaderManager();
manager.removeHeaderNamed("User-Agent");
manager.add(new Header("User-Agent","octoperf-jamg"));
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
HeaderManager manager = ctx.getCurrentSampler().getHeaderManager();
manager.removeHeaderNamed("User-Agent");
manager.add(new Header("User-Agent","octoperf-jamg"));
Warning
For this script to work, a header manager must exist, so make there is at least one header defined in OctoPerf.
Modify HTTP Request¶
OctoPerf's interface already allows editing requests, but JSR scripts can do it as well:
Modify HTTP request
sampler.setDomain("petstore.octoperf.com");
sampler.setProtocol("HTTPS");
sampler.setMethod("GET");
sampler.setPort(443);
sampler.setDomain("petstore.octoperf.com");
sampler.setProtocol("HTTPS");
sampler.setMethod("GET");
sampler.setPort(443);
sampler.setDomain("petstore.octoperf.com");
sampler.setProtocol("HTTPS");
sampler.setMethod("GET");
sampler.setPort(443);
Post-processor¶
Ignore Http Status Code¶
Ignore globally¶
It is possible to ignore an error code (4xx
OR 5xx
code) with the help of a Post-processor script. This will effectively make the response code 200
:
Ignore error
prev.setResponseOK();
prev.setResponseOK();
prev.setResponseOK();
And if you would like to ignore only a specific error code you can do it this way:
Ignore specific error
if(prev.getResponseCode() == "404") {
prev.setResponseOK();
}
if(prev.getResponseCode() == "404") {
prev.setResponseOK();
}
if(prev.getResponseCode() == "404") {
prev.setResponseOK();
}
Activable through property¶
This Java
script allows you to ignore certain errors based on HTTP Response Code:
Activable through property
final String prop = props.get("filterErrors");
final boolean isFilterErrors = prop == null ? true : Boolean.valueOf(prop);
if (isFilterErrors) {
int responseCode = 200;
try {
responseCode = Integer.parseInt(prev.getResponseCode());
} catch (final NumberFormatException e) {
// Ignore
}
if (responseCode >= 400 && responseCode < 500) {
prev.setResponseOK();
}
}
This script can be enabled / disabled live during the test via JMeter property filterErrors
. Set it to:
false
to disable ignoring errors,true
to ignore certain errors again.
Read Previous SampleResult¶
Using the prev
variable you can check the content of the previous sample result:
Read previous results
log.info("Thread Group name is: " + prev.getThreadName());
def end_time = prev.getEndTime();
log.info("End Time is: " + (new Date(end_time).toString()));
log.info("Response Time is: " + prev.getTime().toString());
log.info("Connect Time is: " + prev.getConnectTime().toString());
log.info("Latency is: " + prev.getLatency().toString());
log.info("Size in bytes is: " + prev.getBytesAsLong().toString());
log.info("URL is: " + prev.getURL());
log.info("The result is passed: " + prev.isSuccessful().toString());
log.info("Headers are: " + prev.getResponseHeaders());
log.info("Thread Group name is: " + prev.getThreadName());
long end_time = prev.getEndTime();
log.info("End Time is: " + (new Date(end_time).toString()));
log.info("Response Time is: " + prev.getTime().toString());
log.info("Connect Time is: " + prev.getConnectTime().toString());
log.info("Latency is: " + prev.getLatency().toString());
log.info("Size in bytes is: " + prev.getBytesAsLong().toString());
log.info("URL is: " + prev.getURL());
log.info("The result is passed: " + prev.isSuccessful().toString());
log.info("Headers are: " + prev.getResponseHeaders());
Modify previous SampleResult¶
Modifying the previous sample result is also quite simple. It can be useful when you want to programmatically control the response content.
Static change¶
Modify results
def startTime = new Date();
log.info("Start Time should be: " + startTime.getTime().toString());
prev.setStartTime(startTime.getTime());
prev.setResponseCode("201");
prev.setResponseMessage("This message is returned from a JSR223 script");
prev.setResponseData("You will see this sentence in Response Data tab", "UTF-8");
long startTime = new Date();
log.info("Start Time should be: " + startTime.getTime().toString());
prev.setStartTime(startTime.getTime());
prev.setResponseCode("201");
prev.setResponseMessage("This message is returned from a JSR223 script");
prev.setResponseData("You will see this sentence in Response Data tab", "UTF-8");
Dynamic change¶
Here is an example overriding response times that are over a certain value:
Dynamically modify results
def response_time = prev.getTime().toInteger();
def expected_response_time = 500;
if (response_time > expected_response_time) {
prev.setSampleLabel("The response time is too long");
prev.setSuccessful(false);
prev.setResponseCode("500");
prev.setResponseMessage("The expected response time is : " + expected_response_time + "ms but it took: " + response_time + "ms");
}
long response_time = prev.getTime().toInteger();
long expected_response_time = 500;
if (response_time > expected_response_time) {
prev.setSampleLabel("The response time is too long");
prev.setSuccessful(false);
prev.setResponseCode("500");
prev.setResponseMessage("The expected response time is : " + expected_response_time + "ms but it took: " + response_time + "ms");
}
Warning
We use the SampleLabel to tie each sample to its corresponding element in the virtual user tree. Because of this editing the SampleLabel will cause OctoPerf to lose track of this response.
Edit response time¶
This script will edit the response time to always be 1342:
Edit response time
def newEndTime = prev.getStartTime() + 1342;
prev.setEndTime(newEndTime);
long newEndTime = prev.getStartTime() + 1342;
prev.setEndTime(newEndTime);
Warning
While this is a very good way to log a custom value, the original response time will be lost, so make sure to do this on a meaningless HTTP request.
Edit JMeter/JVM settings¶
JMeter Context¶
This script provides examples of what you can achieve through the ctx
variable:
Read from context
log.info("Current Sampler class is: " + ctx.getCurrentSampler());
log.info("JMeter Engine class is: " + ctx.getEngine());
log.error("Previous Response Message is: " + ctx.getPreviousResult().getResponseDataAsString());
log.info("Previous Response Code is: " + ctx.getPreviousResult().getResponseCode());
log.info("Previous Response URL is: " + ctx.getPreviousResult().getURL());
log.info("Previous Response Time is: " + ctx.getPreviousResult().getTime());
log.info("Previous Domain is: " + ctx.getPreviousSampler().getDomain());
log.info("Previous Protocol is: " + ctx.getPreviousSampler().getProtocol());
log.info("Previous Port is: " + ctx.getPreviousSampler().getPort());
log.info("Previous Method is: " + ctx.getPreviousSampler().getMethod());
log.info("Thread Name is: " + ctx.getThread().getThreadName());
log.info("Thread Start Time is: " + ctx.getThread().getStartTime());
log.info("Thread End Time is: " + ctx.getThread().getEndTime());
log.info("Start Next Thread Loop on Error: " + ctx.getThreadGroup().getOnErrorStartNextLoop());
log.info("Stop Test on Error: " + ctx.getThreadGroup().getOnErrorStopTest());
log.info("Current Sampler class is: " + ctx.getCurrentSampler());
log.info("JMeter Engine class is: " + ctx.getEngine());
log.error("Previous Response Message is: " + ctx.getPreviousResult().getResponseDataAsString());
log.info("Previous Response Code is: " + ctx.getPreviousResult().getResponseCode());
log.info("Previous Response URL is: " + ctx.getPreviousResult().getURL());
log.info("Previous Response Time is: " + ctx.getPreviousResult().getTime());
log.info("Previous Domain is: " + ctx.getPreviousSampler().getDomain());
log.info("Previous Protocol is: " + ctx.getPreviousSampler().getProtocol());
log.info("Previous Port is: " + ctx.getPreviousSampler().getPort());
log.info("Previous Method is: " + ctx.getPreviousSampler().getMethod());
log.info("Thread Name is: " + ctx.getThread().getThreadName());
log.info("Thread Start Time is: " + ctx.getThread().getStartTime());
log.info("Thread End Time is: " + ctx.getThread().getEndTime());
log.info("Start Next Thread Loop on Error: " + ctx.getThreadGroup().getOnErrorStartNextLoop());
log.info("Stop Test on Error: " + ctx.getThreadGroup().getOnErrorStopTest());
log.info("Current Sampler class is: " + ctx.getCurrentSampler());
log.info("JMeter Engine class is: " + ctx.getEngine());
log.error("Previous Response Message is: " + ctx.getPreviousResult().getResponseDataAsString());
log.info("Previous Response Code is: " + ctx.getPreviousResult().getResponseCode());
log.info("Previous Response URL is: " + ctx.getPreviousResult().getURL());
log.info("Previous Response Time is: " + ctx.getPreviousResult().getTime());
log.info("Previous Domain is: " + ctx.getPreviousSampler().getDomain());
log.info("Previous Protocol is: " + ctx.getPreviousSampler().getProtocol());
log.info("Previous Port is: " + ctx.getPreviousSampler().getPort());
log.info("Previous Method is: " + ctx.getPreviousSampler().getMethod());
log.info("Thread Name is: " + ctx.getThread().getThreadName());
log.info("Thread Start Time is: " + ctx.getThread().getStartTime());
log.info("Thread End Time is: " + ctx.getThread().getEndTime());
log.info("Start Next Thread Loop on Error: " + ctx.getThreadGroup().getOnErrorStartNextLoop());
log.info("Stop Test on Error: " + ctx.getThreadGroup().getOnErrorStopTest());
Read Write JMeter Properties¶
JMeter properties can be edited this way:
Properties
props.get("PROPERTY_NAME");
props.put("PROPERTY_NAME", "VALUE");
props.get("PROPERTY_NAME");
props.put("PROPERTY_NAME", "VALUE");
props.get("PROPERTY_NAME");
props.put("PROPERTY_NAME", "VALUE");
Info
For a complete list of existing properties, you can use the Debug action. Make sure to activate the display of JMeter and/or system properties if you do so.
JVM configuration change¶
As we take care of installing and maintaining the JVM for you, not all the usual settings are available. But some settings can be edited after the JVM is started using this script:
Properties
System.setProperty("jsse.enableSNIExtension", "false");
System.setProperty("jsse.enableSNIExtension", "false");
Note
It is also possible to use PRE or POST test SH scripts to interact with the underlying JVM.
Set a proxy for all requests¶
While the proxy option is not available in OctoPerf, it is still possible to add a proxy to every HTTP request using the following code. It can be set in a setup threadgroup so that the property is changed once before the test starts:
Proxy
import java.net.Authenticator;
import org.apache.jmeter.ProxyAuthenticator;
System.setProperty("http.proxyHost", "XXX.XXX.XXX.XXX");
System.setProperty("http.proxyPort", "XXXX");
System.setProperty("http.nonProxyHosts", "XXX.XXX.XXX.XXX,XXX.XXX.XXX.XXX");
import java.net.Authenticator;
import org.apache.jmeter.ProxyAuthenticator;
System.setProperty("http.proxyHost", "XXX.XXX.XXX.XXX");
System.setProperty("http.proxyPort", "XXXX");
System.setProperty("http.nonProxyHosts", "XXX.XXX.XXX.XXX,XXX.XXX.XXX.XXX");
Info
Note that we do not recommend load testing through a proxy since you will be limited by the proxy capacity. If you proceed with load testing through a proxy, make sure to monitor the proxy server as well.
Write data to a local file¶
This script allows you to write data to a local file named file.csv
.
This can be useful if you want to prepare a dataset for a later test or just save information for later use.
Proxy
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
BufferedWriter bw = null;
FileWriter fw = null;
String filename="file.csv";
String data="\n"+vars.get("token")+","+vars.get("login")+","+vars.get("password");
File file = new File(filename);
// if file does not exists, then create it
if (!file.exists()) {
file.createNewFile();
}
fw = new FileWriter(file.getAbsoluteFile(), true);
bw = new BufferedWriter(fw);
bw.write(data);
bw.close();
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
BufferedWriter bw = null;
FileWriter fw = null;
String filename="file.csv";
String data="\n"+vars.get("token")+","+vars.get("login")+","+vars.get("password");
File file = new File(filename);
// if file does not exists, then create it
if (!file.exists()) {
file.createNewFile();
}
fw = new FileWriter(file.getAbsoluteFile(), true);
bw = new BufferedWriter(fw);
bw.write(data);
bw.close();
Warning
The file will be cleaned automatically after the test when we destroy the load generator. But you can use an after test script to upload it to our report engine
Deprecated¶
Iteration pacing¶
Warning
Since OctoPerf 11.7.0
this feature is natively available from the runtime screen.
Iteration pacing is a good way to make sure every iteration will have the same duration whatever the response time. To implement it, we will use two scripts and a constant variable named pacing
that contains the duration of the pacing in milliseconds.
Pacing
Put a first script at the very beginning of your Virtual user profile:
import com.google.common.base.Stopwatch;
vars.putObject("watch",Stopwatch.createStarted());
//Remove current script sampler results from report
//SampleResult.setIgnore();
Then the last action in your user profile should be a script with:
import com.google.common.base.Stopwatch;
import java.util.Map;
Map env = System.getenv();
Stopwatch watch = vars.getObject("watch");
long elapsed = watch.elapsed(java.util.concurrent.TimeUnit.MILLISECONDS);
long pacing = Long.parseLong(vars.get("pacing"));
//We do not replay pacing for VU validation
if (elapsed <= pacing && "STANDARD".equals(env.get("TEST_MODE"))) {
long sleep = pacing-elapsed;
Thread.sleep(sleep);
}
//Remove current script sampler results from report
//SampleResult.setIgnore();
Note
We use TEST_MODE
to ensure the pacing is only used during a real test and not a during a validation.