Make server_send/recv a feature of the web filter
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.event;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@SuppressWarnings("serial")
|
||||
public class ServerReceivedEvent extends ApplicationEvent {
|
||||
|
||||
private final Span parent;
|
||||
private final Span span;
|
||||
|
||||
public ServerReceivedEvent(Object source, Span span) {
|
||||
this(source, null, span);
|
||||
}
|
||||
|
||||
public ServerReceivedEvent(Object source, Span parent, Span span) {
|
||||
super(source);
|
||||
this.parent = parent;
|
||||
this.span = span;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.event;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@SuppressWarnings("serial")
|
||||
public class ServerSentEvent extends ApplicationEvent {
|
||||
|
||||
private final Span parent;
|
||||
private final Span span;
|
||||
|
||||
public ServerSentEvent(Object source, Span span) {
|
||||
this(source, null, span);
|
||||
}
|
||||
|
||||
public ServerSentEvent(Object source, Span parent, Span span) {
|
||||
super(source);
|
||||
this.parent = parent;
|
||||
this.span = span;
|
||||
}
|
||||
}
|
||||
@@ -34,9 +34,15 @@ import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.cloud.sleuth.MilliSpan;
|
||||
import org.springframework.cloud.sleuth.MilliSpan.MilliSpanBuilder;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Trace;
|
||||
import org.springframework.cloud.sleuth.TraceContextHolder;
|
||||
import org.springframework.cloud.sleuth.TraceScope;
|
||||
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
|
||||
import org.springframework.cloud.sleuth.event.ServerSentEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
@@ -56,7 +62,7 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE + 5)
|
||||
public class TraceFilter extends OncePerRequestFilter {
|
||||
public class TraceFilter extends OncePerRequestFilter implements ApplicationEventPublisherAware {
|
||||
|
||||
protected static final String TRACE_REQUEST_ATTR = TraceFilter.class.getName()
|
||||
+ ".TRACE";
|
||||
@@ -68,6 +74,8 @@ public class TraceFilter extends OncePerRequestFilter {
|
||||
private final Pattern skipPattern;
|
||||
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
public TraceFilter(Trace trace) {
|
||||
this.trace = trace;
|
||||
this.skipPattern = DEFAULT_SKIP_PATTERN;
|
||||
@@ -78,6 +86,11 @@ public class TraceFilter extends OncePerRequestFilter {
|
||||
this.skipPattern = skipPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
@@ -117,7 +130,9 @@ public class TraceFilter extends OncePerRequestFilter {
|
||||
span.remote(true);
|
||||
|
||||
// TODO: trace description?
|
||||
traceScope = this.trace.startSpan(name, span.build());
|
||||
Span parent = span.build();
|
||||
traceScope = this.trace.startSpan(name, parent);
|
||||
publish(new ServerReceivedEvent(this, parent, traceScope.getSpan()));
|
||||
request.setAttribute(TRACE_REQUEST_ATTR, traceScope);
|
||||
// Send new span id back
|
||||
addToResponseIfNotPresent(response, TRACE_ID_NAME, traceScope.getSpan()
|
||||
@@ -144,12 +159,19 @@ public class TraceFilter extends OncePerRequestFilter {
|
||||
}
|
||||
if (traceScope != null) {
|
||||
addResponseAnnotations(response);
|
||||
publish(new ServerSentEvent(this, traceScope.getSavedSpan(), traceScope.getSpan()));
|
||||
traceScope.close();
|
||||
}
|
||||
TraceContextHolder.removeCurrentSpan();
|
||||
}
|
||||
}
|
||||
|
||||
private void publish(ApplicationEvent event) {
|
||||
if (this.publisher!=null) {
|
||||
this.publisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: move annotation keys to constants
|
||||
protected void addRequestAnnotations(HttpServletRequest request) {
|
||||
String uri = this.urlPathHelper.getPathWithinApplication(request);
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.cloud.sleuth.Trace;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -63,10 +64,12 @@ public class TraceWebAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public FilterRegistrationBean traceFilter() {
|
||||
public FilterRegistrationBean traceFilter(ApplicationEventPublisher publisher) {
|
||||
Pattern pattern = StringUtils.hasText(this.skipPattern) ? Pattern.compile(this.skipPattern)
|
||||
: TraceFilter.DEFAULT_SKIP_PATTERN;
|
||||
return new FilterRegistrationBean(new TraceFilter(this.trace, pattern));
|
||||
TraceFilter filter = new TraceFilter(this.trace, pattern);
|
||||
filter.setApplicationEventPublisher(publisher);
|
||||
return new FilterRegistrationBean(filter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.zuul;
|
||||
|
||||
import static org.springframework.cloud.sleuth.TraceContextHolder.getCurrentSpan;
|
||||
|
||||
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class TracePostZuulFilter extends ZuulFilter implements
|
||||
ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldFilter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object run() {
|
||||
// TODO: the client sent event should come from the client not the filter!
|
||||
publish(new ClientReceivedEvent(this, getCurrentSpan()));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterType() {
|
||||
return "post";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int filterOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void publish(ApplicationEvent event) {
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,6 +71,7 @@ ApplicationEventPublisherAware {
|
||||
setHeader(response, SPAN_NAME_NAME, getCurrentSpan().getName());
|
||||
setHeader(response, PARENT_ID_NAME, getParentId(getCurrentSpan()));
|
||||
setHeader(response, PROCESS_ID_NAME, getCurrentSpan().getProcessId());
|
||||
// TODO: the client sent event should come from the client not the filter!
|
||||
publish(new ClientSentEvent(this, getCurrentSpan()));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
||||
@@ -48,7 +48,7 @@ import com.netflix.niws.client.http.RestClient;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommandFactory
|
||||
implements ApplicationEventPublisherAware {
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
@@ -70,7 +70,7 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
|
||||
return new TraceRestClientRibbonCommand(
|
||||
context.getServiceId(), restClient, getVerb(context.getVerb()),
|
||||
context.getUri(), context.getRetryable(), context.getHeaders(),
|
||||
context.getParams(), context.getRequestEntity(), publisher);
|
||||
context.getParams(), context.getRequestEntity(), this.publisher);
|
||||
}
|
||||
|
||||
class TraceRestClientRibbonCommand extends RestClientRibbonCommand {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class TraceZuulAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TracePreZuulFilter traceZuulFilter() {
|
||||
public TracePreZuulFilter tracePreZuulFilter() {
|
||||
return new TracePreZuulFilter();
|
||||
}
|
||||
|
||||
@@ -53,4 +53,10 @@ public class TraceZuulAutoConfiguration {
|
||||
return new TraceRestClientRibbonCommandFactory(factory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TracePostZuulFilter tracePostZuulFilter() {
|
||||
return new TracePostZuulFilter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.TimelineAnnotation;
|
||||
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
|
||||
import org.springframework.cloud.sleuth.event.ClientSentEvent;
|
||||
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
|
||||
import org.springframework.cloud.sleuth.event.ServerSentEvent;
|
||||
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
|
||||
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
@@ -65,10 +67,15 @@ public class ZipkinSpanListener {
|
||||
@EventListener
|
||||
@Order(0)
|
||||
public void start(SpanAcquiredEvent event) {
|
||||
event.getSpan().addTimelineAnnotation("acquire");
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@Order(0)
|
||||
public void serverReceived(ServerReceivedEvent event) {
|
||||
if (event.getParent() != null && event.getParent().isRemote()) {
|
||||
event.getParent().addTimelineAnnotation(zipkinCoreConstants.SERVER_RECV);
|
||||
}
|
||||
event.getSpan().addTimelineAnnotation("acquire");
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@@ -85,11 +92,16 @@ public class ZipkinSpanListener {
|
||||
|
||||
@EventListener
|
||||
@Order(0)
|
||||
public void release(SpanReleasedEvent event) {
|
||||
public void serverSend(ServerSentEvent event) {
|
||||
if (event.getParent() != null && event.getParent().isRemote()) {
|
||||
event.getParent().addTimelineAnnotation(zipkinCoreConstants.SERVER_SEND);
|
||||
this.spanCollector.collect(convert(event.getParent()));
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@Order(0)
|
||||
public void release(SpanReleasedEvent event) {
|
||||
event.getSpan().addTimelineAnnotation("release");
|
||||
this.spanCollector.collect(convert(event.getSpan()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user