mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2024-11-25 10:10:32 -06:00
fix body diagnostics for http driver
This commit is contained in:
parent
a6e374a5f1
commit
6281c8c91d
@ -113,6 +113,7 @@ public class HttpAction implements SyncAction {
|
||||
httpActivity.resultSuccessTimer.update(nanos, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
if (httpActivity.isDiagnosticMode()) {
|
||||
httpActivity.console.summarizeRequest("request", error, httpOp.request, System.out, cycle, nanos);
|
||||
if (response != null) {
|
||||
httpActivity.console.summarizeResponseChain(error, response, System.out, cycle, nanos);
|
||||
} else {
|
||||
|
@ -40,7 +40,6 @@ public class HttpConsoleFormats {
|
||||
private final static long _DATA100 = 1L << 7;
|
||||
private final static long _DATA1000 = 1L << 8;
|
||||
|
||||
private final static Set<String> PRINTABLE_TYPES = Set.of("text","html","json","xhtml");
|
||||
enum Diag {
|
||||
|
||||
headers(_HEADERS),
|
||||
@ -180,7 +179,7 @@ public class HttpConsoleFormats {
|
||||
|
||||
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());
|
||||
out.println(DETAIL_CUE + "body length: " + request.bodyPublisher().get().contentLength());
|
||||
summarizeRequestContent(request, out);
|
||||
|
||||
}
|
||||
@ -198,12 +197,24 @@ public class HttpConsoleFormats {
|
||||
}
|
||||
|
||||
summariseHeaders(response.headers(), out);
|
||||
summarizeContent(response, out);
|
||||
summarizedResponseContent(response, out);
|
||||
|
||||
}
|
||||
|
||||
private final static Set<String> PRINTABLE = Set.of("text", "html", "json", "xhtml");
|
||||
|
||||
private void summarizeContent(HttpResponse<String> response, PrintStream out) {
|
||||
private boolean isPrintableContentType(String contentType) {
|
||||
|
||||
if (contentType == null) {
|
||||
return false;
|
||||
}
|
||||
if (contentType.toLowerCase().startsWith("text")) {
|
||||
return true;
|
||||
}
|
||||
return PRINTABLE.contains(contentType.split("/")[0].toLowerCase());
|
||||
}
|
||||
|
||||
private void summarizedResponseContent(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);
|
||||
@ -214,35 +225,36 @@ public class HttpConsoleFormats {
|
||||
|
||||
System.out.println(PAYLOAD_CUE);
|
||||
List<String> contentTypeList = response.headers().map().getOrDefault("content-type", List.of("text/html"));
|
||||
String printable = "<non-printable>";
|
||||
String toprint = "<non-printable>";
|
||||
if (contentTypeList.size() > 1) {
|
||||
printable = "non-printable/multiple content types provided";
|
||||
toprint = "non-printable/multiple content types provided";
|
||||
} else {
|
||||
String contentType = contentTypeList.get(0).toLowerCase();
|
||||
if (!PRINTABLE_TYPES.contains(contentType.toLowerCase())) {
|
||||
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 (isPrintableContentType(contentType)) {
|
||||
toprint = response.body();
|
||||
if (toprint == null) {
|
||||
toprint = "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";
|
||||
if (toprint.length() > 1000) {
|
||||
toprint = toprint.substring(0, 1000) + "\n--truncated at 1000 characters--\n";
|
||||
}
|
||||
} else if (Diag.data100.includedIn(mask)) {
|
||||
if (printable.length() > 100) {
|
||||
printable = printable.substring(0, 100) + "\n--truncated at 100 characters--\n";
|
||||
if (toprint.length() > 100) {
|
||||
toprint = toprint.substring(0, 100) + "\n--truncated at 100 characters--\n";
|
||||
}
|
||||
} else if (Diag.data10.includedIn(mask)) {
|
||||
if (printable.length() > 10) {
|
||||
printable = printable.substring(0, 10) + "\n--truncated at 10 characters--\n";
|
||||
if (toprint.length() > 10) {
|
||||
toprint = toprint.substring(0, 10) + "\n--truncated at 10 characters--\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toprint = "non-printable content type:" + contentTypeList.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
System.out.println(printable);
|
||||
System.out.println(toprint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,74 +263,85 @@ public class HttpConsoleFormats {
|
||||
if (request.bodyPublisher().isEmpty()) {
|
||||
sb.append(PAYLOAD_CUE).append("\n--no body publisher is defined for this request--\n");
|
||||
} else {
|
||||
String charset = "UTF-8";
|
||||
String contentType = "text/html";
|
||||
List<String> contentTypeHeaders = request.headers().allValues("content-type");
|
||||
if (contentTypeHeaders.size()==0) {
|
||||
sb.append("\n--WARNING: content-type header assumed as 'text/html; charset=UTF-8--\n");
|
||||
} else if (contentTypeHeaders.size()>1) {
|
||||
sb.append("--non-printable/multiple content types provided--");
|
||||
} else {
|
||||
String cth = contentTypeHeaders.get(0);
|
||||
String[] fields = cth.split("; *",2);
|
||||
switch(fields.length) {
|
||||
case 2: charset = fields[1].split("=")[1].trim();
|
||||
case 1: contentType = fields[0].trim();
|
||||
}
|
||||
HttpRequest.BodyPublisher publisher = request.bodyPublisher().get();
|
||||
long contentLength = publisher.contentLength();
|
||||
if (contentLength > 0) {
|
||||
String charset = "UTF-8";
|
||||
String contentType = "text/html";
|
||||
List<String> contentTypeHeaders = request.headers().allValues("content-type");
|
||||
|
||||
if (!PRINTABLE_TYPES.contains(contentType.toLowerCase())) {
|
||||
sb.append("--non-printable content type:").append(contentType).append("--");
|
||||
if (contentTypeHeaders.size() == 0) {
|
||||
sb.append(DETAIL_CUE).append("BODY (WARNING: content-type header MISSING, assumed as 'text/html; charset=UTF-8)\n");
|
||||
} else if (contentTypeHeaders.size() > 1) {
|
||||
sb.append(DETAIL_CUE).append("BODY is non-printable or multiple content types provided\n");
|
||||
} else {
|
||||
HttpRequest.BodyPublisher publisher = request.bodyPublisher().get();
|
||||
long contentLength = publisher.contentLength();
|
||||
if (contentLength > 0) {
|
||||
List<ByteBuffer> byteBuffers = new BodyReceiver()
|
||||
.subscribe(publisher)
|
||||
.awaitBuffers();
|
||||
for (ByteBuffer buf : byteBuffers) {
|
||||
sb.append(new String(buf.array(), Charset.forName(charset)));
|
||||
}
|
||||
} else {
|
||||
sb.append("\n<no-content>\n");
|
||||
String cth = contentTypeHeaders.get(0);
|
||||
String[] fields = cth.split("; *", 2);
|
||||
switch (fields.length) {
|
||||
case 2:
|
||||
charset = fields[1].split("=")[1].trim();
|
||||
case 1:
|
||||
contentType = fields[0].trim();
|
||||
}
|
||||
|
||||
sb.append(DETAIL_CUE).append("BODY (content type detected as ").append(contentType).append(")\n");
|
||||
}
|
||||
if (isPrintableContentType(contentType)) {
|
||||
List<ByteBuffer> byteBuffers = new BodyReceiver()
|
||||
.subscribe(publisher)
|
||||
.awaitBuffers();
|
||||
for (ByteBuffer buf : byteBuffers) {
|
||||
sb.append(new String(buf.array(), Charset.forName(charset)));
|
||||
}
|
||||
} else {
|
||||
sb.append("--non-printable content type:").append(contentType).append("--");
|
||||
}
|
||||
|
||||
} else {
|
||||
sb.append("\n<no-content>\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
out.println(sb);
|
||||
}
|
||||
|
||||
private final static class BodyReceiver implements Flow.Subscriber<ByteBuffer> {
|
||||
|
||||
public List<ByteBuffer> buffers = new LinkedList<>();
|
||||
public List<ByteBuffer> buffers = null;
|
||||
public List<ByteBuffer> completed = null;
|
||||
|
||||
public BodyReceiver subscribe(Flow.Publisher<ByteBuffer> flowpub) {
|
||||
public synchronized BodyReceiver subscribe(Flow.Publisher<ByteBuffer> flowpub) {
|
||||
flowpub.subscribe(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Flow.Subscription subscription) {
|
||||
public synchronized void onSubscribe(Flow.Subscription subscription) {
|
||||
buffers = new ArrayList<>();
|
||||
subscription.request(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(ByteBuffer item) {
|
||||
public synchronized void onNext(ByteBuffer item) {
|
||||
buffers.add(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
public synchronized void onError(Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onComplete() {
|
||||
completed = buffers;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized List<ByteBuffer> awaitBuffers() {
|
||||
try {
|
||||
wait();
|
||||
while (completed==null) {
|
||||
wait(1000);
|
||||
}
|
||||
return buffers;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
Loading…
Reference in New Issue
Block a user