Convert grizzly groovy to java (#12248)
This commit is contained in:
parent
ee30a26796
commit
171e9d170a
|
@ -1,243 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import io.opentelemetry.api.common.AttributeKey
|
|
||||||
import io.opentelemetry.instrumentation.test.AgentTestTrait
|
|
||||||
import io.opentelemetry.instrumentation.test.base.HttpServerTest
|
|
||||||
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
|
|
||||||
import io.opentelemetry.semconv.HttpAttributes
|
|
||||||
import org.glassfish.grizzly.filterchain.BaseFilter
|
|
||||||
import org.glassfish.grizzly.filterchain.FilterChain
|
|
||||||
import org.glassfish.grizzly.filterchain.FilterChainBuilder
|
|
||||||
import org.glassfish.grizzly.filterchain.FilterChainContext
|
|
||||||
import org.glassfish.grizzly.filterchain.NextAction
|
|
||||||
import org.glassfish.grizzly.filterchain.TransportFilter
|
|
||||||
import org.glassfish.grizzly.http.HttpContent
|
|
||||||
import org.glassfish.grizzly.http.HttpHeader
|
|
||||||
import org.glassfish.grizzly.http.HttpRequestPacket
|
|
||||||
import org.glassfish.grizzly.http.HttpResponsePacket
|
|
||||||
import org.glassfish.grizzly.http.HttpServerFilter
|
|
||||||
import org.glassfish.grizzly.http.server.HttpServer
|
|
||||||
import org.glassfish.grizzly.http.util.Parameters
|
|
||||||
import org.glassfish.grizzly.nio.transport.TCPNIOServerConnection
|
|
||||||
import org.glassfish.grizzly.nio.transport.TCPNIOTransport
|
|
||||||
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder
|
|
||||||
import org.glassfish.grizzly.utils.DelayedExecutor
|
|
||||||
import org.glassfish.grizzly.utils.IdleTimeoutFilter
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.AUTH_REQUIRED
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
|
|
||||||
import static java.lang.String.valueOf
|
|
||||||
import static java.nio.charset.Charset.defaultCharset
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS
|
|
||||||
import static org.glassfish.grizzly.memory.Buffers.wrap
|
|
||||||
|
|
||||||
class GrizzlyFilterchainServerTest extends HttpServerTest<HttpServer> implements AgentTestTrait {
|
|
||||||
|
|
||||||
private TCPNIOTransport transport
|
|
||||||
private TCPNIOServerConnection serverConnection
|
|
||||||
|
|
||||||
@Override
|
|
||||||
HttpServer startServer(int port) {
|
|
||||||
FilterChain filterChain = setUpFilterChain()
|
|
||||||
setUpTransport(filterChain)
|
|
||||||
|
|
||||||
serverConnection = transport.bind("127.0.0.1", port)
|
|
||||||
transport.start()
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void stopServer(HttpServer httpServer) {
|
|
||||||
transport.shutdownNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
|
|
||||||
def attributes = super.httpAttributes(endpoint)
|
|
||||||
attributes.remove(HttpAttributes.HTTP_ROUTE)
|
|
||||||
attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean testException() {
|
|
||||||
// justification: grizzly async closes the channel which
|
|
||||||
// looks like a ConnectException to the client when this happens
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean testCapturedHttpHeaders() {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean verifyServerSpanEndTime() {
|
|
||||||
// server spans are ended inside of the controller spans
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUpTransport(FilterChain filterChain) {
|
|
||||||
TCPNIOTransportBuilder transportBuilder = TCPNIOTransportBuilder.newInstance()
|
|
||||||
.setOptimizedForMultiplexing(true)
|
|
||||||
|
|
||||||
transportBuilder.setTcpNoDelay(true)
|
|
||||||
transportBuilder.setKeepAlive(false)
|
|
||||||
transportBuilder.setReuseAddress(true)
|
|
||||||
transportBuilder.setServerConnectionBackLog(50)
|
|
||||||
transportBuilder.setServerSocketSoTimeout(80000)
|
|
||||||
|
|
||||||
transport = transportBuilder.build()
|
|
||||||
transport.setProcessor(filterChain)
|
|
||||||
}
|
|
||||||
|
|
||||||
FilterChain setUpFilterChain() {
|
|
||||||
return FilterChainBuilder.stateless()
|
|
||||||
.add(createTransportFilter())
|
|
||||||
.add(createIdleTimeoutFilter())
|
|
||||||
.add(new HttpServerFilter())
|
|
||||||
.add(new LastFilter())
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
TransportFilter createTransportFilter() {
|
|
||||||
return new TransportFilter()
|
|
||||||
}
|
|
||||||
|
|
||||||
IdleTimeoutFilter createIdleTimeoutFilter() {
|
|
||||||
return new IdleTimeoutFilter(new DelayedExecutor(Executors.newCachedThreadPool()), 80000, MILLISECONDS)
|
|
||||||
}
|
|
||||||
|
|
||||||
static class LastFilter extends BaseFilter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
NextAction handleRead(final FilterChainContext ctx) throws IOException {
|
|
||||||
if (ctx.getMessage() instanceof HttpContent) {
|
|
||||||
HttpContent httpContent = ctx.getMessage()
|
|
||||||
HttpHeader httpHeader = httpContent.getHttpHeader()
|
|
||||||
if (httpHeader instanceof HttpRequestPacket) {
|
|
||||||
HttpRequestPacket request = (HttpRequestPacket) httpContent.getHttpHeader()
|
|
||||||
ResponseParameters responseParameters = buildResponse(request)
|
|
||||||
HttpResponsePacket.Builder builder = HttpResponsePacket.builder(request)
|
|
||||||
.status(responseParameters.getStatus())
|
|
||||||
.header("Content-Length", valueOf(responseParameters.getResponseBody().length))
|
|
||||||
responseParameters.fillHeaders(builder)
|
|
||||||
HttpResponsePacket responsePacket = builder.build()
|
|
||||||
controller(responseParameters.getEndpoint()) {
|
|
||||||
responseParameters.execute()
|
|
||||||
ctx.write(HttpContent.builder(responsePacket)
|
|
||||||
.content(wrap(ctx.getMemoryManager(), responseParameters.getResponseBody()))
|
|
||||||
.build())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ctx.getStopAction()
|
|
||||||
}
|
|
||||||
|
|
||||||
ResponseParameters buildResponse(HttpRequestPacket request) {
|
|
||||||
String uri = request.getRequestURI()
|
|
||||||
Map<String, String> headers = new HashMap<>()
|
|
||||||
|
|
||||||
ServerEndpoint endpoint
|
|
||||||
Closure closure
|
|
||||||
switch (uri) {
|
|
||||||
case "/success":
|
|
||||||
endpoint = SUCCESS
|
|
||||||
break
|
|
||||||
case "/redirect":
|
|
||||||
endpoint = REDIRECT
|
|
||||||
headers.put("location", REDIRECT.body)
|
|
||||||
break
|
|
||||||
case "/error-status":
|
|
||||||
endpoint = ERROR
|
|
||||||
break
|
|
||||||
case "/exception":
|
|
||||||
throw new Exception(EXCEPTION.body)
|
|
||||||
case "/query":
|
|
||||||
endpoint = QUERY_PARAM
|
|
||||||
break
|
|
||||||
case "/path/123/param":
|
|
||||||
endpoint = PATH_PARAM
|
|
||||||
break
|
|
||||||
case "/authRequired":
|
|
||||||
endpoint = AUTH_REQUIRED
|
|
||||||
break
|
|
||||||
case "/child":
|
|
||||||
endpoint = INDEXED_CHILD
|
|
||||||
Parameters parameters = new Parameters()
|
|
||||||
parameters.setQuery(request.getQueryStringDC())
|
|
||||||
parameters.setQueryStringEncoding(StandardCharsets.UTF_8)
|
|
||||||
parameters.handleQueryParameters()
|
|
||||||
closure = {
|
|
||||||
INDEXED_CHILD.collectSpanAttributes { name -> parameters.getParameter(name) }
|
|
||||||
}
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
endpoint = NOT_FOUND
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
int status = endpoint.status
|
|
||||||
String responseBody = endpoint == REDIRECT ? "" : endpoint.body
|
|
||||||
|
|
||||||
byte[] responseBodyBytes = responseBody.getBytes(defaultCharset())
|
|
||||||
return new ResponseParameters(endpoint, status, responseBodyBytes, headers, closure)
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ResponseParameters {
|
|
||||||
Map<String, String> headers
|
|
||||||
ServerEndpoint endpoint
|
|
||||||
int status
|
|
||||||
byte[] responseBody
|
|
||||||
Closure closure
|
|
||||||
|
|
||||||
ResponseParameters(ServerEndpoint endpoint,
|
|
||||||
int status,
|
|
||||||
byte[] responseBody,
|
|
||||||
Map<String, String> headers,
|
|
||||||
Closure closure) {
|
|
||||||
this.endpoint = endpoint
|
|
||||||
this.status = status
|
|
||||||
this.responseBody = responseBody
|
|
||||||
this.headers = headers
|
|
||||||
this.closure = closure
|
|
||||||
}
|
|
||||||
|
|
||||||
int getStatus() {
|
|
||||||
return status
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] getResponseBody() {
|
|
||||||
return responseBody
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerEndpoint getEndpoint() {
|
|
||||||
return endpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
void fillHeaders(HttpResponsePacket.Builder builder) {
|
|
||||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
|
||||||
builder.header(header.getKey(), header.getValue())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute() {
|
|
||||||
if (closure != null) {
|
|
||||||
closure.run()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.glassfish.grizzly.IOStrategy
|
|
||||||
import org.glassfish.grizzly.http.server.NetworkListener
|
|
||||||
import org.glassfish.grizzly.strategies.LeaderFollowerNIOStrategy
|
|
||||||
import org.glassfish.grizzly.strategies.SameThreadIOStrategy
|
|
||||||
import org.glassfish.grizzly.strategies.SimpleDynamicNIOStrategy
|
|
||||||
|
|
||||||
abstract class GrizzlyIOStrategyTest extends GrizzlyTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void configureListener(NetworkListener listener) {
|
|
||||||
// Default in NIOTransportBuilder is WorkerThreadIOStrategy, so don't need to retest that.
|
|
||||||
listener.getTransport().setIOStrategy(strategy())
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract IOStrategy strategy()
|
|
||||||
}
|
|
||||||
|
|
||||||
class LeaderFollowerTest extends GrizzlyIOStrategyTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
IOStrategy strategy() {
|
|
||||||
return LeaderFollowerNIOStrategy.instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SameThreadTest extends GrizzlyIOStrategyTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
IOStrategy strategy() {
|
|
||||||
return SameThreadIOStrategy.instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleDynamicTest extends GrizzlyIOStrategyTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
IOStrategy strategy() {
|
|
||||||
return SimpleDynamicNIOStrategy.instance
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import io.opentelemetry.api.common.AttributeKey
|
|
||||||
import io.opentelemetry.instrumentation.test.AgentTestTrait
|
|
||||||
import io.opentelemetry.instrumentation.test.base.HttpServerTest
|
|
||||||
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
|
|
||||||
import io.opentelemetry.semconv.HttpAttributes
|
|
||||||
import org.glassfish.grizzly.http.server.HttpHandler
|
|
||||||
import org.glassfish.grizzly.http.server.HttpServer
|
|
||||||
import org.glassfish.grizzly.http.server.NetworkListener
|
|
||||||
import org.glassfish.grizzly.http.server.Request
|
|
||||||
import org.glassfish.grizzly.http.server.Response
|
|
||||||
import org.glassfish.grizzly.http.server.ServerConfiguration
|
|
||||||
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
|
|
||||||
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
|
|
||||||
|
|
||||||
class GrizzlyTest extends HttpServerTest<HttpServer> implements AgentTestTrait {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
HttpServer startServer(int port) {
|
|
||||||
HttpServer server = new HttpServer()
|
|
||||||
NetworkListener listener = new NetworkListener("grizzly", "localhost", port)
|
|
||||||
configureListener(listener)
|
|
||||||
server.addListener(listener)
|
|
||||||
ServerConfiguration config = server.getServerConfiguration()
|
|
||||||
config.addHttpHandler(new HttpHandler() {
|
|
||||||
@Override
|
|
||||||
void service(Request request, Response response) throws Exception {
|
|
||||||
def endpoint = ServerEndpoint.forPath(request.getDecodedRequestURI())
|
|
||||||
controller(endpoint) {
|
|
||||||
switch (endpoint) {
|
|
||||||
case SUCCESS:
|
|
||||||
response.status = endpoint.status
|
|
||||||
response.writer.write(endpoint.body)
|
|
||||||
break
|
|
||||||
case INDEXED_CHILD:
|
|
||||||
response.status = endpoint.status
|
|
||||||
endpoint.collectSpanAttributes { request.getParameter(it) }
|
|
||||||
break
|
|
||||||
case QUERY_PARAM:
|
|
||||||
response.status = endpoint.status
|
|
||||||
response.writer.write(request.queryString)
|
|
||||||
break
|
|
||||||
case REDIRECT:
|
|
||||||
response.sendRedirect(endpoint.body)
|
|
||||||
break
|
|
||||||
case ERROR:
|
|
||||||
response.sendError(endpoint.status, endpoint.body)
|
|
||||||
break
|
|
||||||
case NOT_FOUND:
|
|
||||||
response.status = endpoint.status
|
|
||||||
break
|
|
||||||
case EXCEPTION:
|
|
||||||
throw new Exception(EXCEPTION.body)
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("unexpected endpoint " + endpoint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, "/")
|
|
||||||
|
|
||||||
server.start()
|
|
||||||
|
|
||||||
return server
|
|
||||||
}
|
|
||||||
|
|
||||||
void configureListener(NetworkListener listener) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
Set<AttributeKey<?>> httpAttributes(ServerEndpoint endpoint) {
|
|
||||||
def attributes = super.httpAttributes(endpoint)
|
|
||||||
attributes.remove(HttpAttributes.HTTP_ROUTE)
|
|
||||||
attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void stopServer(HttpServer server) {
|
|
||||||
server.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean hasResponseCustomizer(ServerEndpoint endpoint) {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean testCapturedHttpHeaders() {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean verifyServerSpanEndTime() {
|
|
||||||
// fails for redirect test
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
boolean testErrorBody() {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT;
|
||||||
|
import static java.nio.charset.Charset.defaultCharset;
|
||||||
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
import static org.glassfish.grizzly.memory.Buffers.wrap;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.common.AttributeKey;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint;
|
||||||
|
import io.opentelemetry.semconv.HttpAttributes;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import org.glassfish.grizzly.Transport;
|
||||||
|
import org.glassfish.grizzly.filterchain.BaseFilter;
|
||||||
|
import org.glassfish.grizzly.filterchain.FilterChain;
|
||||||
|
import org.glassfish.grizzly.filterchain.FilterChainBuilder;
|
||||||
|
import org.glassfish.grizzly.filterchain.FilterChainContext;
|
||||||
|
import org.glassfish.grizzly.filterchain.NextAction;
|
||||||
|
import org.glassfish.grizzly.filterchain.TransportFilter;
|
||||||
|
import org.glassfish.grizzly.http.HttpContent;
|
||||||
|
import org.glassfish.grizzly.http.HttpHeader;
|
||||||
|
import org.glassfish.grizzly.http.HttpRequestPacket;
|
||||||
|
import org.glassfish.grizzly.http.HttpResponsePacket;
|
||||||
|
import org.glassfish.grizzly.http.HttpServerFilter;
|
||||||
|
import org.glassfish.grizzly.http.util.Parameters;
|
||||||
|
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
|
||||||
|
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
|
||||||
|
import org.glassfish.grizzly.utils.DelayedExecutor;
|
||||||
|
import org.glassfish.grizzly.utils.IdleTimeoutFilter;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
class GrizzlyFilterchainServerTest extends AbstractHttpServerTest<Transport> {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent();
|
||||||
|
|
||||||
|
private TCPNIOTransport transport;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Transport setupServer() throws Exception {
|
||||||
|
FilterChain filterChain = setUpFilterChain();
|
||||||
|
setUpTransport(filterChain);
|
||||||
|
|
||||||
|
transport.bind("127.0.0.1", port);
|
||||||
|
transport.start();
|
||||||
|
return transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stopServer(Transport transport) throws IOException {
|
||||||
|
transport.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpServerTestOptions options) {
|
||||||
|
options.setHttpAttributes(
|
||||||
|
serverEndpoint -> {
|
||||||
|
Set<AttributeKey<?>> attributes =
|
||||||
|
new HashSet<>(HttpServerTestOptions.DEFAULT_HTTP_ATTRIBUTES);
|
||||||
|
attributes.remove(HttpAttributes.HTTP_ROUTE);
|
||||||
|
return attributes;
|
||||||
|
});
|
||||||
|
|
||||||
|
// justification: grizzly async closes the channel which
|
||||||
|
// looks like a ConnectException to the client when this happens
|
||||||
|
options.setTestException(false);
|
||||||
|
|
||||||
|
options.setTestCaptureHttpHeaders(false);
|
||||||
|
|
||||||
|
// server spans are ended inside of the controller spans
|
||||||
|
options.setVerifyServerSpanEndTime(false);
|
||||||
|
options.setTestErrorBody(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpTransport(FilterChain filterChain) {
|
||||||
|
TCPNIOTransportBuilder transportBuilder =
|
||||||
|
TCPNIOTransportBuilder.newInstance().setOptimizedForMultiplexing(true);
|
||||||
|
|
||||||
|
transportBuilder.setTcpNoDelay(true);
|
||||||
|
transportBuilder.setKeepAlive(false);
|
||||||
|
transportBuilder.setReuseAddress(true);
|
||||||
|
transportBuilder.setServerConnectionBackLog(50);
|
||||||
|
transportBuilder.setServerSocketSoTimeout(80000);
|
||||||
|
|
||||||
|
transport = transportBuilder.build();
|
||||||
|
transport.setProcessor(filterChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings(
|
||||||
|
"deprecation") // Constructor has been deprecated in favor of builder pattern promised to be
|
||||||
|
// released in a next major release version, but it is not yet available.
|
||||||
|
private static FilterChain setUpFilterChain() {
|
||||||
|
return FilterChainBuilder.stateless()
|
||||||
|
.add(createTransportFilter())
|
||||||
|
.add(createIdleTimeoutFilter())
|
||||||
|
.add(new HttpServerFilter())
|
||||||
|
.add(new LastFilter())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TransportFilter createTransportFilter() {
|
||||||
|
return new TransportFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IdleTimeoutFilter createIdleTimeoutFilter() {
|
||||||
|
return new IdleTimeoutFilter(
|
||||||
|
new DelayedExecutor(Executors.newCachedThreadPool()), 80000, MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class LastFilter extends BaseFilter {
|
||||||
|
@Override
|
||||||
|
public NextAction handleRead(FilterChainContext ctx) throws IOException {
|
||||||
|
if (ctx.getMessage() instanceof HttpContent) {
|
||||||
|
HttpContent httpContent = ctx.getMessage();
|
||||||
|
HttpHeader httpHeader = httpContent.getHttpHeader();
|
||||||
|
if (httpHeader instanceof HttpRequestPacket) {
|
||||||
|
HttpRequestPacket request = (HttpRequestPacket) httpContent.getHttpHeader();
|
||||||
|
ResponseParameters responseParameters = buildResponse(request);
|
||||||
|
HttpResponsePacket.Builder builder =
|
||||||
|
HttpResponsePacket.builder(request)
|
||||||
|
.status(responseParameters.getStatus())
|
||||||
|
.header(
|
||||||
|
"Content-Length",
|
||||||
|
String.valueOf(responseParameters.getResponseBody().length));
|
||||||
|
responseParameters.fillHeaders(builder);
|
||||||
|
HttpResponsePacket responsePacket = builder.build();
|
||||||
|
controller(
|
||||||
|
responseParameters.getEndpoint(),
|
||||||
|
() -> {
|
||||||
|
responseParameters.execute();
|
||||||
|
ctx.write(
|
||||||
|
HttpContent.builder(responsePacket)
|
||||||
|
.content(wrap(ctx.getMemoryManager(), responseParameters.getResponseBody()))
|
||||||
|
.build());
|
||||||
|
return responsePacket;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ctx.getStopAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ResponseParameters buildResponse(HttpRequestPacket request) {
|
||||||
|
String uri = request.getRequestURI();
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
|
||||||
|
ServerEndpoint endpoint = ServerEndpoint.forPath(uri);
|
||||||
|
Runnable closure = null;
|
||||||
|
if (endpoint == REDIRECT) {
|
||||||
|
headers.put("location", REDIRECT.getBody());
|
||||||
|
}
|
||||||
|
if (endpoint == EXCEPTION) {
|
||||||
|
throw new IllegalArgumentException(EXCEPTION.getBody());
|
||||||
|
}
|
||||||
|
if (endpoint == INDEXED_CHILD) {
|
||||||
|
Parameters parameters = new Parameters();
|
||||||
|
parameters.setQuery(request.getQueryStringDC());
|
||||||
|
parameters.setQueryStringEncoding(StandardCharsets.UTF_8);
|
||||||
|
parameters.handleQueryParameters();
|
||||||
|
closure =
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
INDEXED_CHILD.collectSpanAttributes(parameters::getParameter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = endpoint.getStatus();
|
||||||
|
String responseBody = endpoint == REDIRECT ? "" : endpoint.getBody();
|
||||||
|
|
||||||
|
byte[] responseBodyBytes = responseBody.getBytes(defaultCharset());
|
||||||
|
return new ResponseParameters(endpoint, status, responseBodyBytes, headers, closure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResponseParameters {
|
||||||
|
private final Map<String, String> headers;
|
||||||
|
private final ServerEndpoint endpoint;
|
||||||
|
private final int status;
|
||||||
|
private final byte[] responseBody;
|
||||||
|
private final Runnable closure;
|
||||||
|
|
||||||
|
ResponseParameters(
|
||||||
|
ServerEndpoint endpoint,
|
||||||
|
int status,
|
||||||
|
byte[] responseBody,
|
||||||
|
Map<String, String> headers,
|
||||||
|
Runnable closure) {
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
this.status = status;
|
||||||
|
this.responseBody = responseBody;
|
||||||
|
this.headers = headers;
|
||||||
|
this.closure = closure;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] getResponseBody() {
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerEndpoint getEndpoint() {
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillHeaders(HttpResponsePacket.Builder builder) {
|
||||||
|
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||||
|
builder.header(header.getKey(), header.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute() {
|
||||||
|
if (closure != null) {
|
||||||
|
closure.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
|
import org.glassfish.grizzly.IOStrategy;
|
||||||
|
import org.glassfish.grizzly.http.server.NetworkListener;
|
||||||
|
|
||||||
|
abstract class GrizzlyIoStrategyTest extends GrizzlyTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureListener(NetworkListener listener) {
|
||||||
|
// Default in NIOTransportBuilder is WorkerThreadIOStrategy, so don't need to retest that.
|
||||||
|
listener.getTransport().setIOStrategy(strategy());
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract IOStrategy strategy();
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT;
|
||||||
|
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.common.AttributeKey;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint;
|
||||||
|
import io.opentelemetry.semconv.HttpAttributes;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.glassfish.grizzly.http.server.HttpHandler;
|
||||||
|
import org.glassfish.grizzly.http.server.HttpServer;
|
||||||
|
import org.glassfish.grizzly.http.server.NetworkListener;
|
||||||
|
import org.glassfish.grizzly.http.server.Request;
|
||||||
|
import org.glassfish.grizzly.http.server.Response;
|
||||||
|
import org.glassfish.grizzly.http.server.ServerConfiguration;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
abstract class GrizzlyTest extends AbstractHttpServerTest<HttpServer> {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpServer setupServer() throws Exception {
|
||||||
|
HttpServer server = new HttpServer();
|
||||||
|
NetworkListener listener = new NetworkListener("grizzly", "localhost", port);
|
||||||
|
configureListener(listener);
|
||||||
|
server.addListener(listener);
|
||||||
|
ServerConfiguration config = server.getServerConfiguration();
|
||||||
|
config.addHttpHandler(
|
||||||
|
new HttpHandler() {
|
||||||
|
@Override
|
||||||
|
public void service(Request request, Response response) throws Exception {
|
||||||
|
ServerEndpoint endpoint = ServerEndpoint.forPath(request.getDecodedRequestURI());
|
||||||
|
controller(
|
||||||
|
endpoint,
|
||||||
|
() -> {
|
||||||
|
if (endpoint.equals(SUCCESS)) {
|
||||||
|
try {
|
||||||
|
response.getWriter().write(endpoint.getBody());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else if (endpoint.equals(INDEXED_CHILD)) {
|
||||||
|
response.setStatus(endpoint.getStatus());
|
||||||
|
endpoint.collectSpanAttributes(request::getParameter);
|
||||||
|
} else if (endpoint.equals(QUERY_PARAM)) {
|
||||||
|
response.setStatus(endpoint.getStatus());
|
||||||
|
try {
|
||||||
|
response.getWriter().write(request.getQueryString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else if (endpoint.equals(REDIRECT)) {
|
||||||
|
try {
|
||||||
|
response.sendRedirect(endpoint.getBody());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else if (endpoint.equals(ERROR)) {
|
||||||
|
try {
|
||||||
|
response.sendError(endpoint.getStatus(), endpoint.getBody());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else if (endpoint.equals(NOT_FOUND)) {
|
||||||
|
response.setStatus(endpoint.getStatus());
|
||||||
|
} else if (endpoint.equals(EXCEPTION)) {
|
||||||
|
throw new IllegalArgumentException(EXCEPTION.getBody());
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("unexpected endpoint " + endpoint);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/");
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void configureListener(NetworkListener listener);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stopServer(HttpServer server) {
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpServerTestOptions options) {
|
||||||
|
options.setHttpAttributes(
|
||||||
|
serverEndpoint -> {
|
||||||
|
Set<AttributeKey<?>> attributes =
|
||||||
|
new HashSet<>(HttpServerTestOptions.DEFAULT_HTTP_ATTRIBUTES);
|
||||||
|
attributes.remove(HttpAttributes.HTTP_ROUTE);
|
||||||
|
return attributes;
|
||||||
|
});
|
||||||
|
options.setTestCaptureHttpHeaders(false);
|
||||||
|
options.setHasResponseCustomizer(serverEndpoint -> true);
|
||||||
|
options.setVerifyServerSpanEndTime(false); // fails for redirect test
|
||||||
|
options.setTestErrorBody(false);
|
||||||
|
options.setExpectedException(new IllegalArgumentException(EXCEPTION.getBody()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
|
import org.glassfish.grizzly.IOStrategy;
|
||||||
|
import org.glassfish.grizzly.strategies.LeaderFollowerNIOStrategy;
|
||||||
|
|
||||||
|
class LeaderFollowerTest extends GrizzlyIoStrategyTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
IOStrategy strategy() {
|
||||||
|
return LeaderFollowerNIOStrategy.getInstance();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
|
import org.glassfish.grizzly.IOStrategy;
|
||||||
|
import org.glassfish.grizzly.strategies.SameThreadIOStrategy;
|
||||||
|
|
||||||
|
class SameThreadTest extends GrizzlyIoStrategyTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
IOStrategy strategy() {
|
||||||
|
return SameThreadIOStrategy.getInstance();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.grizzly;
|
||||||
|
|
||||||
|
import org.glassfish.grizzly.IOStrategy;
|
||||||
|
import org.glassfish.grizzly.strategies.SimpleDynamicNIOStrategy;
|
||||||
|
|
||||||
|
class SimpleDynamicTest extends GrizzlyIoStrategyTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
IOStrategy strategy() {
|
||||||
|
return SimpleDynamicNIOStrategy.getInstance();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue