Sampler Result in JMeter: The Complete Advanced Guide
Learn what a Sampler Result contains, how every timing, size, status and thread field is measured, how extractors, assertions and listeners use it, how results are saved and reported, and how to read and protect this data like a performance expert.
Think about a courier company. Every parcel has a tracking record: when it was picked up, when it left the warehouse, when the first update arrived, when it was delivered, how heavy it was, who signed for it, and whether anything went wrong. Without these records, nobody could say whether the company is fast or slow, and nobody could find out where a lost parcel went. A JMeter test is similar. Every request it sends creates a tracking record, and that record is called the Sampler Result.
Every chart, every percentile, every error table and every pass or fail decision in a JMeter report is built from Sampler Results. If you understand this one object well, you can trust your numbers, debug failures quickly, and avoid the quiet mistakes that make test reports misleading. This guide walks through the Sampler Result from the basic idea to the advanced topics that experienced performance engineers care about.
1What Is a Sampler Result?
The record that JMeter writes after every single request.
The simple definition
A sampler is a JMeter element that does one piece of work, such as sending an HTTP request, running a database query, or calling a message queue. Each time a sampler runs, JMeter measures what happened and stores the facts in a package. That package is the Sampler Result, often called a sample result or simply a sample. One run of one sampler by one thread produces one Sampler Result.
The package holds the name of the step, the time it took, the status code, the size of the data, the thread that ran it, whether it passed, and much more. It can also hold the full request and the full response if you choose to keep them. Because every report is made of these packages, a mistake in understanding them leads to a mistake in understanding the whole test.
A Sampler Result is like a receipt from a shop. The receipt shows what you bought, when, how much you paid and whether the payment worked. A shop owner who wants to know the day’s business adds up thousands of receipts. A JMeter report adds up thousands of Sampler Results in exactly the same way.
Why it deserves your attention
Most people look at the summary table at the end of a test and never open a single result. This is risky. A summary can show an average of one second while the individual results show that one request in twenty took ten seconds, or that half of the “successful” requests actually returned an error page with a normal status code. The summary only tells the truth when the results underneath are correct and well understood.
Before you run any large test, run it with one or two threads and open a few individual Sampler Results. Check the status, the response and the timings with your own eyes. Five minutes of this saves hours of confusion later.
2Sampler, Sample Result, Assertion Result and Listener
Four neighbouring words that are often mixed up.
JMeter has many moving parts, and the vocabulary around results can be confusing. Clear definitions help you talk to your team and read the documentation without getting lost.
Sampler
The element that performs an action, such as an HTTP request, a JDBC query or a script step. It is the cause of a result.
Sampler Result
The record created by a sampler run. It stores timings, status, sizes, data and thread details. It is the effect of a sampler run.
Assertion Result
A small verdict attached to a Sampler Result by an assertion element. It says whether a check, such as “the page must contain this text”, passed or failed.
Listener
An element that receives finished Sampler Results and shows, summarises or saves them, for example as tables, graphs or files.
Sample
The everyday word for one Sampler Result. When a report says “1,000 samples”, it means 1,000 Sampler Results.
JTL File
The results file that stores Sampler Results, one row or one record per sample, so that they can be analysed after the test.
How they relate
The relationship is a simple chain. A sampler runs and creates a Sampler Result. Assertions look at the result and attach their verdicts. Listeners then receive the result and turn it into something a human can read or a file that a tool can process. Understanding this chain tells you where to look when something is wrong. If a number looks wrong, it may be a problem in what the sampler measured, in what an assertion decided, or in what a listener chose to save or display.
Many beginners think the listener measures the response time. It does not. The sampler measures. The listener only displays and stores what the sampler measured. A listener can hide fields or summarise them, but it cannot create information that the sampler never collected.
3Where the Sampler Result Appears in the Execution Order
Knowing the order of events explains why some elements can see the result and others cannot.
JMeter follows a fixed order every time a sampler is about to run. Understanding this order tells you when a Sampler Result is born and who may touch it.
flowchart TD
A["Configuration elements apply their settings"] --> B["Pre-processors run"]
B --> C["Timers calculate and apply their delays"]
C --> D["Sampler runs and measures the request"]
D --> E["Sampler Result is created"]
E --> F["Post-processors read the result and extract values"]
F --> G["Assertions check the result"]
G --> H["Listeners receive the finished result"]
The sequence in plain words
Preparation
Configuration elements such as default settings and managers prepare the request. Pre-processors can change variables or the request itself just before it is sent.
Waiting
Timers add their pauses. This waiting happens before the sampler starts the clock, so the pause is not part of the measured response time.
Sampling
The sampler sends the request, waits for the response and records the start time, the end time and other measurements. The Sampler Result is created here.
Reading and checking
Post-processors read the result to capture values such as tokens. Assertions then judge the result and add their verdicts, which may change the success flag.
Publishing
Listeners receive the final version of the result and display it or write it to a file. After this, the result is normally released from memory.
Think of a restaurant order. The waiter first prepares the table, then waits until the kitchen is ready, then the kitchen cooks and serves the dish. A reviewer checks the dish, and finally the manager records it in the daily log. The log entry is the Sampler Result, and each person touches it at a different stage.
Why the order matters in practice
Because timers run before the sampler starts measuring, a five-second think time never appears in the response time of the request. Because assertions run after post-processors, an extractor can capture a value from a response even if an assertion later marks that same response as failed. Because listeners come last, they always see the final status after all assertions have spoken. These simple facts explain many puzzling situations that confuse beginners.
Timers, assertions, pre-processors and post-processors apply only to the samplers within their scope, which is decided by where they sit in the test plan tree. An assertion placed at the top of a thread group checks every sampler below it. The same assertion placed inside a single sampler checks only that sampler. Misplaced elements are a common cause of “why did this check fail on a request I never meant to check”.
4Anatomy of a Sampler Result: Every Field at a Glance
A map of the whole record before we study each part in detail.
A Sampler Result is a bundle of fields. Some describe time, some describe size, some describe status, and some describe the request and the response. Here is a map. Later chapters examine each group carefully.
| Group | Fields | Question it answers |
|---|---|---|
| Identity | Label, thread name, timestamp | Which step ran, who ran it and when? |
| Timing | Elapsed time, latency, connect time, idle time | How long did it take and where was the time spent? |
| Status | Response code, response message, success flag, failure message | Did it work and what did the server say? |
| Size | Bytes received, bytes sent, headers size, body size | How much data moved? |
| Concurrency | Group threads, all threads | How many users were active at that moment? |
| Request | Sampler data, request headers, URL, cookies | What exactly was sent? |
| Response | Response data, response headers, data type, encoding | What exactly came back? |
| Structure | Sub-results, sample count, error count | Was this sample made of smaller samples? |
| Verdicts | Assertion results | Which checks passed or failed? |
Not every field is saved by default
The in-memory Sampler Result holds everything, but when results are written to a file, JMeter saves only a chosen set of fields. By default it saves a compact set that covers the essentials: timestamp, elapsed time, label, response code, response message, thread name, data type, success flag, failure message, bytes, sent bytes, group threads, all threads, URL, latency, idle time and connect time. Heavy fields such as response data, request headers and response headers are not saved unless you ask for them. This choice protects the file size and the memory of the load generator.
Expecting to find response bodies in the results file after a long test, when the setting to save them was never turned on. Decide before the run which fields you will need for analysis, because you cannot recover data that was never saved.
5Timing Fields: Elapsed Time, Latency, Connect Time and Idle Time
Four clocks, each telling a different part of the story.
Timing is the heart of performance testing, and the Sampler Result carries several time measurements. Many people use only one, the elapsed time, and miss valuable information in the others.
Elapsed Time
The total time from just before the request is sent until the last byte of the response has been received. This is the number most reports call “response time” or “load time”.
Latency
The time from just before sending the request until the first byte of the response arrives. It shows how long the server took to start answering. In recent versions it includes the connect time.
Connect Time
The time taken to open the network connection, including the secure handshake for encrypted traffic. It is zero or very small when an existing connection is reused.
Idle Time
Time during which the thread was not sampling, for example while a timer paused it. It helps reconstruct the true rhythm of a user thread.
flowchart LR
A["Request starts"] --> B["Connection opened: connect time"]
B --> C["Request sent and server works"]
C --> D["First byte arrives: latency ends"]
D --> E["Rest of response downloads"]
E --> F["Last byte arrives: elapsed time ends"]
Reading the clocks together
The clocks become powerful when read together. If the connect time is large, the problem is probably in the network path, in name resolution, or in the secure handshake. If connect time is small but latency is large, the server took a long time to start responding, which points to slow processing in the application or the database. If latency is small but the elapsed time is much larger, the server answered quickly but the response is large or the network is slow at carrying it. The gap between elapsed time and latency is roughly the download time.
| What you see | Most likely meaning | Where to look first |
|---|---|---|
| High connect time | Slow connection set-up or secure handshake | Network path, load balancer, certificate settings, connection reuse |
| Low connect, high latency | Slow server-side processing | Application code, database, external services |
| Low latency, high elapsed | Large or slowly delivered response | Response size, compression, bandwidth, content delivery |
| All three small | Healthy and fast | Nothing to fix |
Imagine ordering a pizza by phone. Connect time is how long it takes the shop to pick up your call. Latency is how long until the first sign of progress, such as the shop confirming the order. Elapsed time is how long until the pizza is at your door. A long wait can come from any of the three, and the fix depends on which one it is.
When you report slow responses, quote the percentiles of elapsed time, but keep latency and connect time in your results file. They allow you to say not only that a request was slow, but also which part of the journey was slow, which is what developers need to fix it.
6Response Code and Response Message
What the server said, and what JMeter says when the server says nothing.
HTTP response codes
For web requests, the response code is the three-digit status the server returns, and the response message is the short text that goes with it, such as “OK” or “Not Found”. Codes in the two hundreds mean success. Codes in the three hundreds mean redirection. Codes in the four hundreds mean the client made a mistake. Codes in the five hundreds mean the server failed. The HTTP sampler treats the four-hundred and five-hundred families as failed samples by default, unless an assertion or setting says otherwise.
| Code | Message | Meaning in a load test |
|---|---|---|
| 200 | OK | Request succeeded, but the content still needs checking |
| 201 | Created | A new item was created, common after posting data |
| 302 | Found | Redirect, often during log-in flows |
| 400 | Bad Request | The request was malformed, often a script or data problem |
| 401 | Unauthorized | Missing or expired credentials, often an expired token |
| 403 | Forbidden | Access denied, may be a security rule blocking the load |
| 404 | Not Found | Wrong address or missing data |
| 429 | Too Many Requests | Rate limiting is active and is slowing your test |
| 500 | Internal Server Error | The application failed while processing |
| 502 / 503 / 504 | Gateway or service errors | A proxy, load balancer or backend is overloaded or unreachable |
When the response code is not a number
Sometimes the request never reaches a normal server answer. The connection may be refused, the name may not be found, the secure handshake may fail, or the response may time out. In these cases, JMeter fills the response code with a text that starts with “Non HTTP response code” followed by the name of the technical error. The response message then starts with “Non HTTP response message” followed by details. These entries are very valuable, because they tell you that the problem happened before the application could answer.
Connection refused
Nothing is listening at that address and port. The server may be down, or a firewall or load balancer is rejecting connections at the thread count you reached.
Unknown host
The name could not be resolved. Check the address, the name server and any local host settings on the load generator.
Read or connect timeout
The server accepted the request but did not answer in time, or the connection could not be opened in time. This often signals saturation.
Secure handshake failure
The encrypted connection could not be established, often because of certificate trust, protocol versions or server overload.
Counting only the numeric error codes and ignoring the text codes. Reports that group errors by number may show “a few errors” while thousands of requests failed with connection or timeout problems. Always group by the full response code text, so no failure family is hidden.
A numeric code is like a shop assistant who answers your question, even if the answer is “sorry, we are out of stock”. A non-HTTP code is like walking up to a shop with a locked door, a dead phone line or a missing address. In the first case you got an answer. In the second case you never reached anyone.
7The Success Flag, Assertions and Failure Messages
A request can return a happy status code and still be a failure. The success flag exists to tell the truth.
The Sampler Result carries a success flag, a simple yes or no that says whether the sample passed. The sampler sets an initial value based on its own rules, such as the status code family. Then every assertion attached to the sample gets a chance to change it. If any assertion fails, the final success flag becomes false and a failure message is attached to explain why.
Why status codes alone are not enough
Many modern applications return a normal success code even when the business action failed. A log-in page may return a normal page with the words “wrong password”. A search may return a normal page with the words “no results because of an internal error”. A payment service may return a success code with an error message inside the data. If you only trust the status code, all of these appear green, and your report shows a perfect error rate while real users are suffering.
Response Assertion
Checks text, code, message, headers or the address of the sample against patterns. The most common and the most flexible check.
Duration Assertion
Fails a sample whose elapsed time is longer than a limit you set. Useful for enforcing an agreed response time target.
Size Assertion
Checks that the response size is equal to, larger than or smaller than a number of bytes. Helps detect empty or truncated responses.
JSON and XML Assertions
Check that structured responses contain the right fields and values, instead of searching raw text.
flowchart TD
A["Sampler sets the first success value from its own rules"] --> B["Assertion 1 checks the result"]
B --> C["Assertion 2 checks the result"]
C --> D{"Did any assertion fail?"}
D -->|"Yes"| E["Success flag becomes false and a failure message is stored"]
D -->|"No"| F["Success flag stays as it was"]
Balancing strictness and cost
Assertions cost CPU time, because JMeter must search or parse each response. A very large number of heavy assertions can slow down the load generator and distort the timings. The art is to choose a few checks that prove the business action worked, such as one unique word on the confirmation page, rather than scanning the whole body for many patterns. A well-chosen assertion is cheap and powerful.
For every important step, such as log-in, search and checkout, add at least one assertion that checks a sign of real success, such as a welcome name or an order number. Without it, you are measuring how fast the application can return an error page.
Example: hidden failures behind a 200
A team load-tested a booking page and saw a clean report with zero errors. After they added a check for the booking reference, the error rate jumped to thirty percent. The server had been returning a normal page that said “service busy” under load. The first report had been green only because nothing was checking the content.
Ignore status and non-failing assertions
The Response Assertion has an option called ignore status, which tells it to ignore the failure already caused by the status code, so that a deliberate error response, such as a planned 404 in a negative test, can be counted as a pass. Use this carefully and only for tests where the error is the expected result.
8Size Fields: Bytes, Sent Bytes, Headers Size and Body Size
How much data moved, and why that explains so many slow requests.
The Sampler Result records the amount of data in both directions. These numbers help you understand bandwidth use, spot unexpectedly large responses, and explain why one request is slower than another even though the server worked equally hard.
Bytes (Received)
The total size of the response, including the headers and the body. This is the main size number in reports.
Sent Bytes
The total size of what JMeter sent in the request, including headers and any posted data.
Headers Size
The part of the response that is made of headers. Large cookies and many headers can add surprising weight to every request.
Body Size
The part of the response that is the actual content, such as the page or the data.
Using sizes to find problems
Sizes are a quick sanity check. A page that normally weighs two hundred kilobytes and suddenly weighs two kilobytes under load is almost certainly an error page, even if the status code looks normal. A response that is much larger than expected may indicate missing compression or a data query that returns too many rows. Total received bytes divided by the test time gives the network throughput, which tells you whether the network card or the link to the server could be the limit.
| Observation | Possible reason | Action |
|---|---|---|
| Response size suddenly much smaller | Error or fallback page returned with a normal code | Add a content or size assertion |
| Response size much larger than expected | Compression off, too many rows returned, debug data included | Check headers and the query behind the page |
| Large headers size | Big cookies or many custom headers | Review what the application sets on every response |
| Throughput stops growing but CPU is idle | Network bandwidth reached | Check link capacity and the generator network card |
Size is like the weight of a parcel. A courier can be fast and still take longer to deliver a heavy parcel, because carrying it takes more effort. If a parcel that should weigh one kilogram arrives weighing ten grams, you immediately suspect that something important is missing from the box.
Keep a record of the normal response size for each key step in your test plan. When a test shows a different size, the difference is often the first and fastest clue that something has changed in the application.
9Identity and Concurrency Fields: Label, Thread Name, Timestamp and Active Threads
Who ran it, when it ran and how busy the test was at that moment.
Label
The label is the name of the sample. By default it is the name of the sampler in your test plan. The label is the main key used to group samples in every summary and graph, so a clear and stable naming scheme is one of the most useful habits in performance testing. Chapter 18 treats naming in detail.
Thread name
The thread name combines the name of the thread group and the number of the thread, such as “Shoppers 1-37”. It tells you which virtual user produced the sample. When one user keeps failing while others succeed, the thread name lets you look at that one user’s whole journey and find what was special about it, such as bad test data.
Timestamp
The timestamp records the moment of the sample as a number of milliseconds since the first of January 1970 in universal time. It is the basis of every graph that has time on the horizontal axis. Because all load generators should use synchronised clocks, timestamps from several machines can be placed on one common timeline.
Active threads
Two fields record how busy the test was at the moment of the sample. Group threads is the number of active threads in the same thread group. All threads is the number of active threads in the whole test, across all groups on that machine. These fields let you plot response time against the number of active users, which is exactly the graph you need to find the point where the system begins to struggle.
flowchart LR
A["Samples with timestamp and active threads"] --> B["Group by time"]
B --> C["Response time over time"]
B --> D["Throughput over time"]
B --> E["Active threads over time"]
C --> F["Combined view: how speed changes as users grow"]
D --> F
E --> F
In a test with several workers, the active thread numbers in each sample describe only the machine that ran the sample. To find the total number of active users in the whole test, you must combine the numbers from all workers at the same moment, or use a tool that does this for you.
Example: spotting a broken test account
A tester saw a steady five percent failure rate. Grouping failed samples by thread name showed that almost all failures belonged to three threads. Those three threads had been given test accounts that were locked. Fixing the data removed the failures, and the application had never been at fault.
10The Request Side: Sampler Data, Request Headers, URL and Cookies
The part of the record that proves exactly what JMeter sent.
When a response looks wrong, the first question is always “what did we really send?”. The Sampler Result keeps the answer, as long as it was kept in memory or saved. The request-side fields are your evidence.
Sampler Data
A description of the request as sent, such as the method, the address and the body that was posted. It shows the real values after variables have been replaced.
Request Headers
The headers that were sent, such as content type, authorisation and accepted formats. Missing or wrong headers cause many mysterious failures.
URL
The full address that was called, including query parameters. Useful for checking that variables were replaced correctly.
Cookies
The cookies that were sent with the request. They show whether the thread kept its session or started afresh.
The most common discovery
The most frequent discovery when reading the request side is that a variable was not replaced. The test plan said to send a token, but the request shows the text of the variable name instead of its value. This means the extractor that should have captured the token did not find it in the previous response. Without the request-side evidence, the failure would look like a server problem. With it, the cause is clear within seconds.
Open the failing sample
Look at the request side first: the address, the headers and the body that were really sent.
Compare with what you expected
Check that every variable shows a real value, that the content type is right and that cookies are present when they should be.
Trace backwards
If a value is missing, open the previous sample and its response to see why the extractor failed to capture it.
Fix and repeat
Correct the extractor or the data, and run again with a single thread to confirm before returning to a full test.
Request headers and bodies often hold passwords, tokens and personal data. They are valuable for debugging and dangerous in shared files. Chapter 20 explains how to handle this safely.
11The Response Side: Response Data, Response Headers, Data Type and Encoding
What came back, and how JMeter understands it.
Response data
The response data is the body of the answer: a page, a data message, a file. JMeter keeps it in memory while extractors and assertions work on it. For text answers it can be searched with patterns. For binary answers, such as images or documents, JMeter keeps the bytes but does not try to read them as text. Response data is often the biggest piece of a Sampler Result, and it is the biggest reason that results consume memory.
Response headers
The response headers are the extra information the server sends with its answer: content type, content length, cache rules, cookies to set, and server identification. Extractors can read them to capture values, and assertions can check them. They are also very useful for diagnosing caching, compression and security settings.
Data type and encoding
The data type tells whether the response is treated as text or as binary. The encoding tells JMeter which character set to use when it turns bytes into text. If the encoding is wrong, accented letters and many non-English characters appear as strange symbols, and text checks may fail even though the server answered correctly. If an assertion on a non-English page fails mysteriously, check the encoding first.
| Field | What it holds | Typical use | Cost |
|---|---|---|---|
| Response data | The body of the answer | Extractors, assertions, debugging | High memory use |
| Response headers | Header lines from the server | Caching, cookies, security checks | Low |
| Data type | Text or binary | Decides how the body is handled | None |
| Encoding | Character set of the text | Correct reading of non-English text | None |
Response data is the letter inside an envelope. Response headers are the writing on the outside of the envelope: sender, date, handling instructions. Encoding is the language the letter was written in. If you read a Hindi letter as if it were French, the words look like nonsense even though the letter is perfectly fine.
During script development, keep response data and headers so you can study them. During large load runs, turn off saving them, and rely on assertions to detect failures, so that the load generator keeps its memory for the threads.
12Sub-Results: Redirects, Embedded Resources and Transactions
Sometimes one Sampler Result contains smaller ones inside it.
A single Sampler Result can have sub-results, which are smaller results nested inside a parent result. This happens in three common situations, and each of them changes how you read your numbers.
Redirect chains
When the server answers with a redirect and JMeter is set to follow it, each step of the chain can be stored as a sub-result under the main one. The parent shows the final answer, and the children show the journey.
Embedded resources
When the sampler is set to retrieve images, scripts and styles that a page refers to, each of those downloads becomes a sub-result of the page sample. This makes the page time include the downloads.
Transaction controllers
A transaction controller groups several samplers into one business step, such as “Place order”. It can produce a parent result whose time is the total of the steps inside.
flowchart TD
P["Parent sample: Checkout page"] --> C1["Sub-result: main HTML"]
P --> C2["Sub-result: style file"]
P --> C3["Sub-result: script file"]
P --> C4["Sub-result: product image"]
Why this matters for your numbers
If you group several steps in a transaction and also keep the individual steps in your summary, then the same time is counted twice, once inside the child and once inside the parent. A report that adds everything together would show inflated throughput and counts. Most reports solve this by showing only the parent, or by letting you choose whether to include the sub-samples. Know which one your report uses before you compare tests.
The transaction controller options
The transaction controller has an option to generate a parent sample. When it is on, the group appears as one result with the others hidden inside. When it is off, the group’s total appears as an extra sample next to the individual samples. Another option decides whether the pauses from timers and the work of pre-processors and post-processors inside the group are counted in the total. Choose deliberately: counting the pauses gives the full user-experienced time of a journey, while leaving them out gives the pure system time.
| Setting | When on | When off |
|---|---|---|
| Generate parent sample | One combined result with children inside | Individual results plus an extra total result |
| Include timer and processor time | Total includes pauses and script work | Total is only the measured request time |
| Retrieve embedded resources | Page time includes the downloads | Only the main document is timed |
Comparing a test that retrieved embedded resources with one that did not, and concluding that the application became slower. The difference may be only the extra downloads inside the page time. Keep these settings identical across tests you want to compare.
A sub-result is like the parts of a journey inside a travel booking. The parent is “trip from home to the hotel”, and the children are the taxi, the train and the walk. You can talk about the whole trip or about each part, but you must not add the whole trip and its parts together, or you would count the same hours twice.
13Reading the Sampler Result in View Results Tree
The debugging window where most people first meet the record.
The View Results Tree listener shows each sample as an entry on the left. Selecting an entry shows its details on the right, split into tabs. The tab named Sampler Result is the one that displays the summary of the record, and the other tabs show the request and the response in detail.
Sampler Result
The summary: thread name, start time, load time, connect time, latency, sizes, counts, data type, response code, response message and response headers.
Request
What was sent: the request line, the headers and the body, with variables already replaced by their values.
Response data
What came back, shown as text, as formatted markup, as a rendered page, as structured data or as a result of a test pattern, depending on the viewer you pick.
A reliable reading routine
Check the colour and the status
Failed samples are marked in red. Open the Sampler Result tab and read the response code and message first.
Read the timings
Compare connect time, latency and load time to see which part of the journey was slow.
Open the request
Confirm the address, headers and body. Look for unreplaced variables and wrong content types.
Open the response
Read the body. Does it look like the expected page or like an error message that returned with a normal status?
Check assertion results
If a sample failed with a normal code, the failure message tells you which assertion judged it a failure and why.
View Results Tree keeps every result in memory, including full request and response data. Use it only for debugging with a handful of threads. Leaving it enabled during a real load test is one of the fastest ways to fill the memory of a load generator and ruin a run.
For long debugging sessions, configure the listener to display only errors, so the list does not fill with thousands of green entries. Searching for a failure among green results wastes time.
14Using the Sampler Result Inside the Test: Extractors, Assertions and Scripts
The result is not only for reports. The test itself reads it to make decisions.
While a test runs, other elements read the Sampler Result of the sampler they belong to, and use it to drive the next steps. This is how a script copes with changing session tokens, dynamic identifiers and conditional journeys.
Extractors read fields from the result
Extractors are post-processors that search the result and store what they find in variables. A Regular Expression Extractor, a JSON Extractor, an XPath Extractor and a Boundary Extractor can all read the response body. Many of them can also be told to read other fields of the result: the response headers, the request headers, the address, the response code or the response message. This choice is called the field to check, and it is the way to capture a token from a header or the status code into a variable for later decisions.
Scope: main sample and sub-samples
When a result has sub-results, such as embedded resources, an extractor or assertion needs to know which part to read. The scope setting offers choices: the main sample only, the sub-samples only, both, or the value of a variable. The default is the main sample only. If a value you need appears in a sub-sample, such as a redirect step, but your extractor looks only at the main sample, the extractor will quietly find nothing.
| Element | What it reads from the result | What it does with it |
|---|---|---|
| Regular Expression Extractor | Body, headers, address, code or message | Stores matched text in a variable |
| JSON Extractor | Body that holds structured data | Stores values selected by a path |
| Response Assertion | Body, headers, code, message, address or request data | Passes or fails the sample |
| Duration Assertion | Elapsed time | Fails the sample if too slow |
| Script post-processor | The whole previous result object | Custom logic, such as computing or deciding |
Script elements and the previous result
Script-based elements in JMeter can reach the whole Sampler Result of the sampler that just ran, through an object commonly called the previous result. From there a script can read any field: the code, the timings, the sizes, the headers. It can also change the result, for example to mark a sample as failed for a business reason, or to change the label. This is powerful, but it should be used sparingly, because scripts cost CPU time and can slow the generator under high thread counts.
Prefer the built-in extractors and assertions for everyday work. They are faster, easier to maintain and easier to explain to others. Keep scripts for logic that no built-in element can express.
Example: reading a token from a header
A secure service returns an access token in a response header instead of the body. The team uses an extractor with the field to check set to response headers. The token is stored in a variable that belongs to the thread, and the next request sends it back. Without this setting, the extractor would search the body, find nothing and every later request would fail.
Example: conditional journey on a status code
A script reads the response code of the log-in step. If the code shows that the session expired, the thread repeats the log-in. Otherwise it continues to the next step. The decision uses a field of the Sampler Result to make the test behave like a real user who logs in again.
15Saving Sampler Results: JTL Files, CSV, XML and Save Settings
Choosing what to keep decides what you can learn afterwards.
During a real test, results should be written to a file as they are produced. This file is commonly called a JTL file. The command-line option for the results file is the standard way to produce it in non-GUI mode. After the test, tools and the report generator read this file to produce tables and graphs.
CSV or XML
JMeter can save results as comma-separated rows or as XML records. The CSV format is compact and fast, and it is the default in recent versions and the one most analysis tools expect. The XML format can hold full request and response data and nested sub-results with more structure, but it is much larger and slower to write. For load tests, CSV with a carefully chosen set of fields is usually the right choice. XML is useful for short debugging runs where you need every detail.
CSV format
- Small files and fast writing
- Opens in spreadsheet and analysis tools
- Works directly with the HTML report generator
- Ideal for long and heavy tests
XML format
- Much larger files
- More memory and CPU to write
- Harder to analyse at scale
- Best kept for short debugging runs
Choosing which fields to save
The set of saved fields is controlled by settings in the JMeter properties file or in the configuration window of a listener. The defaults cover the essentials. You can add fields you need and remove those you do not. Adding the response data or the headers makes files much larger, and the load generator must hold and write all that data. Saving only failed samples with full details, while saving a light record for every sample, is a common compromise.
Essential timing and status
Timestamp, elapsed time, label, response code, response message, success flag and failure message. Almost every analysis needs these.
Detail timings and sizes
Latency, connect time, idle time, bytes and sent bytes. They explain where time and bandwidth went.
Concurrency fields
Thread name, group threads and all threads. They connect speed to the number of active users.
Bodies and headers
Response data and headers are heavy and can hold sensitive data. Save them for failures or short runs, not for every sample.
Overwriting the results file of a previous run, or appending a new test to an old file. Both ruin the analysis. Give every run its own results file and folder, named with the date and a short description of the test.
Add a header row to CSV files and keep the same set of fields across tests. Consistent files let you compare tests with the same tools and the same scripts, and they let new team members understand old results without guessing.
16From Samples to Statistics: How Reports Use Sampler Results
Every number in a report is a calculation over many small records.
Listeners like the Summary Report, the Aggregate Report and the HTML dashboard take thousands of Sampler Results and group them, usually by label. For each group they calculate familiar statistics. Knowing exactly which field feeds which statistic lets you judge whether a number deserves your trust.
| Statistic | Calculated from | How to read it |
|---|---|---|
| Samples | Count of results per label | How many times the step ran |
| Average | Mean of elapsed time | A rough centre, easily pulled by slow outliers |
| Median | Middle value of elapsed time | What a typical request experienced |
| 90, 95, 99 percent lines | Elapsed time at that rank | What the slowest tenth, twentieth or hundredth experienced |
| Minimum and maximum | Lowest and highest elapsed time | The extremes, useful for spotting spikes |
| Error percent | Share of results with the success flag false | How often the step failed |
| Throughput | Count of results divided by test time | How many requests were completed per second |
| Received and sent rate | Bytes fields divided by test time | How much network traffic was used |
Percentiles tell the truth about slow users
The average hides the tail. If ninety-five requests take one second and five take twenty seconds, the average is nearly two seconds, but one in twenty users waited twenty seconds. The ninety-fifth and ninety-ninth percentile lines expose this. Always read the percentile lines before the average, and always report them next to it.
The garbage-in rule
Statistics cannot fix bad samples. If the success flag is wrong because nobody asserted on content, the error percentage is wrong. If the label is unstable, the groups are wrong. If the timestamp is not synchronised across machines, the timeline is wrong. If ramp-up samples are mixed with steady-state samples, the averages are wrong. Check the quality of the samples before you believe the summary.
flowchart LR
A["Thousands of Sampler Results"] --> B["Group by label"]
B --> C["Filter out ramp-up and ramp-down periods"]
C --> D["Calculate average, percentiles, errors, throughput"]
D --> E["Tables and graphs in the report"]
The HTML report generator can filter which labels and which time range are included. Use it to exclude the ramp-up and ramp-down, so the figures describe the steady period, and to exclude helper samplers, such as set-up steps, that do not represent user actions.
17The Cost of Sampler Results: Memory, CPU and Disk on the Load Generator
Every result has a price, and a heavy test pays it thousands of times per second.
It is easy to forget that each Sampler Result is a real object living in the memory of the load generator. With a few threads this is invisible. With hundreds of threads sending many requests per second, the total weight becomes significant, and the cost of keeping, processing and writing results can slow the test tool itself.
Memory
Response bodies, headers and request data are held until all processors and listeners finish. Large bodies multiplied by many threads fill the heap quickly.
CPU
Assertions, extractors and scripts read and search the result. Heavy patterns on large bodies can burn a lot of processor time.
Disk
Writing every sample to a file takes time and space. Saving full bodies can fill a disk during a long test.
Network
In distributed tests, results travel from each worker to the controller. Heavy result traffic can overload the controller or its network link.
How to keep the cost low
Run without the graphical interface
Use command-line mode for real tests, and write results to a file. Graphical listeners keep results in memory and draw them continuously.
Remove debugging listeners
Disable or delete View Results Tree and similar listeners before load tests. Keep only a light file writer.
Save lean records
Save the essential fields for every sample and keep bodies and headers for failures only, or for short debug runs.
Use cheap checks
Prefer simple, targeted assertions to scanning large bodies with complicated patterns.
Size the heap and watch the generator
Give the JMeter process enough memory, and monitor its CPU, memory and garbage collection during every run.
If the load generator is starved of memory or processor time, requests are delayed inside JMeter itself, and the elapsed times in the Sampler Results include delays that the application never caused. A heavy result-handling set-up can therefore make a healthy application look slow.
Imagine a delivery driver who must stop at every house to write a long report before moving on. The more detailed the report, the fewer parcels he delivers per hour, and the slower every delivery looks to the customer. Lean records keep the driver moving.
18Design Patterns for Labels and Result Naming
A good name today saves hours of confusion when you read results next month.
The label is the key that groups samples. Every table and graph in your report is built on it. A careful naming scheme makes reports readable and comparable. A careless one produces thousands of useless groups and makes trends invisible.
Pattern 1: order and readability
Start labels with a number that shows the order of the step in the journey, followed by a short meaningful name, such as “01 Open home page”, “02 Search product” and “03 Add to cart”. Reports then sort in the natural order of the user journey, and anyone can read them without opening the test plan.
Pattern 2: stable labels, never dynamic ones
Never put changing values, such as user identifiers or order numbers, in a label. If the label contains a variable that changes on every request, each sample creates its own group. A test with a hundred thousand requests then shows a hundred thousand rows in the report, and the load generator and the report tool both choke. Put changing values in the request, not in the name.
Pattern 3: one name per business action
Give each business action one clear name, and keep that name identical across tests and across script versions. When names change, history is lost, and you cannot compare today’s result with last month’s.
Pattern 4: separate main steps from helper steps
Some samplers are only technical helpers, such as fetching a token or setting up data. Give them a clear prefix so you can exclude them from user-facing statistics. Otherwise, your average response time mixes real user steps with internal helpers, and the average no longer describes the user experience.
Pattern 5: group embedded resources sensibly
When pages download many images and scripts, those sub-results can flood the report with rows. Use the option that places resources under their parent, or use a naming pattern that groups them, so the report focuses on business steps.
| Label style | Example | Result |
|---|---|---|
| Numbered and clear | 03 Add to cart | Sorted, readable, comparable across tests |
| Default and vague | HTTP Request 7 | Meaningless to readers, easy to confuse |
| Contains dynamic value | Open order 928374 | One group per request, huge reports, no useful statistics |
| Helper prefixed | Z Get token | Easy to exclude from user statistics |
Agree on a naming standard with your team before writing scripts, and put it in a short document. Consistent names turn a folder of old test results into a useful history that shows how the application changes over time.
19Sampler Results in Distributed Tests and Live Dashboards
Results travel, and the way they travel changes what you can see.
Results from many workers
In a distributed test, each worker machine runs the test plan and creates its own Sampler Results. These results are sent back to the controller, which collects them into one stream for the listeners and the results file. This means that the controller handles the results of every worker, and under high load it can become a bottleneck if the results are heavy or very numerous.
Sending modes
JMeter lets you choose how workers send results to the controller. The standard mode sends each sample as soon as it is ready, which gives the most live view but costs the most network and processing. Other modes send samples in batches, send summarised statistics instead of every sample, remove heavy data such as response bodies before sending, or store samples on disk and send them in the background. The right choice depends on your test size. A light mode such as batching or stripping heavy data is usually recommended for large tests, while the standard mode suits small ones.
flowchart TD
W1["Worker 1: creates Sampler Results"] --> S["Result sending mode: standard, batch or lighter"]
W2["Worker 2: creates Sampler Results"] --> S
W3["Worker 3: creates Sampler Results"] --> S
S --> C["Controller: collects all results"]
C --> F["Results file and listeners"]
Live dashboards through a backend listener
The Backend Listener sends aggregated information from the Sampler Results to an external metrics database while the test is running. Typical numbers sent are the count of samples, the average and percentile response times, the error counts and the active thread counts, grouped by label and by time interval. A dashboard tool then draws live graphs. This lets you watch the test as it happens, correlate it with server metrics on the same screen, and stop the test early if something is clearly wrong.
| Approach | Strength | Weakness |
|---|---|---|
| Results file and later report | Complete record, easy to repeat analysis | You see the story only after the test |
| Backend listener and live dashboard | Live view next to server metrics | Aggregated data, not every raw sample |
| Both together | Live view plus a complete record | Slightly more set-up and a little more load |
For serious tests, use both: a lean results file as the permanent record and a backend listener for the live dashboard. The file keeps the evidence for later analysis, and the dashboard gives you the chance to react while the test is still running.
Keep the clocks of the controller, the workers and the servers synchronised. Without it, timestamps in the Sampler Results do not line up with server metrics, and a graph that should show cause and effect shows a confusing gap.
20Security and Privacy of Result Data
A Sampler Result can contain the exact secrets your application protects.
Because a Sampler Result may hold the full request and response, it can contain passwords, access tokens, cookies, personal details and business data. A results file or a screenshot from the debugging window is therefore sensitive material, even if the test used only test accounts. The risk is real: result files are often attached to emails, uploaded to shared drives and pasted into tickets.
Credentials in requests
Log-in steps send usernames and passwords. Request headers carry tokens. Saving these fields places secrets in the file.
Personal data in responses
Responses may contain names, addresses, account numbers or messages. If the test environment holds copied production data, the risk is higher.
Session cookies
Saved cookies and tokens could be reused to impersonate the test users if the environment is reachable.
Shared evidence
Screenshots, results files and reports passed around a company may reach people who should not see the content.
Protective habits
Use synthetic data
Test with fake accounts and generated data. Never run load tests with real customer details.
Save only what you need
Do not save request headers, response headers or bodies for every sample. The less you store, the less can leak.
Protect and expire result files
Store files in access-controlled locations, and delete them when they are no longer needed.
Clean before sharing
Before sending evidence outside the test team, remove or mask secrets and personal values from screenshots and extracts.
Rotate test credentials
Change test passwords and tokens after sharing evidence or after a large test, so that anything that leaked becomes useless.
Treat a results file that contains request and response data like a password file. If it would be a problem for an outsider to read the content of your application’s real traffic, it is a problem if they read this file.
21Anti-patterns That Corrupt Your Results
Mistakes that make the Sampler Results lie, or make you misread them.
Problem
The team trusts the status code alone, with no content check on any important step.
Why It’s Harmful
Applications often return a normal code with an error message in the content. The success flag stays true, the error rate shows zero, and real failures stay hidden until users complain.
Correct Approach
Add a cheap assertion to every key step that proves the business action worked, such as an order number or a welcome message.
Problem
View Results Tree and other heavy listeners stay enabled during a load test.
Why It’s Harmful
Memory fills with full requests and responses, garbage collection freezes threads, and the elapsed times include delays from the test tool itself.
Correct Approach
Use debugging listeners only with a few threads. For load tests, run in command-line mode and write a lean results file.
Problem
Dynamic values such as user identifiers or order numbers are placed in sampler labels.
Why It’s Harmful
Each request becomes its own group, reports explode in size, memory is wasted on thousands of group records, and no meaningful statistics exist for any step.
Correct Approach
Use stable, numbered labels. Keep changing values in the request, not in the name.
Problem
The report uses the average response time as the main figure and nothing else.
Why It’s Harmful
Slow outliers hide inside the average. A step with a healthy average may still leave one in twenty users waiting many seconds.
Correct Approach
Report the median and the ninetieth, ninety-fifth and ninety-ninth percentile lines, together with the error percent and throughput.
Problem
Ramp-up samples, steady-state samples and helper-step samples are mixed in one summary.
Why It’s Harmful
Ramp-up results describe a changing load, and helper steps do not represent user actions. The mix gives a figure that describes nothing real.
Correct Approach
Filter the report to the steady period and exclude helper samples, using clear labels and the report filters.
Problem
Result files containing request and response data are emailed and uploaded without cleaning.
Why It’s Harmful
Passwords, tokens and personal data leak to people who should not see them, and the test turns into a security incident.
Correct Approach
Save lean records, store files in protected places, mask evidence before sharing, and rotate test credentials after large tests.
22Best Practices and Real-World Examples
A checklist you can apply tomorrow, and four stories that show it working.
Best-practice checklist
Inspect real samples first
Run with one or two threads and read a few full Sampler Results before any large test.
Assert on content
Make sure every key step has a cheap content check, so the success flag means something.
Name labels carefully
Use numbered, stable labels and a clear prefix for helper steps.
Save lean, plan your fields
Choose the saved fields before the run. Use CSV, and keep bodies and headers for failures or debug runs.
Read all timing clocks
Keep connect time and latency in the file and use them to locate where time was spent.
Report percentiles and steady state
Filter out ramp periods, and report percentiles with errors and throughput.
Protect the generator and the data
Run in command-line mode, watch the generator’s health and protect result files.
Keep history
Name result files by date and test type, keep the same fields across runs, and compare releases over time.
Real-world stories
Retail checkout with hidden failures
A retailer saw a clean report before a sale. Opening individual Sampler Results showed that checkout pages returned a normal code with a message about a busy payment service. After the team added a content check on the order confirmation, the true error rate was visible, the payment service was fixed, and the sale ran smoothly.
Slow log-in explained by connect time
A bank’s log-in looked slow in tests. Latency was fine, but connect time was high. The cause was a secure handshake repeated on every request because connection reuse was off in the test configuration. Fixing the setting cut the elapsed time in half, and the application code had not been the problem.
Memory crash from saved bodies
An engineer ran a four-hour test with response bodies saved for every sample. After two hours the load generator ran out of memory and the test stopped. Switching to a lean result file with bodies saved only for failures made the same test finish with plenty of headroom.
One broken thread among hundreds
A test showed a small but steady error rate. Grouping failed Sampler Results by thread name revealed that only a few threads were failing, all with locked test accounts. Cleaning the test data removed the errors, saving the team from chasing a problem that did not exist in the application.
23Sampler Results for Non-HTTP Samplers
The same record, filled in differently for databases, messages, sockets and scripts.
Most examples in this guide use web requests, but JMeter can test many other things: database queries, message queues, file transfers, directory services, raw network sockets and custom scripts. All of them create Sampler Results with the same set of fields. What changes is how each sampler fills those fields. Understanding these differences stops you from misreading results when you leave the world of web pages.
Database query sampler
The elapsed time covers running the query and fetching the result. The response data holds the returned rows as text. There is no web status code, so the sampler uses its own simple success or failure values.
Messaging samplers
Sending a message and waiting for a reply are measured as separate kinds of samples. The elapsed time may show only the time to hand the message to the broker, not the time until a consumer processed it.
Raw network sampler
Sends bytes over a connection and reads until a chosen end condition or a timeout. The elapsed time includes the wait for that end condition, so a wrong end setting inflates the time.
Script-based sampler
A script decides what to measure and can fill the result fields itself: the label, the status, the data and the success flag. It gives freedom, but also puts the responsibility for correct measurement on you.
Debug sampler
Creates a result whose data lists the current variables and properties. It is a handy way to inspect what a thread holds at a given moment, but it should be removed or disabled before real load.
Flow control steps
Steps that only change the flow of the test, such as skipping to the next loop, are not real requests and do not produce results of their own.
What to check when you leave HTTP
Find out what the elapsed time covers
Read the documentation of the sampler to learn exactly where the clock starts and stops. A database sampler and a messaging sampler measure very different things under the same name.
Do not expect latency and connect time to mean the same
For many non-web samplers, connect time is zero or latency equals the elapsed time. That is normal, not an error.
Define success yourself
Without an HTTP status family, the default success rule may be weak. Add assertions on the returned data, such as a number of rows or a specific field value.
Watch the size of returned data
A query that returns a huge number of rows costs memory in the result and time to transfer. Limit rows in the test query to what a real user would receive.
Name samples by business action
“Load customer profile” is a better label than the name of a table or queue. Reports should speak the language of the business.
Measuring only the time to send a message and reporting it as the time to complete a business process. The user waits for the whole process, not just the hand-over. If the real process includes a consumer, design a test that measures the time until the effect is visible.
Posting a letter and receiving the reply are two different events. A stopwatch that stops when the letter drops into the postbox tells you how fast you walked to the postbox, not how fast the other person answered. The sampler’s own definition of “done” decides what your stopwatch measures.
Example: database sample with a weak success rule
A team tested a reporting query and saw all samples green with fast times. Later they found that under load the query returned zero rows because of a timeout in a lower layer, but the sampler treated an empty result as success. Adding a check on the minimum number of rows exposed the failures.
24Advanced Result Analysis: Asking Better Questions of the Data
A results file is a small database. The value comes from the questions you ask it.
Once a test is finished, the results file holds the full story of the run in thousands or millions of rows. Standard reports answer the usual questions, but expert engineers go further. They slice the data by time, by label, by thread and by response code to answer sharper questions. The following ideas turn raw Sampler Results into real insight.
| Question | Fields to combine | What you learn |
|---|---|---|
| When did the slowdown start? | Timestamp with elapsed time per time interval | The exact moment and the load level at that moment |
| At what user count does speed degrade? | All threads with elapsed time percentiles | The knee, where response time begins to climb |
| Which step is the weakest? | Label with percentiles and error percent | The step that deserves developer time first |
| Are errors random or clustered? | Timestamp, thread name, response code | Whether failures link to time, user or load |
| Is the network or the server slow? | Connect time, latency, elapsed time | Which part of the journey takes the time |
| Are responses suspiciously small? | Bytes with label and success flag | Hidden error pages that pass as success |
| Did this release get slower? | Same label across two result files | A before-and-after comparison on identical steps |
Slice by time
Group samples into small time buckets, such as every ten or thirty seconds, and calculate the percentiles, the error count and the throughput for each bucket. The result is a timeline that shows how the system behaved during the test, rather than one average for the whole run. Events such as garbage collection pauses, scheduled jobs, cache expiry and auto-scaling appear as spikes or steps on this timeline, and you can match them with server logs.
Slice by error type
Group failed samples by the full response code text and the failure message. A report that says “five percent errors” is far less useful than one that says “three percent connection timeouts, one percent service unavailable and one percent failed content checks”. Each type points to a different cause and a different owner.
Compare runs, not just numbers
The strongest use of results is comparison. Run the same test against the old and the new version and compare the percentiles per label. Make sure the settings are identical: the same thread counts, the same ramp-up, the same data and the same labels. A single run can be unlucky, because networks, caches and shared environments vary. Repeat important tests several times, and treat differences smaller than the natural variation between identical runs as noise.
Run a test three times before you announce that a release is faster or slower. If the three runs give very different figures, the environment is unstable, and the first job is to stabilise it, not to analyse the application.
Satisfaction scores
The HTML report includes a satisfaction score built from elapsed times, often called an Apdex score. It uses two thresholds: a lower one under which a response is called satisfying, and a higher one under which it is called tolerable. Responses above the higher threshold count as frustrating. The score combines these groups into a single number between zero and one. The thresholds are configurable, and you should set them to match what your business considers fast and acceptable, not leave the defaults without thinking.
flowchart TD
A["Raw results file"] --> B["Clean: remove ramp phases and helper labels"]
B --> C["Slice by time, label, thread and error type"]
C --> D["Compare with a baseline run"]
D --> E["Find the weak step and the load level where it breaks"]
E --> F["Report with evidence and a clear recommendation"]
Beware of missing samples
Thread-based tests send the next request only after the previous one has finished. When the server stalls for ten seconds, every thread waits, and the requests that real users would have sent during that stall never appear in the results. The results therefore under-represent slow periods, and the percentiles look better than what real visitors would feel. This effect, known as coordinated omission, is a limitation of closed-loop tests. Be aware of it when you interpret tail percentiles, and consider rate-driven test designs when your real traffic arrives independently of server speed.
Example: finding a hidden scheduled job
A team sliced their results into thirty-second buckets and saw a sharp spike in the ninety-ninth percentile every ten minutes. Matching the timestamps with server logs showed a scheduled cleanup job that locked a table. The standard report, which showed one overall percentile, had never revealed the pattern.
25Failures, Retries and Automated Pass or Fail Gates
What a thread does after a failed sample, and how teams turn results into decisions.
What happens after a failed sample
When a Sampler Result is marked as failed, the thread group decides what the thread does next. The thread can carry on with the next step, start its next loop, stop itself, stop the whole test after finishing running requests, or stop the whole test immediately. This choice shapes the load and the shape of your results. If failing threads stop themselves, then during a failure storm the number of active threads falls, the pressure on the application drops, and the system may look as if it recovered when in fact your own load faded away. For capacity tests, most teams choose to continue or to start the next loop, so the load stays steady and the failures stay visible.
A test that stops threads on error can produce a lovely recovery curve that never happened. Always compare the active threads graph with the plan. If the active count fell during the test, ask whether that fall came from errors, and whether the results after that moment still describe the load you intended.
Designing realistic retries
Real users and real clients often retry a failed action. A mobile app may retry a failed call automatically, and a person may press the button again. You can copy this behaviour with a loop controller that repeats a step while the previous sample failed. JMeter keeps a thread variable that records whether the last sample succeeded, and a controller can read it to decide whether to retry. The important rule is to keep each attempt as its own Sampler Result with a clear label, so that your report shows both the failures and the retries, rather than hiding failures behind eventual success.
| Design choice | Effect on results | When to use it |
|---|---|---|
| No retry, continue to the next step | Each failure appears once and the load stays steady | Capacity and stress tests |
| Retry with a clear label | Failures and retries both visible, load rises slightly under failure | When real clients retry automatically |
| Stop the thread on error | Load shrinks as errors grow | Short functional checks, rarely for load |
| Stop the whole test on error | Test ends at the first problem | Smoke tests that guard a pipeline |
Imagine a call centre test where each tester hangs up and goes home after the first busy signal. The phone lines look calmer and calmer, but only because the testers left. Retrying like real customers keeps the pressure on, and the busy signals remain in the record for everyone to see.
Using Sampler Results in automated gates
Many teams run short performance tests inside an automated delivery pipeline and use the results to decide whether a build may move forward. The test writes a results file, a small step reads it, calculates figures such as the ninety-fifth percentile per label and the error percent, and compares them with agreed limits. If a limit is broken, the pipeline stops. This turns performance from a once-a-quarter event into a daily guard.
Agree on measurable limits
Write down limits per business step, such as a maximum ninety-fifth percentile and a maximum error percent. Vague goals cannot be automated.
Run a short, stable test
Use a small, repeatable load with a fixed ramp-up and a stable environment, so differences between runs reflect code changes rather than noise.
Read the lean results file
Calculate the statistics per label from the saved samples, excluding ramp phases and helper steps.
Compare with limits and with the previous build
Fail the stage if a limit is crossed, and flag a large change compared with the last accepted build, even if the limit is still met.
Keep the evidence
Store the results file and the report with the build, so that a failed gate can be investigated later with the same data.
Gates based on a single run can be flaky. Use a tolerance, repeat a failing test once before blocking a build, and track trends over several builds. A gate that blocks builds for random noise quickly loses the trust of the team.
Example: a quiet regression caught by a gate
A team added a nightly test with limits per label. One morning the gate failed on the search step: the ninety-fifth percentile had doubled, while the average had barely moved. The previous day’s change to a query had added a slow path for a small share of searches. Because the gate looked at the percentile and kept the evidence, the cause was found within an hour of the change.
26Troubleshooting: Symptoms, Causes and Fixes
Start from what you see in the results, and work toward the cause.
| Symptom | Likely cause | First check |
|---|---|---|
| Everything is green but users complain | No content assertions, only status codes checked | Open samples, read the body, add assertions |
| Extractor finds nothing | Wrong scope, wrong field to check or the value is in a sub-result | Scope setting and the field to check |
| Variable name appears in the request | Previous extractor failed to capture the value | Previous sample’s response and the extractor pattern |
| Strange characters in text checks | Wrong encoding | Encoding and the response header for character set |
| High elapsed time, low latency | Large response or slow network | Response size, compression and bandwidth |
| High connect time | Slow connection set-up or no connection reuse | Network path and keep-alive settings |
| Report has thousands of rows | Dynamic values in labels or many embedded resources | Label design and resource retrieval settings |
| Response data missing in the file | The save setting for response data was off | Result save configuration |
| Totals look larger than expected | Parents and children counted together | Transaction controller settings and report filters |
| Test tool crashes with out-of-memory | Heavy listeners or saved bodies | Listener list and saved fields |
| Failures all from a few threads | Bad or locked test data | Group failed samples by thread name |
A calm way to investigate
Reproduce with one thread
If the problem appears with a single thread, it is a script or application issue. If it only appears under load, think about capacity and the generator.
Open the failing sample
Read the code, the timings, the request and the response in that order.
Look at the previous sample
Many failures start one step earlier, where a value was not captured or a session was lost.
Group and count
Group failures by label, response code, thread name and time to see whether they are random, clustered or linked to a certain load level.
Change one thing at a time
Fix one suspected cause, rerun, and compare, rather than changing many settings together.
27Frequently Asked Questions
Quick answers to questions that come up in almost every project.
The sampler is the element that performs the action. The Sampler Result is the record of one run of that action, with the timings, status, sizes and data. One sampler can produce thousands of results during a test.
Elapsed time runs from the start of the request to the last byte of the response. Latency runs from the start of the request to the first byte. The difference between them is roughly the time spent downloading the response.
Because an assertion judged the content or the time to be wrong. The failure message in the result explains which assertion failed and why. A normal status code only means the server answered, not that the answer was correct.
No. Timers run before the sampler starts measuring, so their delay is not part of the elapsed time of the sample. Idle time records such pauses separately, and a transaction controller can include them in a group total if you ask it to.
By default, JMeter does not save response data, headers or request data in the results file, to protect file size and memory. You can switch on saving for these fields, but do it only for debugging or for failed samples.
It means the request failed before a normal server answer was received, for example because of a refused connection, an unknown host, a timeout or a handshake failure. The text after it names the technical problem.
CSV is better for almost all load tests because it is compact, fast and works directly with the report generator. XML is useful for short debugging runs when you need full detail and nested sub-results.
Common reasons are that the extractor reads the wrong field, such as the body instead of the headers, that its scope excludes the sub-sample where the value appears, that the pattern does not match, or that the encoding is wrong. Check these in turn.
Use the thread name saved in each result. Group failed samples by thread name to see whether failures are spread across all users or concentrated in a few, which often points to bad test data.
Yes. Memory-hungry listeners, saved bodies and heavy assertions can starve the load generator and delay requests inside JMeter, so the measured times include delays that the application did not cause.
Usually the report should count the parent result, because counting both the parent and its children double-counts the same work. Know how your report treats sub-results before you compare tests.
Only if it is lean and has been checked. Files that contain request or response data may hold passwords, tokens and personal details. Clean or mask them first, and store files in protected locations.
28Summary and Key Takeaways
The Sampler Result is the foundation of every JMeter report. It is the record created each time a sampler runs, and it carries the identity, the timings, the status, the sizes, the thread information, the request, the response and the verdicts of the assertions. Extractors and assertions read it during the test, listeners display and save it, and reports turn thousands of them into statistics. If the records are rich, correct and lean, then your report is trustworthy and your debugging is fast. If they are thin, misleading or heavy, the report can be wrong while looking perfectly professional.
Key Takeaways
- One run, one record — every sampler run creates one Sampler Result, and all reports are built from these records.
- Read all the clocks — elapsed time, latency, connect time and idle time together show where time was spent.
- Status code is not success — use content assertions so that the success flag reflects real business success.
- Know the order of events — timers run before sampling, assertions after extractors, and listeners last, which explains many surprises.
- Mind sub-results and scope — redirects, embedded resources and transactions nest results, and extractors only read the scope you choose.
- Save lean and safe — choose fields before the run, prefer CSV, keep bodies for failures only, and protect result files.
- Report with percentiles and stable labels — filter to the steady period, use numbered stable labels, and never trust the average alone.