diff options
Diffstat (limited to 'src/main/java/ch/hiddenalpha')
9 files changed, 1456 insertions, 3 deletions
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/FailFastMetricsOptions.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/FailFastMetricsOptions.java new file mode 100644 index 0000000..c911061 --- /dev/null +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/FailFastMetricsOptions.java @@ -0,0 +1,35 @@ +package ch.hiddenalpha.unspecifiedgarbage.gateleenKludge; + +import io.vertx.core.json.JsonObject; +import io.vertx.core.metrics.MetricsOptions; +import io.vertx.core.spi.VertxMetricsFactory; + + +public class FailFastMetricsOptions extends io.vertx.core.metrics.MetricsOptions { + + private final String dbgMsg; + + public FailFastMetricsOptions( String dbgMsg ){ this.dbgMsg = dbgMsg; } + + public FailFastMetricsOptions(){ this(failCtor()); } + + private FailFastMetricsOptions( MetricsOptions o ){ this(failCtor()); } + + private FailFastMetricsOptions( JsonObject json ){ this(failCtor()); } + + private static String failCtor(){ throw new IllegalStateException("Do NOT use this ctor!"); } + + @Override public boolean isEnabled(){ throw new UnsupportedOperationException(dbgMsg); } + + @Override public MetricsOptions setEnabled(boolean en){ throw new UnsupportedOperationException(dbgMsg); } + + @Override public VertxMetricsFactory getFactory(){ throw new UnsupportedOperationException(dbgMsg); } + + @Override public MetricsOptions setFactory( VertxMetricsFactory f ){ throw new UnsupportedOperationException(dbgMsg); } + + @Override public JsonObject toJson(){ throw new UnsupportedOperationException(dbgMsg); } + + @Override public String toString(){ throw new UnsupportedOperationException(dbgMsg); } + +} + diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/FailFastVertxMetricsFactory.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/FailFastVertxMetricsFactory.java new file mode 100644 index 0000000..fa0d7e1 --- /dev/null +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/FailFastVertxMetricsFactory.java @@ -0,0 +1,27 @@ +package ch.hiddenalpha.unspecifiedgarbage.gateleenKludge; + +import io.vertx.core.VertxOptions; +import io.vertx.core.impl.VertxBuilder; +import io.vertx.core.json.JsonObject; +import io.vertx.core.metrics.MetricsOptions; +import io.vertx.core.spi.metrics.VertxMetrics; + + +public class FailFastVertxMetricsFactory implements io.vertx.core.spi.VertxMetricsFactory { + + private final String dbgMsg; + + public FailFastVertxMetricsFactory(String dbgMsg ){ this.dbgMsg = dbgMsg; } + + @Override public void init(VertxBuilder b) { throw new UnsupportedOperationException(dbgMsg); } + + @Override public VertxMetrics metrics(VertxOptions o){ throw new UnsupportedOperationException(dbgMsg); } + + @Override public MetricsOptions newOptions() { throw new UnsupportedOperationException(dbgMsg); } + + @Override public MetricsOptions newOptions(MetricsOptions o) { throw new UnsupportedOperationException(dbgMsg); } + + @Override public MetricsOptions newOptions(JsonObject j) { throw new UnsupportedOperationException(dbgMsg); } + +} + diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateHttpServerRequest.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateHttpServerRequest.java new file mode 100644 index 0000000..aa4ad48 --- /dev/null +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateHttpServerRequest.java @@ -0,0 +1,394 @@ +package ch.hiddenalpha.unspecifiedgarbage.gateleenKludge.tmoutissue20240123; + +import io.netty.handler.codec.DecoderResult; +import io.vertx.core.AsyncResult; +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.Cookie; +import io.vertx.core.http.HttpConnection; +import io.vertx.core.http.HttpFrame; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServerFileUpload; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.core.http.HttpVersion; +import io.vertx.core.http.ServerWebSocket; +import io.vertx.core.http.StreamPriority; +import io.vertx.core.net.NetSocket; +import io.vertx.core.net.SocketAddress; +import io.vertx.core.streams.Pipe; +import io.vertx.core.streams.WriteStream; + +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.security.cert.X509Certificate; +import java.util.Map; +import java.util.Set; + +public class DelegateHttpServerRequest implements io.vertx.core.http.HttpServerRequest { + + private final io.vertx.core.http.HttpServerRequest delegate; + private final boolean isDebugging = true; + + public DelegateHttpServerRequest(HttpServerRequest delegate) { + this.delegate = delegate; + } + + private void breakpoint(){ + try{ + throw new UnsupportedOperationException(); + }catch(UnsupportedOperationException ex){} + } + + @Override + public HttpServerRequest exceptionHandler(Handler<Throwable> handler) { + if( isDebugging ) breakpoint(); + return delegate.exceptionHandler(handler); + } + + @Override + public HttpServerRequest handler(Handler<Buffer> handler) { + if( isDebugging ) breakpoint(); + return delegate.handler(handler); + } + + @Override + public HttpServerRequest pause() { + if( isDebugging ) breakpoint(); + return delegate.pause(); + } + + @Override + public HttpServerRequest resume() { + if( isDebugging ) breakpoint(); + return delegate.resume(); + } + + @Override + public HttpServerRequest fetch(long amount) { + if( isDebugging ) breakpoint(); + return delegate.fetch(amount); + } + + @Override + public HttpServerRequest endHandler(Handler<Void> endHandler) { + if( isDebugging ) breakpoint(); + return delegate.endHandler(endHandler); + } + + @Override + public HttpVersion version() { + if( isDebugging ) breakpoint(); + return delegate.version(); + } + + @Override + public HttpMethod method() { + if( isDebugging ) breakpoint(); + return delegate.method(); + } + + @Override + public boolean isSSL() { + if( isDebugging ) breakpoint(); + return delegate.isSSL(); + } + + @Override + public String scheme() { + if( isDebugging ) breakpoint(); + return delegate.scheme(); + } + + @Override + public String uri() { + if( isDebugging ) breakpoint(); + return delegate.uri(); + } + + @Override + public String path() { + if( isDebugging ) breakpoint(); + return delegate.path(); + } + + @Override + public String query() { + if( isDebugging ) breakpoint(); + return delegate.query(); + } + + @Override + public String host() { + if( isDebugging ) breakpoint(); + return delegate.host(); + } + + @Override + public long bytesRead() { + if( isDebugging ) breakpoint(); + return delegate.bytesRead(); + } + + @Override + public HttpServerResponse response() { + if( isDebugging ) breakpoint(); + return delegate.response(); + } + + @Override + public MultiMap headers() { + if( isDebugging ) breakpoint(); + return delegate.headers(); + } + + @Override + public String getHeader(String headerName) { + if( isDebugging ) breakpoint(); + return delegate.getHeader(headerName); + } + + @Override + public String getHeader(CharSequence headerName) { + if( isDebugging ) breakpoint(); + return delegate.getHeader(headerName); + } + + @Override + public MultiMap params() { + if( isDebugging ) breakpoint(); + return delegate.params(); + } + + @Override + public String getParam(String paramName) { + if( isDebugging ) breakpoint(); + return delegate.getParam(paramName); + } + + @Override + public String getParam(String paramName, String defaultValue) { + if( isDebugging ) breakpoint(); + return delegate.getParam(paramName, defaultValue); + } + + @Override + public SocketAddress remoteAddress() { + if( isDebugging ) breakpoint(); + return delegate.remoteAddress(); + } + + @Override + public SocketAddress localAddress() { + if( isDebugging ) breakpoint(); + return delegate.localAddress(); + } + + @Override + public SSLSession sslSession() { + if( isDebugging ) breakpoint(); + return delegate.sslSession(); + } + + @Override + public X509Certificate[] peerCertificateChain() throws SSLPeerUnverifiedException { + if( isDebugging ) breakpoint(); + return delegate.peerCertificateChain(); + } + + @Override + public String absoluteURI() { + if( isDebugging ) breakpoint(); + return delegate.absoluteURI(); + } + + @Override + public HttpServerRequest bodyHandler(Handler<Buffer> bodyHandler) { + if( isDebugging ) breakpoint(); + return delegate.bodyHandler(bodyHandler); + } + + @Override + public HttpServerRequest body(Handler<AsyncResult<Buffer>> handler) { + if( isDebugging ) breakpoint(); + return delegate.body(handler); + } + + @Override + public Future<Buffer> body() { + if( isDebugging ) breakpoint(); + return delegate.body(); + } + + @Override + public void end(Handler<AsyncResult<Void>> handler) { + if( isDebugging ) breakpoint(); + delegate.end(handler); + } + + @Override + public Future<Void> end() { + if( isDebugging ) breakpoint(); + return delegate.end(); + } + + @Override + public void toNetSocket(Handler<AsyncResult<NetSocket>> handler) { + if( isDebugging ) breakpoint(); + delegate.toNetSocket(handler); + } + + @Override + public Future<NetSocket> toNetSocket() { + if( isDebugging ) breakpoint(); + return delegate.toNetSocket(); + } + + @Override + public HttpServerRequest setExpectMultipart(boolean expect) { + if( isDebugging ) breakpoint(); + return delegate.setExpectMultipart(expect); + } + + @Override + public boolean isExpectMultipart() { + if( isDebugging ) breakpoint(); + return delegate.isExpectMultipart(); + } + + @Override + public HttpServerRequest uploadHandler(Handler<HttpServerFileUpload> uploadHandler) { + if( isDebugging ) breakpoint(); + return delegate.uploadHandler(uploadHandler); + } + + @Override + public MultiMap formAttributes() { + if( isDebugging ) breakpoint(); + return delegate.formAttributes(); + } + + @Override + public String getFormAttribute(String attributeName) { + if( isDebugging ) breakpoint(); + return delegate.getFormAttribute(attributeName); + } + + @Override + public int streamId() { + if( isDebugging ) breakpoint(); + return delegate.streamId(); + } + + @Override + public void toWebSocket(Handler<AsyncResult<ServerWebSocket>> handler) { + if( isDebugging ) breakpoint(); + delegate.toWebSocket(handler); + } + + @Override + public Future<ServerWebSocket> toWebSocket() { + if( isDebugging ) breakpoint(); + return delegate.toWebSocket(); + } + + @Override + public boolean isEnded() { + if( isDebugging ) breakpoint(); + return delegate.isEnded(); + } + + @Override + public HttpServerRequest customFrameHandler(Handler<HttpFrame> handler) { + if( isDebugging ) breakpoint(); + return delegate.customFrameHandler(handler); + } + + @Override + public HttpConnection connection() { + if( isDebugging ) breakpoint(); + return delegate.connection(); + } + + @Override + public StreamPriority streamPriority() { + if( isDebugging ) breakpoint(); + return delegate.streamPriority(); + } + + @Override + public HttpServerRequest streamPriorityHandler(Handler<StreamPriority> handler) { + if( isDebugging ) breakpoint(); + return delegate.streamPriorityHandler(handler); + } + + @Override + public DecoderResult decoderResult() { + if( isDebugging ) breakpoint(); + return delegate.decoderResult(); + } + + @Override + public Cookie getCookie(String name) { + if( isDebugging ) breakpoint(); + return delegate.getCookie(name); + } + + @Override + public Cookie getCookie(String name, String domain, String path) { + if( isDebugging ) breakpoint(); + return delegate.getCookie(name, domain, path); + } + + @Override + public int cookieCount() { + if( isDebugging ) breakpoint(); + return delegate.cookieCount(); + } + + @Override + @Deprecated + public Map<String, Cookie> cookieMap() { + if( isDebugging ) breakpoint(); + return delegate.cookieMap(); + } + + @Override + public Set<Cookie> cookies(String name) { + if( isDebugging ) breakpoint(); + return delegate.cookies(name); + } + + @Override + public Set<Cookie> cookies() { + if( isDebugging ) breakpoint(); + return delegate.cookies(); + } + + @Override + public HttpServerRequest routed(String route) { + if( isDebugging ) breakpoint(); + return delegate.routed(route); + } + + @Override + public Pipe<Buffer> pipe() { + if( isDebugging ) breakpoint(); + return delegate.pipe(); + } + + @Override + public Future<Void> pipeTo(WriteStream<Buffer> dst) { + if( isDebugging ) breakpoint(); + return delegate.pipeTo(dst); + } + + @Override + public void pipeTo(WriteStream<Buffer> dst, Handler<AsyncResult<Void>> handler) { + if( isDebugging ) breakpoint(); + delegate.pipeTo(dst, handler); + } + +} diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateVertxHttpServerRequestInternal.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateVertxHttpServerRequestInternal.java new file mode 100644 index 0000000..92fe3fc --- /dev/null +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateVertxHttpServerRequestInternal.java @@ -0,0 +1,475 @@ +package ch.hiddenalpha.unspecifiedgarbage.gateleenKludge.tmoutissue20240123; + +import io.netty.handler.codec.DecoderResult; +import io.vertx.core.AsyncResult; +import io.vertx.core.Context; +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.Cookie; +import io.vertx.core.http.HttpConnection; +import io.vertx.core.http.HttpFrame; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServerFileUpload; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.core.http.HttpVersion; +import io.vertx.core.http.ServerWebSocket; +import io.vertx.core.http.StreamPriority; +import io.vertx.core.http.impl.HttpServerRequestInternal; +import io.vertx.core.net.NetSocket; +import io.vertx.core.net.SocketAddress; +import io.vertx.core.streams.Pipe; +import io.vertx.core.streams.WriteStream; +import org.slf4j.Logger; + +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.security.cert.X509Certificate; +import java.util.Map; +import java.util.Set; + +import static org.slf4j.LoggerFactory.getLogger; + +public class DelegateVertxHttpServerRequestInternal implements HttpServerRequestInternal { + + private static final Logger log = getLogger(DelegateVertxHttpServerRequestInternal.class); + private final HttpServerRequestInternal delegate; + private final boolean isDebugging = true; + private final String dbgHint; + + public DelegateVertxHttpServerRequestInternal(String debugHint, HttpServerRequest delegate) { + log.trace("{}: new DelegateVertxHttpServerRequestInternal()", debugHint); + this.delegate = (HttpServerRequestInternal) delegate; + this.dbgHint = debugHint; + } + + private void breakpoint(){ + try{ + throw new UnsupportedOperationException(); + }catch(UnsupportedOperationException ex){} + } + + @Override + public HttpServerRequest exceptionHandler(Handler<Throwable> handler) { + log.trace("{}: exceptionHandler(Hdlr<Ex>)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.exceptionHandler(handler); + } + + @Override + public HttpServerRequest handler(Handler<Buffer> handler) { + log.trace("{}: handler(Hdlr<Buf>)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.handler(handler); + } + + @Override + public HttpServerRequest pause() { + log.trace("{}: pause()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.pause(); + } + + @Override + public HttpServerRequest resume() { + log.trace("{}: resume()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.resume(); + } + + @Override + public HttpServerRequest fetch(long amount) { + log.trace("{}: fetch({})", dbgHint, amount); + if( isDebugging ) breakpoint(); + return delegate.fetch(amount); + } + + @Override + public HttpServerRequest endHandler(Handler<Void> endHandler) { + log.trace("{}: endHandler(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.endHandler(endHandler); + } + + @Override + public HttpVersion version() { + log.trace("{}: version()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.version(); + } + + @Override + public HttpMethod method() { + log.trace("{}: method()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.method(); + } + + @Override + public boolean isSSL() { + log.trace("{}: isSSL()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.isSSL(); + } + + @Override + public String scheme() { + log.trace("{}: scheme()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.scheme(); + } + + @Override + public String uri() { + log.trace("{}: uri()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.uri(); + } + + @Override + public String path() { + log.trace("{}: path()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.path(); + } + + @Override + public String query() { + log.trace("{}: query()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.query(); + } + + @Override + public String host() { + log.trace("{}: host()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.host(); + } + + @Override + public long bytesRead() { + log.trace("{}: bytesRead()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.bytesRead(); + } + + @Override + public HttpServerResponse response() { + log.trace("{}: response()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.response(); + } + + @Override + public MultiMap headers() { + log.trace("{}: headers()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.headers(); + } + + @Override + public String getHeader(String headerName) { + log.trace("{}: getHeader(\"{}\")", dbgHint, headerName); + if( isDebugging ) breakpoint(); + return delegate.getHeader(headerName); + } + + @Override + public String getHeader(CharSequence headerName) { + log.trace("{}: getHeader(\"{}\")", dbgHint, headerName); + if( isDebugging ) breakpoint(); + return delegate.getHeader(headerName); + } + + @Override + public MultiMap params() { + log.trace("{}: params()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.params(); + } + + @Override + public String getParam(String paramName) { + log.trace("{}: getParam(\"{}\")", dbgHint, paramName); + if( isDebugging ) breakpoint(); + return delegate.getParam(paramName); + } + + @Override + public String getParam(String paramName, String defaultValue) { + log.trace("{}: getParam(\"{}\", \"{}\")", dbgHint, paramName, defaultValue); + if( isDebugging ) breakpoint(); + return delegate.getParam(paramName, defaultValue); + } + + @Override + public SocketAddress remoteAddress() { + log.trace("{}: remoteAddress()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.remoteAddress(); + } + + @Override + public SocketAddress localAddress() { + log.trace("{}: localAddress()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.localAddress(); + } + + @Override + public SSLSession sslSession() { + log.trace("{}: sslSession()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.sslSession(); + } + + @Override + public X509Certificate[] peerCertificateChain() throws SSLPeerUnverifiedException { + log.trace("{}: peerCertificateChain()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.peerCertificateChain(); + } + + @Override + public String absoluteURI() { + log.trace("{}: absoluteURI()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.absoluteURI(); + } + + @Override + public HttpServerRequest bodyHandler(Handler<Buffer> bodyHandler) { + log.trace("{}: bodyHandler(Hdlr<Buf>)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.bodyHandler(bodyHandler); + } + + @Override + public HttpServerRequest body(Handler<AsyncResult<Buffer>> handler) { + log.trace("{}: body(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.body(handler); + } + + @Override + public Future<Buffer> body() { + log.trace("{}: body(void)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.body(); + } + + @Override + public void end(Handler<AsyncResult<Void>> handler) { + log.trace("{}: end(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + delegate.end(handler); + } + + @Override + public Future<Void> end() { + log.trace("{}: end(void)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.end(); + } + + @Override + public void toNetSocket(Handler<AsyncResult<NetSocket>> handler) { + log.trace("{}: toNetSocket(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + delegate.toNetSocket(handler); + } + + @Override + public Future<NetSocket> toNetSocket() { + log.trace("{}: toNetSocket(void)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.toNetSocket(); + } + + @Override + public HttpServerRequest setExpectMultipart(boolean expect) { + log.trace("{}: toNetSocket({})", dbgHint, expect); + if( isDebugging ) breakpoint(); + return delegate.setExpectMultipart(expect); + } + + @Override + public boolean isExpectMultipart() { + log.trace("{}: isExpectMultipart()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.isExpectMultipart(); + } + + @Override + public HttpServerRequest uploadHandler(Handler<HttpServerFileUpload> uploadHandler) { + log.trace("{}: uploadHandler(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.uploadHandler(uploadHandler); + } + + @Override + public MultiMap formAttributes() { + log.trace("{}: formAttributes()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.formAttributes(); + } + + @Override + public String getFormAttribute(String attributeName) { + log.trace("{}: getFormAttribute(\"{}\")", dbgHint, attributeName); + if( isDebugging ) breakpoint(); + return delegate.getFormAttribute(attributeName); + } + + @Override + public int streamId() { + log.trace("{}: streamId()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.streamId(); + } + + @Override + public void toWebSocket(Handler<AsyncResult<ServerWebSocket>> handler) { + log.trace("{}: toWebSocket(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + delegate.toWebSocket(handler); + } + + @Override + public Future<ServerWebSocket> toWebSocket() { + log.trace("{}: toWebSocket()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.toWebSocket(); + } + + @Override + public boolean isEnded() { + log.trace("{}: isEnded()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.isEnded(); + } + + @Override + public HttpServerRequest customFrameHandler(Handler<HttpFrame> handler) { + log.trace("{}: customFrameHandler(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.customFrameHandler(handler); + } + + @Override + public HttpConnection connection() { + log.trace("{}: connection()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.connection(); + } + + @Override + public StreamPriority streamPriority() { + log.trace("{}: streamPriority()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.streamPriority(); + } + + @Override + public HttpServerRequest streamPriorityHandler(Handler<StreamPriority> handler) { + log.trace("{}: streamPriorityHandler(Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.streamPriorityHandler(handler); + } + + @Override + public DecoderResult decoderResult() { + log.trace("{}: decoderResult()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.decoderResult(); + } + + @Override + public Cookie getCookie(String name) { + log.trace("{}: getCookie(\"{}\")", dbgHint, name); + if( isDebugging ) breakpoint(); + return delegate.getCookie(name); + } + + @Override + public Cookie getCookie(String name, String domain, String path) { + log.trace("{}: getCookie(\"{}\", Str, Str)", dbgHint, name); + if( isDebugging ) breakpoint(); + return delegate.getCookie(name, domain, path); + } + + @Override + public int cookieCount() { + log.trace("{}: cookieCount()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.cookieCount(); + } + + @Override + @Deprecated + public Map<String, Cookie> cookieMap() { + log.trace("{}: cookieMap()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.cookieMap(); + } + + @Override + public Set<Cookie> cookies(String name) { + log.trace("{}: cookies(\"{}\")", dbgHint, name); + if( isDebugging ) breakpoint(); + return delegate.cookies(name); + } + + @Override + public Set<Cookie> cookies() { + log.trace("{}: cookies(void)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.cookies(); + } + + @Override + public HttpServerRequest routed(String route) { + log.trace("{}: routed(\"{}\")", dbgHint, route); + if( isDebugging ) breakpoint(); + return delegate.routed(route); + } + + @Override + public Pipe<Buffer> pipe() { + log.trace("{}: pipe()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.pipe(); + } + + @Override + public Future<Void> pipeTo(WriteStream<Buffer> dst) { + log.trace("{}: pipeTo(WrStrm<Buf>)", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.pipeTo(dst); + } + + @Override + public void pipeTo(WriteStream<Buffer> dst, Handler<AsyncResult<Void>> handler) { + log.trace("{}: pipeTo(WrStrm<Buf>,Hdlr)", dbgHint); + if( isDebugging ) breakpoint(); + delegate.pipeTo(dst, handler); + } + + @Override + public Context context() { + log.trace("{}: context()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.context(); + } + + @Override + public Object metric() { + log.trace("{}: metric()", dbgHint); + if( isDebugging ) breakpoint(); + return delegate.metric(); + } + +} diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateVertxHttpServerResponse.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateVertxHttpServerResponse.java new file mode 100644 index 0000000..87ce5a9 --- /dev/null +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/DelegateVertxHttpServerResponse.java @@ -0,0 +1,111 @@ +package ch.hiddenalpha.unspecifiedgarbage.gateleenKludge.tmoutissue20240123; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.Cookie; +import io.vertx.core.http.HttpFrame; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.core.http.StreamPriority; +import io.vertx.core.streams.ReadStream; +import org.slf4j.Logger; + +import java.util.Set; + +import static org.slf4j.LoggerFactory.getLogger; + +public class DelegateVertxHttpServerResponse implements HttpServerResponse { + + private static final Logger log = getLogger(DelegateVertxHttpServerResponse.class); + private final HttpServerResponse delegate; + private final String dbgHint; + + public DelegateVertxHttpServerResponse(String debugHint, HttpServerResponse delegate) { + this.dbgHint = debugHint; + this.delegate = delegate; + } + + @Override public HttpServerResponse exceptionHandler(Handler<Throwable> handler) { log.trace("{}: exceptionHandler()", dbgHint); return delegate.exceptionHandler(handler); } + @Override public HttpServerResponse setWriteQueueMaxSize(int maxSize) { log.trace("{}: setWriteQueueMaxSize()", dbgHint); return delegate.setWriteQueueMaxSize(maxSize); } + @Override public HttpServerResponse drainHandler(Handler<Void> handler) { log.trace("{}: drainHandler()", dbgHint); return delegate.drainHandler(handler); } + @Override public int getStatusCode() { log.trace("{}: getStatusCode()", dbgHint); return delegate.getStatusCode(); } + @Override public HttpServerResponse setStatusCode(int statusCode) { log.trace("{}: setStatusCode()", dbgHint); return delegate.setStatusCode(statusCode); } + @Override public String getStatusMessage() { log.trace("{}: getStatusMessage()", dbgHint); return delegate.getStatusMessage(); } + @Override public HttpServerResponse setStatusMessage(String statusMessage) { log.trace("{}: setStatusMessage()", dbgHint); return delegate.setStatusMessage(statusMessage); } + @Override public HttpServerResponse setChunked(boolean chunked) { log.trace("{}: setChunked()", dbgHint); return delegate.setChunked(chunked); } + @Override public boolean isChunked() { log.trace("{}: isChunked()", dbgHint); return delegate.isChunked(); } + @Override public MultiMap headers() { log.trace("{}: headers()", dbgHint); return delegate.headers(); } + @Override public HttpServerResponse putHeader(String name, String value) { log.trace("{}: putHeader(Str,Str)", dbgHint); return delegate.putHeader(name, value); } + @Override public HttpServerResponse putHeader(CharSequence name, CharSequence value) { log.trace("{}: putHeader(ChrSeq,ChrSeq)", dbgHint); return delegate.putHeader(name, value); } + @Override public HttpServerResponse putHeader(String name, Iterable<String> values) { log.trace("{}: putHeader(Str,Iter<Str>)", dbgHint); return delegate.putHeader(name, values); } + @Override public HttpServerResponse putHeader(CharSequence name, Iterable<CharSequence> values) { log.trace("{}: putHeader(ChrSeq,Iter<ChrSeq>)", dbgHint); return delegate.putHeader(name, values); } + @Override public MultiMap trailers() { log.trace("{}: trailers()", dbgHint); return delegate.trailers(); } + @Override public HttpServerResponse putTrailer(String name, String value) { log.trace("{}: putTrailer(Str,Str)", dbgHint); return delegate.putTrailer(name, value); } + @Override public HttpServerResponse putTrailer(CharSequence name, CharSequence value) { log.trace("{}: putTrailer(ChrSeq,ChrSeq)", dbgHint); return delegate.putTrailer(name, value); } + @Override public HttpServerResponse putTrailer(String name, Iterable<String> values) { log.trace("{}: putTrailer(Str,Iter<Str>)", dbgHint); return delegate.putTrailer(name, values); } + @Override public HttpServerResponse putTrailer(CharSequence name, Iterable<CharSequence> value) { log.trace("{}: putTrailer(ChrSeq,Iter<ChrSeq>)", dbgHint); return delegate.putTrailer(name, value); } + @Override public HttpServerResponse closeHandler(Handler<Void> handler) { log.trace("{}: closeHandler()", dbgHint); return delegate.closeHandler(handler); } + @Override public HttpServerResponse endHandler(Handler<Void> handler) { log.trace("{}: endHandler()", dbgHint); return delegate.endHandler(handler); } + @Override public Future<Void> write(String chunk, String enc) { log.trace("{}: write(Str,Str)", dbgHint); return delegate.write(chunk, enc); } + @Override public void write(String chunk, String enc, Handler<AsyncResult<Void>> handler) { log.trace("{}: write(Str,Str,Hdlr)", dbgHint); delegate.write(chunk, enc, handler); } + @Override public Future<Void> write(String chunk) { log.trace("{}: write(Str)", dbgHint); return delegate.write(chunk); } + @Override public void write(String chunk, Handler<AsyncResult<Void>> handler) { log.trace("{}: write(Str,Hdlr)", dbgHint); delegate.write(chunk, handler); } + @Override public HttpServerResponse writeContinue() { log.trace("{}: writeContinue()", dbgHint); return delegate.writeContinue(); } + @Override public Future<Void> end(String chunk) { log.trace("{}: end(Str)", dbgHint); return delegate.end(chunk); } + @Override public void end(String chunk, Handler<AsyncResult<Void>> handler) { log.trace("{}: end(Str,Hdlr)", dbgHint); delegate.end(chunk, handler); } + @Override public Future<Void> end(String chunk, String enc) { log.trace("{}: end(Str,Str)", dbgHint); return delegate.end(chunk, enc); } + @Override public void end(String chunk, String enc, Handler<AsyncResult<Void>> handler) { log.trace("{}: end(Str,Str,Hdlr)", dbgHint); delegate.end(chunk, enc, handler); } + @Override public Future<Void> end(Buffer chunk) { log.trace("{}: end(Buf)", dbgHint); return delegate.end(chunk); } + @Override public void end(Buffer chunk, Handler<AsyncResult<Void>> handler) { log.trace("{}: end(Buf,Hdlr)", dbgHint); delegate.end(chunk, handler); } + @Override public Future<Void> end() { log.trace("{}: end(void)", dbgHint); return delegate.end(); } + @Override public void send(Handler<AsyncResult<Void>> handler) { log.trace("{}: send(Hdlr)", dbgHint); delegate.send(handler); } + @Override public Future<Void> send() { log.trace("{}: send(void)", dbgHint); return delegate.send(); } + @Override public void send(String body, Handler<AsyncResult<Void>> handler) { log.trace("{}: send(Str,Hdlr)", dbgHint); delegate.send(body, handler); } + @Override public Future<Void> send(String body) { log.trace("{}: send(Str)", dbgHint); return delegate.send(body); } + @Override public void send(Buffer body, Handler<AsyncResult<Void>> handler) { log.trace("{}: send(Buf,Hdlr)", dbgHint); delegate.send(body, handler); } + @Override public Future<Void> send(Buffer body) { log.trace("{}: send(Buf)", dbgHint); return delegate.send(body); } + @Override public void send(ReadStream<Buffer> body, Handler<AsyncResult<Void>> handler) { log.trace("{}: send(RdStr<Buf>,Hdlr)", dbgHint); delegate.send(body, handler); } + @Override public Future<Void> send(ReadStream<Buffer> body) { log.trace("{}: send(RdStr<Buf>)", dbgHint); return delegate.send(body); } + @Override public Future<Void> sendFile(String filename) { log.trace("{}: sendFile(Str)", dbgHint); return delegate.sendFile(filename); } + @Override public Future<Void> sendFile(String filename, long offset) { log.trace("{}: sendFile(Str,lng)", dbgHint); return delegate.sendFile(filename, offset); } + @Override public Future<Void> sendFile(String filename, long offset, long length) { log.trace("{}: sendFile(Str,lng,lng)", dbgHint); return delegate.sendFile(filename, offset, length); } + @Override public HttpServerResponse sendFile(String filename, Handler<AsyncResult<Void>> resultHandler) { log.trace("{}: sendFile(Str,Hdlr)", dbgHint); return delegate.sendFile(filename, resultHandler); } + @Override public HttpServerResponse sendFile(String filename, long offset, Handler<AsyncResult<Void>> resultHandler) { log.trace("{}: sendFile(Str,lng,Hdlr)", dbgHint); return delegate.sendFile(filename, offset, resultHandler); } + @Override public HttpServerResponse sendFile(String filename, long offset, long length, Handler<AsyncResult<Void>> resultHandler) { log.trace("{}: sendFile(Str,lng,lng,Hdlr)", dbgHint); return delegate.sendFile(filename, offset, length, resultHandler); } + @Override public void close() { log.trace("{}: close()", dbgHint); delegate.close(); } + @Override public boolean ended() { log.trace("{}: ended()", dbgHint); return delegate.ended(); } + @Override public boolean closed() { log.trace("{}: closed()", dbgHint); return delegate.closed(); } + @Override public boolean headWritten() { log.trace("{}: headWritten()", dbgHint); return delegate.headWritten(); } + @Override public HttpServerResponse headersEndHandler(Handler<Void> handler) { log.trace("{}: headersEndHandler()", dbgHint); return delegate.headersEndHandler(handler); } + @Override public HttpServerResponse bodyEndHandler(Handler<Void> handler) { log.trace("{}: bodyEndHandler()", dbgHint); return delegate.bodyEndHandler(handler); } + @Override public long bytesWritten() { log.trace("{}: bytesWritten()", dbgHint); return delegate.bytesWritten(); } + @Override public int streamId() { log.trace("{}: streamId()", dbgHint); return delegate.streamId(); } + @Override public HttpServerResponse push(HttpMethod method, String host, String path, Handler<AsyncResult<HttpServerResponse>> handler) { log.trace("{}: push(Mthd,Str,Str,Hdlr)", dbgHint); return delegate.push(method, host, path, handler); } + @Override public Future<HttpServerResponse> push(HttpMethod method, String host, String path) { log.trace("{}: push(Mthd,Str,Str)", dbgHint); return delegate.push(method, host, path); } + @Override public HttpServerResponse push(HttpMethod method, String path, MultiMap headers, Handler<AsyncResult<HttpServerResponse>> handler) { log.trace("{}: push(Mthd,Str,Map,Hdlr)", dbgHint); return delegate.push(method, path, headers, handler); } + @Override public Future<HttpServerResponse> push(HttpMethod method, String path, MultiMap headers) { log.trace("{}: push(Mthd,Str,Map)", dbgHint); return delegate.push(method, path, headers); } + @Override public HttpServerResponse push(HttpMethod method, String path, Handler<AsyncResult<HttpServerResponse>> handler) { log.trace("{}: push(Mthd,Str,Hdlr)", dbgHint); return delegate.push(method, path, handler); } + @Override public Future<HttpServerResponse> push(HttpMethod method, String path) { log.trace("{}: push(Mthd,Str)", dbgHint); return delegate.push(method, path); } + @Override public HttpServerResponse push(HttpMethod method, String host, String path, MultiMap headers, Handler<AsyncResult<HttpServerResponse>> handler) { log.trace("{}: push(Mthd,Str,Str,Map,Hdlr)", dbgHint); return delegate.push(method, host, path, headers, handler); } + @Override public Future<HttpServerResponse> push(HttpMethod method, String host, String path, MultiMap headers) { log.trace("{}: push(Mthd,Str,Str,Map)", dbgHint); return delegate.push(method, host, path, headers); } + @Override public boolean reset() { log.trace("{}: reset(void)", dbgHint); return delegate.reset(); } + @Override public boolean reset(long code) { log.trace("{}: reset({})", dbgHint, code); return delegate.reset(code); } + @Override public HttpServerResponse writeCustomFrame(int type, int flags, Buffer payload) { log.trace("{}: writeCustomFrame({}, {}, Buf)", dbgHint, type, flags); return delegate.writeCustomFrame(type, flags, payload); } + @Override public HttpServerResponse writeCustomFrame(HttpFrame frame) { log.trace("{}: writeCustomFrame()", dbgHint); return delegate.writeCustomFrame(frame); } + @Override public HttpServerResponse setStreamPriority(StreamPriority streamPriority) { log.trace("{}: setStreamPriority()", dbgHint); return delegate.setStreamPriority(streamPriority); } + @Override public HttpServerResponse addCookie(Cookie cookie) { log.trace("{}: addCookie()", dbgHint); return delegate.addCookie(cookie); } + @Override public Cookie removeCookie(String name) { log.trace("{}: removeCookie({})", dbgHint, name); return delegate.removeCookie(name); } + @Override public Cookie removeCookie(String name, boolean invalidate) { log.trace("{}: removeCookie({}, {})", dbgHint, name, invalidate); return delegate.removeCookie(name, invalidate); } + @Override public Set<Cookie> removeCookies(String name) { log.trace("{}: removeCookies({})", dbgHint, name); return delegate.removeCookies(name); } + @Override public Set<Cookie> removeCookies(String name, boolean invalidate) { log.trace("{}: removeCookies({}, {})", dbgHint, name, invalidate); return delegate.removeCookies(name, invalidate); } + @Override public Cookie removeCookie(String name, String domain, String path) { log.trace("{}: removeCookie({}, Str, Str)", dbgHint, name); return delegate.removeCookie(name, domain, path); } + @Override public Cookie removeCookie(String name, String domain, String path, boolean invalidate) { log.trace("{}: removeCookie({}, Str, Str, {})", dbgHint, name, invalidate); return delegate.removeCookie(name, domain, path, invalidate); } + @Override public Future<Void> write(Buffer data) { log.trace("{}: write(Buf)", dbgHint); return delegate.write(data); } + @Override public void write(Buffer data, Handler<AsyncResult<Void>> handler) { log.trace("{}: write(Buf, Hdlr)", dbgHint); delegate.write(data, handler); } + @Override public void end(Handler<AsyncResult<Void>> handler) { log.trace("{}: end(Hdlr)", dbgHint); delegate.end(handler); } + @Override public boolean writeQueueFull() { log.trace("{}: writeQueueFull()", dbgHint); return delegate.writeQueueFull(); } + +} diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/Foo.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/Foo.java new file mode 100644 index 0000000..8295088 --- /dev/null +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/Foo.java @@ -0,0 +1,131 @@ +package ch.hiddenalpha.unspecifiedgarbage.gateleenKludge.tmoutissue20240123; + +import io.vertx.core.http.HttpServerRequest; +import io.vertx.ext.web.RoutingContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.lang.System.currentTimeMillis; + + +public class Foo { + + private static final Logger log = Foo.getLogger(Foo.class); + private static final boolean assertRequestEquality = false; + private static HttpServerRequest serverInfoRequest; + private static io.vertx.core.http.impl.HttpServerRequestInternal restStorageEvBusAdaptMappdHttpServReq; + private static long onBeginRouteEpochMs; + + public static synchronized void onNewServerInfoRequst(HttpServerRequest request){ + if( !isServerInfoRequst(request) ) return; + //assert serverInfoRequest == null; + log.trace("onNewServerInfoRequst()"); + serverInfoRequest = request; + } + + public static void downReqBegin(HttpServerRequest req) { + if( !isServerInfoRequst(req) ) return; + log.trace("downReqBegin()"); + assert !assertRequestEquality || serverInfoRequest == req; + } + + public static void downReqAuthorized(HttpServerRequest req) { + if( !isServerInfoRequst(req) ) return; + log.trace("downReqAuthorized()"); + assert !assertRequestEquality || serverInfoRequest == req; + } + + public static void onBeforeMainVerticleRouteGeneric(HttpServerRequest req) { + if( !isServerInfoRequst(req) ) return; + log.trace("onBeforeMainVerticleRouteGeneric()"); + onBeginRouteEpochMs = currentTimeMillis(); + assert !assertRequestEquality || serverInfoRequest == req; + } + + public static Logger getLogger(Class<?> clazz) { + assert clazz != null; + return getLogger(clazz.getName()); + } + + public static Logger getLogger(String name) { + assert name != null; + return LoggerFactory.getLogger("FOO."+ name); + } + + public static boolean isServerInfoRequst(HttpServerRequest request) { + return isServerInfoRequst(request.uri()); + } + + private static boolean isServerInfoRequst(String uri) { + assert uri != null; + assert uri.startsWith("/"); + try{ + if( "/houston/server/info".equals(uri) ){ + //log.trace("true <- isServerInfoRequst({})", uri); + return true; + } + //log.trace("false <- isServerInfoRequst({})", uri); + return false; + }catch(Throwable ex){ + assert false; + throw ex; + } + } + + public static void onBeforeEvBusAdapterDataHandler(String uri) { + if( !isServerInfoRequst(uri) ) return; + log.trace("onBeforeEvBusAdapterDataHandler({})", uri); + assert false; + } + + public static void onBeforeEvBusAdapterEndHandler(String uri) { + if( !isServerInfoRequst(uri)) return; + log.trace("onBeforeEvBusAdapterEndHandler({})", uri); + assert false; + } + + public static void onEvBusAdapterHandle(io.vertx.core.http.impl.HttpServerRequestInternal req) { + if( !isServerInfoRequst(req.uri()) ) return; + assert !assertRequestEquality || serverInfoRequest != req; + assert restStorageEvBusAdaptMappdHttpServReq == null; + log.trace("onEvBusAdapterHandle({})", req.uri()); + restStorageEvBusAdaptMappdHttpServReq = req; + } + + public static void onEvBusAdapterError(Throwable ex) { + log.error("onEvBusAdapterError()", new Exception("stacktrace", ex)); + } + + public static void onRestStorageHandlerHandle(HttpServerRequest req) { + if( !isServerInfoRequst(req) ) return; + log.trace("onRestStorageHandlerHandle({})", req.uri()); + assert !assertRequestEquality || serverInfoRequest == req; + } + + public static void onRestStorageHandler_getResource(io.vertx.ext.web.RoutingContext ctx) { + if( !isServerInfoRequst(ctx.request()) ) return; + assert !assertRequestEquality || serverInfoRequest == ctx.request(); + log.trace("onRestStorageHandler_getResource({})", ctx.request().uri()); + } + + public static void onRestStorageHandler_getResource_before_storage_get(String path, int offset, int limit) { + //log.trace("onRestStorageHandler_getResource_before_storage_get({}, {}, {})", path, offset, limit); + } + + public static void onRestStorageHandler_getResource_after_storage_get(String path, int offset, int limit, Object/*org.swisspush.reststorage.Resource*/ resource) { + //log.trace("onRestStorageHandler_getResource_after_storage_get({})", path); + } + + public static void onGetHoustonServerInfo(RoutingContext ctx) { + var req = ctx.request(); + log.trace("onGetHoustonServerInfo({})", req.uri()); + assert !assertRequestEquality || serverInfoRequest != req; + } + + public static void onEndCompleted(long responseBegEpochMs){ + long nowEpochMs = currentTimeMillis(); + log.debug("Request took {}ms and {}ms", nowEpochMs - onBeginRouteEpochMs, nowEpochMs - responseBegEpochMs); + } + +} + diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/HoustonInfoRequestTracer.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/HoustonInfoRequestTracer.java new file mode 100644 index 0000000..a011c7f --- /dev/null +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/gateleenKludge/tmoutissue20240123/HoustonInfoRequestTracer.java @@ -0,0 +1,265 @@ +package ch.hiddenalpha.unspecifiedgarbage.gateleenKludge.tmoutissue20240123; + +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.http.HttpServerResponse; +import org.slf4j.Logger; + +import java.lang.reflect.Field; +import java.util.NoSuchElementException; + +import static java.lang.System.currentTimeMillis; +import static org.slf4j.LoggerFactory.getLogger; + + +/** + * <p>This class got introduced to trace timings of "/houston/server/info" + * requests. It is optimized for exactly this purpose AND NOTHING ELSE! It was + * introduced because SDCISA-13746 is only observable on PROD. It does not + * reproduce locally, and not even on TEST, INT or PREPROD. So we do not really + * have another choice but tracing down this bug directly on PROD itself. + * Unluckily it is not that simple to do so. First debugging/testing on PROD env + * always has some risk. Plus, also our feedback-loop is terribly slow due to our + * heavyweight deployment process. So to be able to see if this code actually does + * what it should, we likely have to wait up to SEVERAL MONTHS.</p> + */ +public class HoustonInfoRequestTracer implements org.swisspush.gateleen.core.debug.InfoRequestTracer { + + private static final Logger log = getLogger(HoustonInfoRequestTracer.class); + private static final String INFO_URI = "/houston/server/info"; + private static final int MAX_REQUESTS = 8; /*WARN: do NOT go too high*/ + private static final Long NO_VALUE = Long.MIN_VALUE / 2; + private static final Class<?> wrapperClazz; + private static final Field delegateField; + private static final int + FLG_WritingHttpResponseHasReturned = 1 << 0, + FLG_WritingHttpResponseEnd = 1 << 1, + FLG_slotIsBusy = 1 << 2; + private final int requestDurationBailTresholdLowMs = 42; /* requests faster than 42 millis likely not interesting*/ + private final Object requestSlotLock = new Object(); + private final HttpServerRequest[] + requestInstances = new HttpServerRequest[MAX_REQUESTS]; + private int slotReUseOffset; + private final int[] + requestFlg = new int[MAX_REQUESTS]; + private final long[] + requestNewHttpReqEpochMs = new long[MAX_REQUESTS], + authorizerBeginMs = new long[MAX_REQUESTS], + authorizerEndMs = new long[MAX_REQUESTS], + beforeCatchallRouting = new long[MAX_REQUESTS], + responseGotRequestedMs = new long[MAX_REQUESTS], + writingResponseBeginMs = new long[MAX_REQUESTS], + writingResponseHasReturnedMs = new long[MAX_REQUESTS], + writingResponseEndMs = new long[MAX_REQUESTS], + requestDoneMs = new long[MAX_REQUESTS]; + + static { + try { + wrapperClazz = Class.forName("io.vertx.ext.web.impl.HttpServerRequestWrapper"); + delegateField = wrapperClazz.getDeclaredField("delegate"); + delegateField.setAccessible(true); + } catch (ClassNotFoundException | NoSuchFieldException ex) { + assert false : "TODO_395w8zuj"; + throw new UnsupportedOperationException(/*TODO*/"Not impl yet", ex); + } + } + + public void onNewHttpRequest(HttpServerRequest req) { + if( !isOfInterestEvenReqNotYetSeen(req) ) return; + req = unwrap(req); + int reqIdx; + synchronized (requestSlotLock){ + reqIdx = getFreeSlotIdx(); + if( reqIdx == -2 ) { + log.debug("No more space to trace yet another request"); + return; + } + assert reqIdx >= 0 && reqIdx < MAX_REQUESTS; + assert !alreadyKnowRequest(req) : "TODO what if.."; + requestFlg[reqIdx] = FLG_slotIsBusy; + } + requestInstances[reqIdx] = req; + requestNewHttpReqEpochMs[reqIdx] = currentTimeMillis(); + authorizerBeginMs[reqIdx] = NO_VALUE; + authorizerEndMs[reqIdx] = NO_VALUE; + beforeCatchallRouting[reqIdx] = NO_VALUE; + responseGotRequestedMs[reqIdx] = NO_VALUE; + writingResponseBeginMs[reqIdx] = NO_VALUE; + writingResponseHasReturnedMs[reqIdx] = NO_VALUE; + writingResponseEndMs[reqIdx] = NO_VALUE; + requestDoneMs[reqIdx] = NO_VALUE; + } + + public void onHttpRequestError(HttpServerRequest req, Throwable ex) { + if( !isOfInterest(req) ) return; + int reqIdx = getIdxOf(req); + long durMs = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + throw new UnsupportedOperationException(/*TODO*/"Not impl yet. Took "+durMs+"ms", ex); + } + + public void onAuthorizerBegin(HttpServerRequest req) { + if( !isOfInterest(req) ) return; + int reqIdx = getIdxOf(req); + authorizerBeginMs[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + } + + public void onAuthorizerEnd(HttpServerRequest req) { + if( !isOfInterest(req) ) return; + int reqIdx = getIdxOf(req); + authorizerEndMs[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + } + + public HttpServerRequest filterRequestBeforeCallingCatchallRouter(HttpServerRequest req) { + if( !isOfInterest(req) ) return req; + int reqIdx = getIdxOf(req); + beforeCatchallRouting[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + return new InterceptingServerRequest("ai9oh8urtgj", req); + } + + private void onHttpResponseGotRequested(HttpServerRequest req) { + assert isOfInterest(req); + int reqIdx = getIdxOf(req); + responseGotRequestedMs[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + } + + public void onWritingHttpResponseBegin(HttpServerRequest req) { + int reqIdx = getIdxOf(req); + writingResponseBeginMs[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + } + + public void onWritingHttpResponseHasReturned(HttpServerRequest req) { + assert isOfInterest(req); + int reqIdx = getIdxOf(req); + writingResponseHasReturnedMs[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + requestFlg[reqIdx] |= FLG_WritingHttpResponseHasReturned; + tryCompletingRequest(reqIdx); + } + + public void onWritingHttpResponseEnd(Throwable ex, HttpServerRequest req) { + assert ex == null; + assert isOfInterest(req); + int reqIdx = getIdxOf(req); + writingResponseEndMs[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + requestFlg[reqIdx] |= FLG_WritingHttpResponseEnd; + tryCompletingRequest(reqIdx); + } + + private void tryCompletingRequest(int reqIdx) { + int requestIsDoneMask = FLG_WritingHttpResponseHasReturned | FLG_WritingHttpResponseEnd; + if ((requestFlg[reqIdx] & requestIsDoneMask) != requestIsDoneMask) return; + requestDoneMs[reqIdx] = currentTimeMillis() - requestNewHttpReqEpochMs[reqIdx]; + report(reqIdx); + /* free our slot */ + synchronized (requestSlotLock){ + requestFlg[reqIdx] &= ~FLG_slotIsBusy; + requestInstances[reqIdx] = null; + } + } + + private void report(int reqIdx) { + if( requestDoneMs[reqIdx] < requestDurationBailTresholdLowMs ){ + /*fast requests usually are not worth logging, we're interested in the slow requests only*/ + if (log.isTraceEnabled()) log.trace( + "Req took {}ms (authBeg={}ms, authEnd={}ms, route={}ms, getRsp={}ms, wrBeg={}ms, wrRet={}ms, wrEnd={}ms)", + requestDoneMs[reqIdx], + authorizerBeginMs[reqIdx], + authorizerEndMs[reqIdx], + beforeCatchallRouting[reqIdx], + responseGotRequestedMs[reqIdx], + writingResponseBeginMs[reqIdx], + writingResponseHasReturnedMs[reqIdx], + writingResponseEndMs[reqIdx]); + }else{ + /*slow requests are interesting*/ + log.info("Req took {}ms (authBeg={}ms, authEnd={}ms, route={}ms, getRsp={}ms, wrBeg={}ms, wrRet={}ms, wrEnd={}ms)", + requestDoneMs[reqIdx], + authorizerBeginMs[reqIdx], + authorizerEndMs[reqIdx], + beforeCatchallRouting[reqIdx], + responseGotRequestedMs[reqIdx], + writingResponseBeginMs[reqIdx], + writingResponseHasReturnedMs[reqIdx], + writingResponseEndMs[reqIdx]); + } + } + + private boolean isOfInterest(HttpServerRequest req){ + if( !isOfInterestEvenReqNotYetSeen(req) ) return false; + if( !alreadyKnowRequest(req) ) return false; // Without start point, we cannot report anything useful + return true; + } + + private boolean isOfInterestEvenReqNotYetSeen(HttpServerRequest req) { + if( !log.isInfoEnabled() ) return false; // if we produce no output, makes no sense to burn CPU for it + if( !HttpMethod.GET.equals(req.method()) ) return false; // Only GET is interesting for us + if( !INFO_URI.equals(req.uri()) ) return false; // Only this specific URI is of interest + return true; + } + + private int getIdxOf(HttpServerRequest req) { + req = unwrap(req); + for( int idx = 0 ; idx < MAX_REQUESTS ; ++idx ){ + if( requestInstances[idx] == req ) return idx; + } + assert false : "why does this happen?"; + throw new NoSuchElementException(/*TODO*/"Not impl yet"); + } + + /** @return either index of free slot or -2 if no slot available */ + private int getFreeSlotIdx() { + for( int i = 0 ; i < MAX_REQUESTS ; ++i ){ + if( (requestFlg[i+slotReUseOffset%MAX_REQUESTS] & FLG_slotIsBusy) == 0 ) { + slotReUseOffset = i + 1; + return i; + } + } + return -2; + } + + private boolean alreadyKnowRequest(HttpServerRequest req) { + req = unwrap(req); + for( int i = 0 ; i < (0 + MAX_REQUESTS) ; ++i ){ + if((requestFlg[i] & FLG_slotIsBusy) == 0) continue; + if( requestInstances[i] == req ) return true; + } + return false; + } + + private HttpServerRequest unwrap(HttpServerRequest req){ + for( boolean hasChanged = true ; hasChanged ;){ + hasChanged = false; + while (req instanceof InterceptingServerRequest) { + hasChanged = true; + req = ((InterceptingServerRequest) req).delegate; + } + while(wrapperClazz.isInstance(req)){ + hasChanged = true; + try { + req = (HttpServerRequest) delegateField.get(req); + } catch (IllegalAccessException ex) { + throw new UnsupportedOperationException(/*TODO*/"Not impl yet", ex); + } + } + } + assert req != null; + return req; + } + + private class InterceptingServerRequest extends DelegateVertxHttpServerRequestInternal { + private final HttpServerRequest delegate; + + public InterceptingServerRequest(String debugHint, HttpServerRequest delegate) { + super(debugHint, delegate); + assert isOfInterest(delegate); + this.delegate = delegate; + } + + @Override public HttpServerResponse response() { + assert isOfInterest(delegate); + onHttpResponseGotRequested(delegate); + return super.response(); + } + } + + +} diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java index 889b3f1..bebe970 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java @@ -25,6 +25,21 @@ public class StreamUtils { return totalBytes; } + public static Runnable newCopyTask(java.io.InputStream src, java.io.OutputStream dst, boolean doCloseDst){ + return ()->{ + try{ + for( byte[] buf = new byte[8291] ;; ){ + int readLen = src.read(buf, 0, buf.length); + if( readLen == -1 ) break; + dst.write(buf, 0, readLen); + } + if( doCloseDst ) dst.close(); + }catch( java.io.IOException ex ){ + throw new RuntimeException(ex); + } + }; + } + public static <SRC,DST> java.util.Iterator<DST> map( java.util.Iterator<SRC> src , java.util.function.Function<SRC,DST> mapper ) { return new java.util.Iterator<DST>() { @Override public boolean hasNext() { return src.hasNext(); } diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java index 2bb1bfb..d7d7ec8 100644 --- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java +++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java @@ -25,9 +25,9 @@ public class TimeUtils { * Find smallest distance assuming integers overflow "like a circle". * * Computers cannot represent all existing integers. Due to how - * integers are represented in computers, they are not infinite but - * more like a circle. Speak when we infinitely increment an - * integer, it overflows and (usually) continues to walk around this + * integers are represented in java, they are not infinite but + * more like a circle. Speak when we infinitely increment an integer, + * it overflows and (usually) continues to walk around this * (imaginary) circle. * * This function takes two of those numbers on this circle and |