Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grizzly Http Server refactor #581

Merged
merged 7 commits into from
Jul 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions opentracing-specialagent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -470,13 +470,6 @@
<optional>true</optional>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentracing.contrib.specialagent.rule</groupId>
<artifactId>mule-4-http-service</artifactId>
<version>${project.version}</version>
<optional>true</optional>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentracing.contrib.specialagent.rule</groupId>
<artifactId>mule-4-module-artifact</artifactId>
Expand Down
16 changes: 2 additions & 14 deletions rule/grizzly-http-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<properties>
<sa.rule.name>grizzly:http-server</sa.rule.name>
<min.version>2.3.35</min.version>
<version.opentracing.grizzly>0.1.3</version.opentracing.grizzly>
<version.opentracing.grizzly>0.2.0</version.opentracing.grizzly>
</properties>
<build>
<plugins>
Expand All @@ -42,15 +42,10 @@
<passes>
<pass>
<dependencies>
<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-framework</artifactId>
<version>org.glassfish.grizzly:grizzly-framework:[${min.version},]</version>
</dependency>
<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-http</artifactId>
<version>org.glassfish.grizzly:grizzly-framework:[${min.version},]</version>
<version>org.glassfish.grizzly:grizzly-http:[${min.version},]</version>
</dependency>
</dependencies>
</pass>
Expand All @@ -76,13 +71,6 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-framework</artifactId>
<version>${min.version}</version>
<optional>true</optional>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-http</artifactId>
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.opentracing.contrib.specialagent.rule.grizzly.http.server;

import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.contrib.grizzly.http.server.GizzlyHttpRequestPacketAdapter;
import io.opentracing.contrib.grizzly.http.server.GrizzlyServerSpanDecorator;
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap;
import io.opentracing.util.GlobalTracer;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.NextAction;
import org.glassfish.grizzly.http.HttpContent;
import org.glassfish.grizzly.http.HttpRequestPacket;
import org.glassfish.grizzly.http.HttpResponsePacket;

public class HttpServerFilterIntercept {
public static void onHandleReadExit(
final Object ctxObj,
Object toReturn) {

FilterChainContext ctx = (FilterChainContext) ctxObj;

// If not continuing to process
// See: org.glassfish.grizzly.filterchain.InvokeAction.TYPE
// If we have have already started a span for this request
if (!(ctx.getMessage() instanceof HttpContent) || ((NextAction) toReturn).type() != 0 || SpanAssociations.get().hasSpanFor(ctx)) {
return;
}

Tracer tracer = GlobalTracer.get();
final HttpRequestPacket request = (HttpRequestPacket) ((HttpContent) ctx.getMessage()).getHttpHeader();

TextMap adapter = new GizzlyHttpRequestPacketAdapter(request);
SpanContext extractedContext = tracer.extract(Format.Builtin.HTTP_HEADERS,
adapter);

final Span span = tracer.buildSpan("HTTP::" + request.getMethod().getMethodString())
.ignoreActiveSpan()
.asChildOf(extractedContext)
.start();

GrizzlyServerSpanDecorator.STANDARD_TAGS.onRequest(request, span);
ctx.addCompletionListener(new SpanCompletionListener(span));
SpanAssociations.get().associateSpan(ctx, span);
}

public static void onPrepareResponse(
final Object ctx,
final Object response) {
Span toTag = SpanAssociations.get().retrieveSpan(ctx);
if (toTag != null) {
GrizzlyServerSpanDecorator.STANDARD_TAGS.onResponse((HttpResponsePacket) response, toTag);
}
}

public static class SpanCompletionListener implements FilterChainContext.CompletionListener {
private final Span span;

public SpanCompletionListener(Span span) {
this.span = span;
}

@Override
public void onComplete(FilterChainContext context) {
span.finish();
SpanAssociations.get().dispose(context);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package io.opentracing.contrib.specialagent.rule.grizzly.http.server;

import io.opentracing.contrib.specialagent.Level;
import io.opentracing.contrib.specialagent.Logger;
import io.opentracing.Scope;
import io.opentracing.contrib.specialagent.AgentRule;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.utility.JavaModule;

import static net.bytebuddy.matcher.ElementMatchers.*;

public class HttpServerFilterRule extends AgentRule {
public static final Logger logger = Logger.getLogger(HttpServerFilterRule.class);
private static final String FILTER_CHAIN_CONTEXT = "org.glassfish.grizzly.filterchain.FilterChainContext";
private static final String HANDLE_READ = "handleRead";

@Override
public AgentBuilder buildAgentChainedGlobal1(final AgentBuilder builder) {
return builder
.type(named("org.glassfish.grizzly.http.HttpServerFilter"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(final DynamicType.Builder<?> builder, final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
return builder.visit(advice(typeDescription).to(HandleReadAdvice.class).on(named(HANDLE_READ)
.and(takesArgument(0, named(FILTER_CHAIN_CONTEXT)))));
}
})
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(final DynamicType.Builder<?> builder, final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
return builder.visit(advice(typeDescription).to(PrepareResponseAdvice.class).on(named("prepareResponse")
.and(takesArgument(0, named(FILTER_CHAIN_CONTEXT)))
.and(takesArgument(2, named("org.glassfish.grizzly.http.HttpResponsePacket")))));
}
})

.type(hasSuperClass(named("org.glassfish.grizzly.filterchain.BaseFilter"))
// common http server filters
.and(not(named("org.glassfish.grizzly.filterchain.TransportFilter")
.or(named("org.glassfish.grizzly.nio.transport.TCPNIOTransportFilter"))
.or(named("org.glassfish.grizzly.http.HttpServerFilter"))
.or(named("org.glassfish.grizzly.http.HttpCodecFilter"))
.or(named("org.glassfish.grizzly.utils.IdleTimeoutFilter"))
// common http client filters
.or(named("com.ning.http.client.providers.grizzly.AsyncHttpClientFilter"))
.or(named("org.glassfish.grizzly.websockets.WebSocketClientFilter"))
.or(hasSuperClass(named("org.glassfish.grizzly.http.HttpClientFilter"))))))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(final DynamicType.Builder<?> builder, final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
return builder.visit(advice(typeDescription).to(WorkerHandleReadAdvice.class).on(named(HANDLE_READ)
.and(takesArgument(0, named(FILTER_CHAIN_CONTEXT)))));
}
});
}

public static class HandleReadAdvice {
@Advice.OnMethodExit
public static void onExit(
final @ClassName String className,
final @Advice.Origin String origin,
@Advice.Argument(0) final Object ctx,
@Advice.Return Object toReturn) {
if (isAllowed(className, origin))
HttpServerFilterIntercept.onHandleReadExit(ctx, toReturn);
}
}

public static class WorkerHandleReadAdvice {
@Advice.OnMethodEnter
public static void onEnter(
final @ClassName String className,
final @Advice.Origin String origin,
final @Advice.This Object thiz,
@Advice.Argument(value = 0, typing = Assigner.Typing.DYNAMIC) final Object ctx,
@Advice.Local("scope") Scope scope) {

if (hackShouldFilter(thiz))
return;

if (isAllowed(className, origin))
scope = WorkerFilterIntercept.onHandleReadEnter(ctx);
}

@Advice.OnMethodExit
public static void onExit(
final @ClassName String className,
final @Advice.Origin String origin,
final @Advice.This Object thiz,
@Advice.Local("scope") Scope scope) {

if (hackShouldFilter(thiz))
return;

if (isAllowed(className, origin))
WorkerFilterIntercept.onHandleReadExit(scope);
}
}

public static class PrepareResponseAdvice {
@Advice.OnMethodExit
public static void onExit(
final @ClassName String className,
final @Advice.Origin String origin,
@Advice.Argument(value = 0, typing = Assigner.Typing.DYNAMIC) final Object ctx,
@Advice.Argument(value = 2, typing = Assigner.Typing.DYNAMIC) final Object response) {

if (isAllowed(className, origin))
HttpServerFilterIntercept.onPrepareResponse(ctx, response);
}

}

public static boolean hackShouldFilter(Object thiz) {
// TODO: 7/11/20 figure out why these are not filtered at TypeDescription
logger.log(Level.FINER, "Checking predicate for potential worker filter " + thiz.getClass().getName());
return "com.ning.http.client.providers.grizzly.AsyncHttpClientFilter".equals(thiz.getClass().getName()) ||
"org.glassfish.grizzly.websockets.WebSocketClientFilter".equals(thiz.getClass().getName());
}
}
Loading