How to Track and Record Unique Request IDs in a Java Performance Testing Framework
This article explains how to generate, propagate, and log unique request IDs across multithreaded HTTP calls in a Java performance‑testing framework, providing a MarkRequest interface, a RequestThreadTimes implementation, and a runnable demo that captures request‑ID timestamps for analysis.
During performance testing, the team needed to reproduce long‑running requests and trace them through logs using a unique requestId that spans the entire call chain, including inter‑service calls and database interactions.
Request ID Generation and Propagation
Each request receives a requestId composed of several parts with algorithms guaranteeing uniqueness. The ID is attached to the HTTP header and is used by all services and middleware to correlate logs.
MarkRequest Interface
A new Java interface MarkRequest is introduced to encapsulate the logic for adding or modifying the request ID header. The interface extends Serializable and defines a single method: public String mark(HttpRequestBase base); Implementations can remove existing headers, generate a new identifier, and add it back to the request.
Thread‑Limited Request Execution
The class RequestThreadTimes extends ThreadLimitTimesCount and manages a pool of threads that repeatedly execute a given HttpRequestBase. Key fields include: Vector<String> requestMark – stores all recorded request IDs. MarkRequest mark – the strategy for marking each request. List<String> marks – records IDs of requests that exceed the configured timeout.
The workflow for each iteration is:
Call mark.mark(request) to obtain the ID string.
Record the start timestamp, execute the request via FanLibrary.excuteSimlple(request), then record the end timestamp.
Calculate the duration; if it exceeds HttpClientConstant.MAX_ACCEPT_TIME, store the duration and ID in marks.
Update counters and break early if a stop condition is met.
After all threads finish, the collected IDs are saved to a file using Save.saveStringList.
Demo Usage
A runnable demo shows how to create an anonymous MarkRequest that removes any existing requestid header, generates a new value of the form fun_<random4chars>_<timestamp>, and adds it back to the request. The demo then creates a RequestThreadTimes instance with two executions, starts a Concurrent runner with two threads, and prints the collected request IDs.
def "Test concurrent response marking"() {
given:
HttpGet httpGet = FanLibrary.getHttpGet("https://cn.bing.com/");
MarkRequest mark = new MarkRequest() {
String m;
@Override
public String mark(HttpRequestBase base) {
base.removeHeaders("requestid");
m = m == null ? RString.getStringWithoutNum(4) : m;
String value = "fun_" + m + CONNECTOR + Time.getTimeStamp();
base.addHeader("requestid", value);
return value;
}
};
FanLibrary.getHttpResponse(httpGet);
HttpClientConstant.MAX_ACCEPT_TIME = -1;
RequestThreadTimes threadTimes = new RequestThreadTimes(httpGet, 2, mark);
new Concurrent(threadTimes, 2).start();
output(RequestThreadTimes.requestMark);
}Sample Output
80_fun_QkhQ_1578367527661
103_fun_QkhQ_1578367527742
101_fun_zwtk_1578367527661
107_fun_zwtk_1578367527763The output shows four entries, each consisting of a thread identifier, the generated random segment, and a timestamp, confirming that the request IDs are unique and can be used to group log entries per thread.
Conclusion
By defining a simple MarkRequest interface and integrating it into a multithreaded request executor, developers can reliably tag each HTTP call with a unique identifier, capture timeout events, and persist the data for later analysis, greatly simplifying performance bottleneck tracing.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
