mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
http release fixes
This commit is contained in:
parent
3fa89ebc14
commit
71195d0a0b
@ -11,7 +11,6 @@ import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
public class ReadyHttpOp implements LongFunction<HttpOp> {
|
||||
@ -69,27 +68,29 @@ public class ReadyHttpOp implements LongFunction<HttpOp> {
|
||||
builder.uri(uri);
|
||||
}
|
||||
|
||||
Set<String> headers = cmd.keySet();
|
||||
for (String header : headers) {
|
||||
if (header.charAt(0) >= 'A' && header.charAt(0) <= 'Z') {
|
||||
builder.header(header, cmd.remove(header));
|
||||
} else {
|
||||
throw new BasicError("HTTP request parameter '" + header + "' was not recognized as a basic request parameter, and it is not capitalized to indicate that it is a header.");
|
||||
}
|
||||
}
|
||||
|
||||
String ok_status = cmd.remove("ok-status");
|
||||
String ok_body = cmd.remove("ok-body");
|
||||
|
||||
String timeoutStr = cmd.remove("timeout");
|
||||
if (timeoutStr!=null) {
|
||||
if (timeoutStr != null) {
|
||||
builder.timeout(Duration.of(Long.parseLong(timeoutStr), ChronoUnit.MILLIS));
|
||||
}
|
||||
|
||||
if (cmd.size()>0) {
|
||||
throw new BasicError("Some provided request fields were not used: " + cmd.toString());
|
||||
// At this point, the only things left in the list must be headers,
|
||||
// but we check them for upper-case conventions as a sanity check for the user
|
||||
for (String headerName : cmd.keySet()) {
|
||||
if (headerName.charAt(0) >= 'A' && headerName.charAt(0) <= 'Z') {
|
||||
String headerValue = cmd.get(headerName);
|
||||
builder = builder.header(headerName, headerValue);
|
||||
} else {
|
||||
throw new BasicError("HTTP request parameter '" + headerName + "' was not recognized as a basic request parameter, and it is not capitalized to indicate that it is a header.");
|
||||
}
|
||||
}
|
||||
|
||||
// cmd.clear();
|
||||
// if (cmd.size()>0) {
|
||||
// throw new BasicError("Some provided request fields were not used: " + cmd.toString());
|
||||
// }
|
||||
//
|
||||
HttpRequest request = builder.build();
|
||||
return new HttpOp(request, ok_status, ok_body);
|
||||
}
|
||||
|
@ -73,18 +73,18 @@ public class HttpAction implements SyncAction {
|
||||
|
||||
try (Timer.Context bindTime = httpActivity.bindTimer.time()) {
|
||||
ReadyHttpOp readHTTPOperation = httpActivity.getSequencer().get(cycleValue);
|
||||
httpOp =readHTTPOperation.apply(cycleValue);
|
||||
httpOp = readHTTPOperation.apply(cycleValue);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("while binding request in cycle " + cycleValue + ": " + e.getMessage(),e);
|
||||
} finally {
|
||||
if (httpActivity.isDiagnosticMode()) {
|
||||
System.out.println("==== cycle " + cycleValue + " DIAGNOSTICS ====");
|
||||
if (httpOp!=null) {
|
||||
httpActivity.console.summarizeRequest(httpOp.request,System.out,cycleValue);
|
||||
if (httpOp != null) {
|
||||
httpActivity.console.summarizeRequest("ERRORED REQUEST", e, httpOp.request, System.out, cycleValue,
|
||||
System.nanoTime());
|
||||
} else {
|
||||
System.out.println("---- REQUEST was null");
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("while binding request in cycle " + cycleValue + ": " + e.getMessage(), e);
|
||||
} finally {
|
||||
}
|
||||
|
||||
int tries = 0;
|
||||
@ -123,7 +123,7 @@ public class HttpAction implements SyncAction {
|
||||
}
|
||||
if (httpActivity.isDiagnosticMode()) {
|
||||
if (response!=null) {
|
||||
httpActivity.console.summarizeResponse(response,System.out,cycleValue,nanos);
|
||||
httpActivity.console.summarizeResponseChain(null, response, System.out, cycleValue, nanos);
|
||||
} else {
|
||||
System.out.println("---- RESPONSE was null");
|
||||
}
|
||||
|
@ -14,9 +14,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.http.HttpClient;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class HttpActivity extends SimpleActivity implements Activity, ActivityDefObserver {
|
||||
@ -45,7 +42,6 @@ public class HttpActivity extends SimpleActivity implements Activity, ActivityDe
|
||||
this.activityDef = activityDef;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initActivity() {
|
||||
super.initActivity();
|
||||
@ -65,15 +61,18 @@ public class HttpActivity extends SimpleActivity implements Activity, ActivityDe
|
||||
@Override
|
||||
public synchronized void onActivityDefUpdate(ActivityDef activityDef) {
|
||||
super.onActivityDefUpdate(activityDef);
|
||||
String[] diag = getParams().getOptionalString("diag").orElse("").split(",");
|
||||
Set<String> diags = new HashSet<String>(Arrays.asList(diag));
|
||||
this.console = new HttpConsoleFormats(diags);
|
||||
|
||||
this.console = getParams().getOptionalString("diag")
|
||||
.map(s -> HttpConsoleFormats.apply(s, this.console))
|
||||
.orElseGet(() -> HttpConsoleFormats.apply(null, null));
|
||||
|
||||
this.diagnosticsEnabled = console.isDiagnosticMode();
|
||||
|
||||
this.timeout = getParams().getOptionalLong("timeout").orElse(Long.MAX_VALUE);
|
||||
|
||||
getParams().getOptionalString("client_scope")
|
||||
.map(ClientScope::valueOf)
|
||||
.ifPresent(this::setClientScope);
|
||||
.map(ClientScope::valueOf)
|
||||
.ifPresent(this::setClientScope);
|
||||
|
||||
}
|
||||
|
||||
@ -104,14 +103,14 @@ public class HttpActivity extends SimpleActivity implements Activity, ActivityDe
|
||||
|
||||
public HttpClient newClient() {
|
||||
HttpClient.Builder builder = HttpClient.newBuilder();
|
||||
getParams().getOptionalString("follow_redirects")
|
||||
HttpClient.Redirect follow_redirects = getParams().getOptionalString("follow_redirects")
|
||||
.map(String::toUpperCase)
|
||||
.map(HttpClient.Redirect::valueOf)
|
||||
.map(r -> {
|
||||
logger.debug("follow_redirects=>" + r);
|
||||
return r;
|
||||
})
|
||||
.ifPresent(builder::followRedirects);
|
||||
}).orElse(HttpClient.Redirect.NORMAL);
|
||||
builder = builder.followRedirects(follow_redirects);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -5,81 +5,252 @@ import java.net.http.HttpClient;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class HttpConsoleFormats {
|
||||
|
||||
private final Set<String> includes;
|
||||
private final long modulo;
|
||||
private static final String CYCLE_CUE = "==== ";
|
||||
private static final String REQUEST_CUE = " ==> ";
|
||||
private static final String RESPONSE_CUE = " <== ";
|
||||
private static final String MESSAGE_CUE = "---- ";
|
||||
private static final String COMPONENT_CUE = " === ";
|
||||
private static final String DETAIL_CUE = " - ";
|
||||
private static final String ENTRY_CUE = " - ";
|
||||
private static final String PAYLOAD_CUE = "data:";
|
||||
|
||||
private final long mask;
|
||||
private final long modulo;
|
||||
private final String enabled;
|
||||
private String filter;
|
||||
|
||||
public String getFilter() {
|
||||
return this.filter;
|
||||
}
|
||||
|
||||
private final static long _STATS = 1L;
|
||||
private final static long _REQUESTS = 1L << 1;
|
||||
private final static long _RESPONSES = 1L << 2;
|
||||
private final static long _HEADERS = 1L << 3;
|
||||
private final static long _REDIRECTS = 1L << 4;
|
||||
private final static long _DATA = 1L << 5;
|
||||
private final static long _DATA10 = 1L << 6;
|
||||
private final static long _DATA100 = 1L << 7;
|
||||
private final static long _DATA1000 = 1L << 8;
|
||||
|
||||
enum Diag {
|
||||
|
||||
headers(_HEADERS),
|
||||
stats(_STATS),
|
||||
data(_DATA),
|
||||
data10(_DATA10),
|
||||
data100(_DATA100),
|
||||
data1000(_DATA1000),
|
||||
redirects(_REDIRECTS),
|
||||
requests(_REQUESTS),
|
||||
responses(_RESPONSES),
|
||||
brief(_HEADERS | _STATS | _REQUESTS | _RESPONSES | _DATA10),
|
||||
all(_HEADERS | _STATS | _REDIRECTS | _REQUESTS | _RESPONSES | _DATA);
|
||||
|
||||
private final long mask;
|
||||
|
||||
Diag(long mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
public long addTo(long othermask) {
|
||||
return othermask | this.mask;
|
||||
}
|
||||
|
||||
public boolean includedIn(long component) {
|
||||
return (mask & component) > 0L;
|
||||
}
|
||||
|
||||
|
||||
public static boolean anyIncluded(long mask, Diag... levels) {
|
||||
for (Diag level : levels) {
|
||||
if (level.includedIn(mask)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String enabledSummary(long includedMask) {
|
||||
if (includedMask <= 0L) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Diag d : values()) {
|
||||
if ((d.mask & includedMask) == d.mask) {
|
||||
sb.append(d).append(",");
|
||||
}
|
||||
}
|
||||
sb.setLength(sb.length() - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpConsoleFormats apply(String spec, HttpConsoleFormats extant) {
|
||||
if (extant == null || (extant.getFilter() != null && !extant.getFilter().equals(spec))) {
|
||||
return new HttpConsoleFormats(spec);
|
||||
} else {
|
||||
return extant;
|
||||
}
|
||||
}
|
||||
|
||||
private HttpConsoleFormats(String spec) {
|
||||
Set<String> filterSet = Set.of();
|
||||
if (spec != null) {
|
||||
filterSet = new HashSet<>(Arrays.asList(spec.split(",")));
|
||||
}
|
||||
|
||||
public HttpConsoleFormats(Set<String> includes) {
|
||||
long mod = 1L;
|
||||
Set<String> incl = new HashSet<>();
|
||||
long mask = 0L;
|
||||
|
||||
for (String include : includes) {
|
||||
for (String include : filterSet) {
|
||||
if (include.matches("[0-9]+")) {
|
||||
mod = Long.parseLong(include);
|
||||
} else if (include.toLowerCase().equals("all")) {
|
||||
incl.add("headers");
|
||||
incl.add("stats");
|
||||
incl.add("content");
|
||||
} {
|
||||
incl.add(include);
|
||||
} else {
|
||||
Diag diag = null;
|
||||
try {
|
||||
diag = Diag.valueOf(include);
|
||||
mask = diag.addTo(mask);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Invalid http diagnostic filter '" + include + "', choose from " +
|
||||
Arrays.toString(Diag.values()));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
this.includes = incl;
|
||||
this.mask = mask;
|
||||
this.modulo = mod;
|
||||
this.enabled = Diag.enabledSummary(mask);
|
||||
}
|
||||
|
||||
public void summarizeRequest(HttpRequest request, PrintStream out, long cycle) {
|
||||
if ((cycle%modulo)!=0) {
|
||||
public void summarizeResponseChain(Exception e, HttpResponse<String> lastResponse, PrintStream out, long cycle, long nanos) {
|
||||
if ((cycle % modulo) != 0) {
|
||||
return;
|
||||
}
|
||||
out.println("---- REQUEST cycle=" + cycle);
|
||||
out.println(" --- " + request.method() + " " + request.uri() + " " + request.version().orElse(HttpClient.Version.HTTP_2));
|
||||
|
||||
if (includes.contains("headers")) {
|
||||
out.println(" -- headers:");
|
||||
summariseHeaders(request.headers(),out);
|
||||
out.println(CYCLE_CUE + "DIAGNOSTICS (cycle " + cycle + ") (filters " + enabled + ")");
|
||||
|
||||
LinkedList<HttpResponse<String>> responses = new LinkedList<>();
|
||||
HttpResponse<String> walking = lastResponse;
|
||||
|
||||
while (lastResponse != null) {
|
||||
responses.add(lastResponse);
|
||||
lastResponse = lastResponse.previousResponse().orElse(null);
|
||||
}
|
||||
|
||||
out.println(" -- body length:" + request.bodyPublisher().get().contentLength());
|
||||
}
|
||||
|
||||
public void summarizeResponse(HttpResponse<String> response, PrintStream out, long cycle, long nanos) {
|
||||
if ((cycle%modulo)!=0) {
|
||||
return;
|
||||
}
|
||||
out.println("---- RESPONSE for cycle=" + cycle + " status=" + response.statusCode() + " took=" + (nanos/1_000_000) + "ms");
|
||||
|
||||
if (includes.contains("stats")) {
|
||||
int redirects=0;
|
||||
Optional<HttpResponse<String>> walkResponses = response.previousResponse();
|
||||
while (walkResponses.isPresent()) {
|
||||
walkResponses=walkResponses.get().previousResponse();
|
||||
redirects++;
|
||||
Iterator<HttpResponse<String>> iter = responses.descendingIterator();
|
||||
int index = 0;
|
||||
while (iter.hasNext()) {
|
||||
index++;
|
||||
HttpResponse<String> resp = iter.next();
|
||||
if (Diag.requests.includedIn(mask) && (Diag.redirects.includedIn(mask) || index == 1)) {
|
||||
summarizeRequest("REQUEST [" + index + "]", null, resp.request(), out, cycle, nanos);
|
||||
}
|
||||
System.out.println(" redirects = " + redirects);
|
||||
}
|
||||
|
||||
summariseHeaders(response.headers(),out);
|
||||
if (Diag.stats.includedIn(mask) && index == 1) {
|
||||
out.println(DETAIL_CUE + "redirects = " + (responses.size() - 1));
|
||||
}
|
||||
|
||||
if (this.includes.contains("content")) {
|
||||
System.out.println(" -- body:");
|
||||
System.out.println(response.body());
|
||||
if (Diag.responses.includedIn(mask) && (Diag.redirects.includedIn(mask) || index == responses.size())) {
|
||||
summarizeResponse("RESPONSE[" + index + "]", null, resp, out, cycle, nanos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void summariseHeaders(HttpHeaders headers, PrintStream out) {
|
||||
out.println(" --- headers:");
|
||||
headers.map().forEach((k,v) -> {
|
||||
out.print(" --- " + k + ":");
|
||||
if (v.size()>1) {
|
||||
public void summarizeRequest(String caption, Exception e, HttpRequest request, PrintStream out, long cycle, long nanos) {
|
||||
if ((cycle % modulo) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
out.println(REQUEST_CUE + (caption != null ? caption : " REQUEST"));
|
||||
|
||||
if (e != null) {
|
||||
out.println(CYCLE_CUE + " EXCEPTION: " + e.getMessage());
|
||||
}
|
||||
|
||||
out.println(COMPONENT_CUE + request.method() + " " + request.uri() + " " + request.version().orElse(HttpClient.Version.HTTP_2));
|
||||
summariseHeaders(request.headers(), out);
|
||||
out.println(DETAIL_CUE + "body length:" + request.bodyPublisher().get().contentLength());
|
||||
}
|
||||
|
||||
public void summarizeResponse(String caption, Exception e, HttpResponse<String> response, PrintStream out, long cycle, long nanos) {
|
||||
if ((cycle % modulo) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
out.println(RESPONSE_CUE + (caption != null ? caption : " RESPONSE") +
|
||||
" status=" + response.statusCode() + " took=" + (nanos / 1_000_000) + "ms");
|
||||
|
||||
if (e != null) {
|
||||
out.println(MESSAGE_CUE + " EXCEPTION: " + e.getMessage());
|
||||
}
|
||||
|
||||
summariseHeaders(response.headers(), out);
|
||||
summarizeContent(response, out);
|
||||
|
||||
}
|
||||
|
||||
private void summarizeContent(HttpResponse<String> response, PrintStream out) {
|
||||
if (Diag.anyIncluded(mask, Diag.data, Diag.data10, Diag.data100, Diag.data1000)) {
|
||||
|
||||
String contentLenStr = response.headers().map().getOrDefault("content-length", List.of("0")).get(0);
|
||||
Long contentLength = Long.parseLong(contentLenStr);
|
||||
if (contentLength == 0L) {
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println(PAYLOAD_CUE);
|
||||
List<String> contentTypeList = response.headers().map().getOrDefault("content-type", List.of("text/html"));
|
||||
String printable = "<non-printable>";
|
||||
if (contentTypeList.size() > 1) {
|
||||
printable = "non-printable/multiple content types provided";
|
||||
} else {
|
||||
String contentType = contentTypeList.get(0).toLowerCase();
|
||||
if (!contentType.contains("text") && !contentType.contains("json")) {
|
||||
printable = "non-printable content type:" + contentTypeList.get(0);
|
||||
} else {
|
||||
printable = response.body();
|
||||
if (printable == null) {
|
||||
printable = "content-length was " + contentLength + ", but body was null";
|
||||
}
|
||||
|
||||
if (Diag.data1000.includedIn(mask)) {
|
||||
if (printable.length() > 1000) {
|
||||
printable = printable.substring(0, 1000) + "\n--truncated at 1000 characters--\n";
|
||||
}
|
||||
} else if (Diag.data100.includedIn(mask)) {
|
||||
if (printable.length() > 100) {
|
||||
printable = printable.substring(0, 100) + "\ntruncated at 100 characters\n";
|
||||
}
|
||||
} else if (Diag.data10.includedIn(mask)) {
|
||||
if (printable.length() > 10) {
|
||||
printable = printable.substring(0, 10) + "\ntruncated at 10 characters\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(printable);
|
||||
}
|
||||
}
|
||||
|
||||
private void summariseHeaders(HttpHeaders headers, PrintStream out) {
|
||||
if (!Diag.headers.includedIn(mask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
out.println(COMPONENT_CUE + "headers(" + headers.map().keySet().size() + ")");
|
||||
headers.map().forEach((k, v) -> {
|
||||
out.print(DETAIL_CUE + k + ":");
|
||||
if (v.size() > 1) {
|
||||
out.println();
|
||||
v.forEach( h -> {
|
||||
out.println(" - " + h);
|
||||
v.forEach(h -> {
|
||||
out.println(ENTRY_CUE + h);
|
||||
});
|
||||
} else {
|
||||
out.println(" " + v.get(0));
|
||||
@ -88,6 +259,6 @@ public class HttpConsoleFormats {
|
||||
}
|
||||
|
||||
public boolean isDiagnosticMode() {
|
||||
return this.includes.size()>0;
|
||||
return this.mask > 0L;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,9 @@ statements:
|
||||
- s2: https://www.amazon.com/s?k={query}
|
||||
ratio: 2
|
||||
bindings:
|
||||
query: WeightedStrings('function generator;backup generator;static generator');
|
||||
query: >
|
||||
WeightedStrings('function generator;backup generator;static generator');
|
||||
UrlEncode();
|
||||
```
|
||||
|
||||
You can even make a detailed request with custom headers and result verification conditions:
|
||||
@ -43,12 +45,13 @@ You can even make a detailed request with custom headers and result verification
|
||||
```yaml
|
||||
# Require that the result be status code 200-299 match regex "OK, account id is .*" in the body
|
||||
statements:
|
||||
- method: GET
|
||||
uri: https://google.com/
|
||||
version: HTTP/1.1
|
||||
"Content-Type": "application/json"
|
||||
ok-status: 2[0-9][0-9]
|
||||
ok-body: ^(OK, account id is .*)$
|
||||
- name: 'get-from-google'
|
||||
method: GET
|
||||
uri: "https://google.com/"
|
||||
version: "HTTP/1.1"
|
||||
Content-Type: "application/json"
|
||||
ok-status: "2[0-9][0-9]"
|
||||
ok-body: "^(OK, account id is .*)$"
|
||||
```
|
||||
|
||||
For those familiar with what an HTTP request looks like on the wire, the format below may be
|
||||
@ -163,19 +166,53 @@ results. Support may be added for long-lived connections in a future release.
|
||||
- **client_scope** - default: activity - One of activity, or thread. This controls how many
|
||||
clients instances you use with an HTTP activity. By default, all threads will use the same
|
||||
client instance.
|
||||
- **follow_redirects** - default: normal - One of never, always, or normal. Normal redirects
|
||||
|
||||
- **follow_redirects** - default: normal - One of never, always, or
|
||||
normal. Normal redirects
|
||||
are those which do not redirect from HTTPS to HTTP.
|
||||
- **diagnostics** - default: none -
|
||||
This setting is a selector for what level of verbosity you will get on console. If you set
|
||||
this to true, you'll get every request and response logged to console. This is only for
|
||||
verifying that a test is configured and to spot check services before running higher scale
|
||||
|
||||
- **diagnostics** - default: none - synonym: **diag**
|
||||
example: `diag=brief,1000` - print diagnostics for every 1000th
|
||||
cycle, including only brief details as explained below.
|
||||
|
||||
This setting is a selector for what level of verbosity you will get
|
||||
on the console. If you set this to true, you'll get every request
|
||||
and response logged to console. This is only for verifying that a test
|
||||
is configured and to spot check services before running higher scale
|
||||
tests.
|
||||
If you want finer control over how much information diagnostics provides, you can specify
|
||||
a comma separated list of the below.
|
||||
- all - Includes all of the below categories
|
||||
- stats - Counts of redirects, headers, body length, etc
|
||||
- headers - include header details
|
||||
- content - include
|
||||
- a number, like 3000 - causes the diagnostics to be reported only on this cycle modulo
|
||||
|
||||
All of the data shown in diagnostics is post-hoc, directly from
|
||||
the response provided by the internal HTTP client in the Java runtime.
|
||||
|
||||
If you want finer control over how much information diagnostics
|
||||
provides, you can specify a comma separated list of the below.
|
||||
|
||||
- headers - show headers
|
||||
- stats - show basic stats of each request
|
||||
- data10 - show only the first 10 characters of each response body
|
||||
- data100 - show only the first 100 characters of each response body
|
||||
this setting supersedes `data10`
|
||||
- data1000 - show only the first 1000 characters of each response body
|
||||
this setting supersedes `data100`
|
||||
- data - show all of each response body
|
||||
this setting supersedes `data1000`
|
||||
- redirects - show details for interstitial request which are made
|
||||
when the client follows a redirect directive like a `location` header.
|
||||
- requests - show details for requests
|
||||
- responses - show details for responses
|
||||
- brief - Show headers, stats, requests, responses, and 10 characters
|
||||
- all - Show everything, including full payloads and redirects
|
||||
- a modulo - any number, like 3000 - causes the diagnostics to be
|
||||
reported only on this cycle modulo. If you set `diag=300,brief`
|
||||
then you will get the brief diagnostic output for every 300th
|
||||
response.
|
||||
|
||||
The requests, responses, and redirects setting work intersectionally.
|
||||
For example, if you specify responses, and redirect, but not requests,
|
||||
then you will only see the response portion of all calls made by the
|
||||
client.
|
||||
|
||||
All of the diagnostic filters are incrementally added.
|
||||
|
||||
- **timeout** - default: forever -
|
||||
Sets the timeout of each request in milliseconds.
|
||||
|
@ -1,8 +1,10 @@
|
||||
# A list of named statements with variable fields and specific ratios:
|
||||
statements:
|
||||
- s1: http://google.com/search?query={query}
|
||||
- s1: "http://google.com/search?query={query}"
|
||||
ratio: 3
|
||||
- s2: https://www.amazon.com/s?k={query}
|
||||
- s2: "https://www.amazon.com/s?k={query}"
|
||||
ratio: 2
|
||||
bindings:
|
||||
query: WeightedStrings('function generator;backup generator;static generator');
|
||||
query: >
|
||||
WeightedStrings('function generator;backup generator;static generator');
|
||||
URLEncode();
|
||||
|
@ -1,8 +1,9 @@
|
||||
# Require that the result be status code 200-299 match regex "OK, account id is .*" in the body
|
||||
statements:
|
||||
- method: GET
|
||||
uri: https://google.com/
|
||||
version: HTTP/1.1
|
||||
"Content-Type": "application/json"
|
||||
ok-status: 2[0-9][0-9]
|
||||
ok-body: ^(OK, account id is .*)$
|
||||
- name: 'get-from-google'
|
||||
method: GET
|
||||
uri: "https://google.com/"
|
||||
version: "HTTP/1.1"
|
||||
Content-Type: "application/json"
|
||||
ok-status: "2[0-9][0-9]"
|
||||
ok-body: "^(OK, account id is .*)$"
|
||||
|
@ -76,7 +76,9 @@ public class MultiMapLookup<V> implements Map<String, V> {
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
throw immutable();
|
||||
V result = get(key);
|
||||
maps.stream().forEach(m -> m.remove(String.valueOf(key)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,41 @@
|
||||
package io.nosqlbench.virtdata.library.basics.shared.unary_string;
|
||||
|
||||
import io.nosqlbench.virtdata.api.annotations.Categories;
|
||||
import io.nosqlbench.virtdata.api.annotations.Category;
|
||||
import io.nosqlbench.virtdata.api.annotations.Example;
|
||||
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
|
||||
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* URLDecode string data
|
||||
*/
|
||||
@ThreadSafeMapper
|
||||
@Categories({Category.conversion})
|
||||
public class URLDecode implements Function<String, String> {
|
||||
|
||||
private final Charset charset;
|
||||
|
||||
/**
|
||||
* URLDecode any incoming string using the specified charset.
|
||||
*
|
||||
* @param charset A valid character set name from {@link Charset}
|
||||
*/
|
||||
@Example({"URLDecode('UTF-16')", "URLDecode using the UTF-16 charset."})
|
||||
public URLDecode(String charset) {
|
||||
this.charset = Charset.forName(charset);
|
||||
}
|
||||
|
||||
@Example({"URLDecode()", "URLDecode using the default UTF-8 charset."})
|
||||
public URLDecode() {
|
||||
this.charset = StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(String s) {
|
||||
return URLDecoder.decode(s, charset);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package io.nosqlbench.virtdata.library.basics.shared.unary_string;
|
||||
|
||||
import io.nosqlbench.virtdata.api.annotations.Categories;
|
||||
import io.nosqlbench.virtdata.api.annotations.Category;
|
||||
import io.nosqlbench.virtdata.api.annotations.Example;
|
||||
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* URLEncode string data
|
||||
*/
|
||||
@ThreadSafeMapper
|
||||
@Categories({Category.conversion})
|
||||
public class URLEncode implements Function<String, String> {
|
||||
|
||||
private final Charset charset;
|
||||
|
||||
/**
|
||||
* UrlEncode any incoming string using the specified charset.
|
||||
*
|
||||
* @param charset A valid character set name from {@link Charset}
|
||||
*/
|
||||
@Example({"URLEncode('UTF-16')", "URLEncode using the UTF-16 charset."})
|
||||
public URLEncode(String charset) {
|
||||
this.charset = Charset.forName(charset);
|
||||
}
|
||||
|
||||
@Example({"URLEncode()", "URLEncode using the default UTF-8 charset."})
|
||||
public URLEncode() {
|
||||
this.charset = StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(String s) {
|
||||
return URLEncoder.encode(s, charset);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user