-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #581 from jam01/grizzly-refactor
Grizzly Http Server refactor
- Loading branch information
Showing
19 changed files
with
296 additions
and
513 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 0 additions & 32 deletions
32
.../opentracing/contrib/specialagent/rule/grizzly/http/server/FilterChainAgentIntercept.java
This file was deleted.
Oops, something went wrong.
72 changes: 0 additions & 72 deletions
72
...va/io/opentracing/contrib/specialagent/rule/grizzly/http/server/FilterChainAgentRule.java
This file was deleted.
Oops, something went wrong.
70 changes: 70 additions & 0 deletions
70
.../opentracing/contrib/specialagent/rule/grizzly/http/server/HttpServerFilterIntercept.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} |
124 changes: 124 additions & 0 deletions
124
...va/io/opentracing/contrib/specialagent/rule/grizzly/http/server/HttpServerFilterRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} | ||
} |
Oops, something went wrong.