From 35bda8cc5bac25666358d92a730661336163b94a Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 22 Jun 2015 12:41:44 -0600 Subject: [PATCH 01/34] Initial interfaces and supporting classes. Move s-c-s-correlation to s-c-s-logging --- docs/src/main/asciidoc/intro.adoc | 11 ++ .../cloud/sleuth/trace/Sampler.java | 33 +++++ .../cloud/sleuth/trace/Span.java | 116 ++++++++++++++++++ .../cloud/sleuth/trace/SpanReceiver.java | 13 ++ .../sleuth/trace/TimelineAnnotation.java | 12 ++ .../cloud/sleuth/trace/Trace.java | 88 +++++++++++++ .../cloud/sleuth/trace/TraceInfo.java | 12 ++ .../cloud/sleuth/trace/TraceScope.java | 7 ++ .../CorrelationIdAspect.java | 6 +- .../CorrelationIdAutoConfiguration.java | 2 +- .../CorrelationIdFilter.java | 17 ++- .../CorrelationIdHolder.java | 2 +- ...ationIdSettingRestTemplateInterceptor.java | 2 +- .../CorrelationIdUpdater.java | 6 +- .../UuidGenerator.java | 2 +- .../hystrix/CorrelatedCommand.java | 6 +- .../ScheduledTaskWithCorrelationIdAspect.java | 6 +- .../TaskSchedulingConfiguration.java | 4 +- .../main/resources/META-INF/spring.factories | 2 +- .../CorrelationIdAspectISpec.groovy | 2 +- .../CorrelationIdFilterISpec.groovy | 2 + .../CorrelationIdFilterSkipPatternSpec.groovy | 3 + .../CorrelationIdUpdaterSpec.groovy | 2 + ...CorrelationIdSettingIntegrationSpec.groovy | 2 +- .../hystrix/CorrelatedCommandSpec.groovy | 5 +- ...CorrelationIdOnScheduledMethodISpec.groovy | 3 +- .../TestBeanWithScheduledMethod.groovy | 2 +- 27 files changed, 332 insertions(+), 36 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Sampler.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanReceiver.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TimelineAnnotation.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/CorrelationIdAspect.java (95%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/CorrelationIdAutoConfiguration.java (97%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/CorrelationIdFilter.java (89%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/CorrelationIdHolder.java (95%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/CorrelationIdSettingRestTemplateInterceptor.java (97%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/CorrelationIdUpdater.java (94%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/UuidGenerator.java (93%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/hystrix/CorrelatedCommand.java (88%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/scheduling/ScheduledTaskWithCorrelationIdAspect.java (91%) rename spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/{correlation => logging}/scheduling/TaskSchedulingConfiguration.java (90%) diff --git a/docs/src/main/asciidoc/intro.adoc b/docs/src/main/asciidoc/intro.adoc index fa1ae62d3..0fe0cdd50 100644 --- a/docs/src/main/asciidoc/intro.adoc +++ b/docs/src/main/asciidoc/intro.adoc @@ -1,2 +1,13 @@ TODO: intro Spring Cloud Sleuth +=== Terminology + +Spring Cloud Sleuth borrows http://research.google.com/pubs/pub36356.html[Dapper's] terminology. + +*Span:* The basic unit of work. For example, sending an RPC is a new span, as is sending a response to an RPC. Span's are identified by a unique 64-bit ID for the span and another 64-bit ID for the trace the span is a part of. Spans also have other data, such as descriptions, key-value annotations, the ID of the span that caused them, and process ID's (normally IP address). + +Spans are started and stopped, and they keep track of their timing information. Once you create a span, you must stop it at some point in the future. + +*Trace:* A set of spans forming a tree-like structure. For example, if you are running a distributed big-data store, a trace might be formed by a put request. + + diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Sampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Sampler.java new file mode 100644 index 000000000..033416eb9 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Sampler.java @@ -0,0 +1,33 @@ +package org.springframework.cloud.sleuth.trace; + +/** + * Extremely simple callback to determine the frequency that an action should be + * performed. + *

+ * 'T' is the object type you require to create a more advanced sampling + * function. For example if there is some RPC information in a 'Call' object, + * you might implement Sampler. Then when the RPC is received you can call + * one of the Trace.java functions that takes the extra 'info' parameter, which + * will be passed into the next function you implemented. + *

+ * For the example above, the next(T info) function may look like this + *

+ *

+ * public boolean next(T info) {
+ *   if (info == null) {
+ *     return false;
+ *   } else if (info.getName().equals("get")) {
+ *     return Math.random() > 0.5;
+ *   } else if (info.getName().equals("put")) {
+ *     return Math.random() > 0.25;
+ *   } else {
+ *     return false;
+ *   }
+ * }
+ * 
+ * 
+ * This would trace 50% of all gets, 75% of all puts and would not trace any other requests. + */ +public interface Sampler { + public boolean next(T info); +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java new file mode 100644 index 000000000..48c8f656d --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java @@ -0,0 +1,116 @@ +package org.springframework.cloud.sleuth.trace; + +import java.util.List; +import java.util.Map; + +/** + * Base interface for gathering and reporting statistics about a block of + * execution. + *

+ * Spans should form a directed acyclic graph structure. It should be possible + * to keep following the parents of a span until you arrive at a span with no + * parents.

+ */ +public interface Span { + /** + * The block has completed, stop the clock + */ + void stop(); + + /** + * Get the start time, in milliseconds + */ + long getStartTimeMillis(); + + /** + * Get the stop time, in milliseconds + */ + long getStopTimeMillis(); + + /** + * Return the total amount of time elapsed since start was called, if running, + * or difference between stop and start + */ + long getAccumulatedMillis(); + + /** + * Has the span been started and not yet stopped? + */ + boolean isRunning(); + + /** + * Return a textual description of this span.

+ *

+ * Will never be null. + */ + String getDescription(); + + /** + * A pseudo-unique (random) number assigned to this span instance.

+ *

+ * The spanId is immutable and cannot be changed. It is safe to access this + * from multiple threads. + */ + long getSpanId(); + + /** + * A pseudo-unique (random) number assigned to the trace associated with this + * span + */ + long getTraceId(); + + /** + * Create a child span of this span with the given description + */ + Span child(String description); + + /** + * Returns the parent IDs of the span.

+ *

+ * The array will be empty if there are no parents. + */ + long[] getParents(); + + /** + * Set the parents of this span.

+ *

+ * Any existing parents will be cleared by this call. + */ + void setParents(long[] parents); + + /** + * Add a data annotation associated with this span + */ + void addKVAnnotation(String key, String value); + + /** + * Add a timeline annotation associated with this span + */ + void addTimelineAnnotation(String msg); + + /** + * Get data associated with this span (read only)

+ *

+ * Will never be null. + */ + Map getKVAnnotations(); + + /** + * Get any timeline annotations (read only)

+ *

+ * Will never be null. + */ + List getTimelineAnnotations(); + + /** + * Return a unique id for the process from which this Span originated.

+ *

+ * Will never be null. + */ + String getProcessId(); + + /** + * Set the process id of a span. + */ + void setProcessId(String s); +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanReceiver.java new file mode 100644 index 000000000..5a42135dd --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanReceiver.java @@ -0,0 +1,13 @@ +package org.springframework.cloud.sleuth.trace; + +import java.io.Closeable; + +/** + * The collector within a process that is the destination of Spans when a trace is running. + */ +public interface SpanReceiver extends Closeable { + /** + * Called when a Span is stopped and can now be stored. + */ + public void receiveSpan(Span span); +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TimelineAnnotation.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TimelineAnnotation.java new file mode 100644 index 000000000..b0b18dc3e --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TimelineAnnotation.java @@ -0,0 +1,12 @@ +package org.springframework.cloud.sleuth.trace; + +import lombok.Data; + +/** + * @author Spencer Gibb + */ +@Data +public class TimelineAnnotation { + private final long time; + private final String msg; +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java new file mode 100644 index 000000000..0728c44ab --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java @@ -0,0 +1,88 @@ +package org.springframework.cloud.sleuth.trace; + +/** + * The Trace class is the primary way to interact with the library. It provides + * methods to create and manipulate spans. + * + * A 'Span' represents a length of time. It has many other attributes such as a + * description, ID, and even potentially a set of key/value strings attached to + * it. + * + * Each thread in your application has a single currently active currentSpan + * associated with it. When this is non-null, it represents the current + * operation that the thread is doing. Spans are NOT thread-safe, and must + * never be used by multiple threads at once. With care, it is possible to + * safely pass a Span object between threads, but in most cases this is not + * necessary. + * + * A 'TraceScope' can either be empty, or contain a Span. TraceScope objects + * implement the Java's Closeable interface. Similar to file descriptors, they + * must be closed after they are created. When a TraceScope contains a Span, + * this span is closed when the scope is closed. + * + * The 'startSpan' methods in this class do a few things: + *

+ * + * Closing a TraceScope does a few things: + * + */ +public interface Trace { + + /** + * Creates a new trace scope. + *

+ * If this thread has a currently active trace span, the trace scope we create + * here will contain a new span descending from the currently active span. + * If there is no currently active trace span, the trace scope we create will + * be empty. + * + * @param description The description field for the new span to create. + */ + public TraceScope startSpan(String description); + + public TraceScope startSpan(String description, TraceInfo tinfo); + + /** + * Creates a new trace scope. + *

+ * If this thread has a currently active trace span, it must be the 'parent' + * span that you pass in here as a parameter. The trace scope we create here + * will contain a new span which is a child of 'parent'. + * + * @param description The description field for the new span to create. + */ + public TraceScope startSpan(String description, Span parent); + + public TraceScope startSpan(String description, Sampler s); + + public TraceScope startSpan(String description, Sampler s, T info); + + /** + * Pick up an existing span from another thread. + */ + public TraceScope continueSpan(Span s); + + /** + * Adds a data annotation to the current span if tracing is currently on. + */ + public void addKVAnnotation(String key, String value); + + /** + * Returns true if the current thread is a part of a trace, false otherwise. + */ + public boolean isTracing(); + + /** + * If we are tracing, return the current span, else null + * + * @return Span representing the current trace, or null if not tracing. + */ + public Span currentSpan(); +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java new file mode 100644 index 000000000..4a9f059dd --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java @@ -0,0 +1,12 @@ +package org.springframework.cloud.sleuth.trace; + +import lombok.Data; + +/** + * @author Spencer Gibb + */ +@Data +public class TraceInfo { + private final long traceId; + private final long spanId; +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java new file mode 100644 index 000000000..f138a5afa --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java @@ -0,0 +1,7 @@ +package org.springframework.cloud.sleuth.trace; + +/** + * @author Spencer Gibb + */ +public class TraceScope { +} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdAspect.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAspect.java similarity index 95% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdAspect.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAspect.java index b73665aba..23b995ded 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdAspect.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAspect.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation; +package org.springframework.cloud.sleuth.logging; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -32,8 +32,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; -import static org.springframework.cloud.sleuth.correlation.CorrelationIdHolder.CORRELATION_ID_HEADER; - /** * Aspect that adds correlation id to *

@@ -115,7 +113,7 @@ public class CorrelationIdAspect { private HttpEntity createNewHttpEntity(HttpEntity httpEntity, String correlationId) { HttpHeaders newHttpHeaders = new HttpHeaders(); newHttpHeaders.putAll(httpEntity.getHeaders()); - newHttpHeaders.add(CORRELATION_ID_HEADER, correlationId); + newHttpHeaders.add(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); return new HttpEntity(httpEntity.getBody(), newHttpHeaders); } diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdAutoConfiguration.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAutoConfiguration.java similarity index 97% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdAutoConfiguration.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAutoConfiguration.java index 51e71dfac..4d5f4aac2 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdAutoConfiguration.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAutoConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation; +package org.springframework.cloud.sleuth.logging; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Value; diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdFilter.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdFilter.java similarity index 89% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdFilter.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdFilter.java index 96a6aef07..78aabfd99 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdFilter.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation; +package org.springframework.cloud.sleuth.logging; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -30,7 +30,6 @@ import java.lang.invoke.MethodHandles; import java.util.concurrent.Callable; import java.util.regex.Pattern; -import static org.springframework.cloud.sleuth.correlation.CorrelationIdHolder.CORRELATION_ID_HEADER; import static org.springframework.util.StringUtils.hasText; /** @@ -87,7 +86,7 @@ public class CorrelationIdFilter extends OncePerRequestFilter { return withLoggingAs("response", new Callable() { @Override public String call() throws Exception { - return response.getHeader(CORRELATION_ID_HEADER); + return response.getHeader(CorrelationIdHolder.CORRELATION_ID_HEADER); } }); } @@ -96,7 +95,7 @@ public class CorrelationIdFilter extends OncePerRequestFilter { return withLoggingAs("request", new Callable() { @Override public String call() throws Exception { - return request.getHeader(CORRELATION_ID_HEADER); + return request.getHeader(CorrelationIdHolder.CORRELATION_ID_HEADER); } }); } @@ -104,7 +103,7 @@ public class CorrelationIdFilter extends OncePerRequestFilter { private String withLoggingAs(String whereWasFound, Callable correlationIdGetter) { String correlationId = tryToGetCorrelationId(correlationIdGetter); if (hasText(correlationId)) { - MDC.put(CORRELATION_ID_HEADER, correlationId); + MDC.put(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); log.debug("Found correlationId in " + whereWasFound + ": " + correlationId); } return correlationId; @@ -121,7 +120,7 @@ public class CorrelationIdFilter extends OncePerRequestFilter { private String createNewCorrIdIfEmpty() { String currentCorrId = uuidGenerator.create(); - MDC.put(CORRELATION_ID_HEADER, currentCorrId); + MDC.put(CorrelationIdHolder.CORRELATION_ID_HEADER, currentCorrId); log.debug("Generating new correlationId: " + currentCorrId); return currentCorrId; } @@ -134,13 +133,13 @@ public class CorrelationIdFilter extends OncePerRequestFilter { } private void addCorrelationIdToResponseIfNotPresent(HttpServletResponse response, String correlationId) { - if (!hasText(response.getHeader(CORRELATION_ID_HEADER))) { - response.addHeader(CORRELATION_ID_HEADER, correlationId); + if (!hasText(response.getHeader(CorrelationIdHolder.CORRELATION_ID_HEADER))) { + response.addHeader(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); } } private void cleanupCorrelationId() { - MDC.remove(CORRELATION_ID_HEADER); + MDC.remove(CorrelationIdHolder.CORRELATION_ID_HEADER); CorrelationIdHolder.remove(); } diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdHolder.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdHolder.java similarity index 95% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdHolder.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdHolder.java index 6474887a5..291bc747a 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdHolder.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdHolder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation; +package org.springframework.cloud.sleuth.logging; /** * Component that stores correlation id using {@link ThreadLocal} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdSettingRestTemplateInterceptor.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdSettingRestTemplateInterceptor.java similarity index 97% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdSettingRestTemplateInterceptor.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdSettingRestTemplateInterceptor.java index 3f1b6fcb8..c17a6fc57 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdSettingRestTemplateInterceptor.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdSettingRestTemplateInterceptor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation; +package org.springframework.cloud.sleuth.logging; import lombok.SneakyThrows; import org.springframework.http.HttpRequest; diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdater.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdUpdater.java similarity index 94% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdater.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdUpdater.java index 0becfca32..29f2afbcc 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdater.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdUpdater.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation; +package org.springframework.cloud.sleuth.logging; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,8 +23,6 @@ import org.springframework.util.StringUtils; import java.lang.invoke.MethodHandles; import java.util.concurrent.Callable; -import static org.springframework.cloud.sleuth.correlation.CorrelationIdHolder.CORRELATION_ID_HEADER; - /** * Class that takes care of updating all necessary components with new value * of correlation id. @@ -45,7 +43,7 @@ public class CorrelationIdUpdater { if (StringUtils.hasText(correlationId)) { log.debug("Updating correlationId with value: [" + correlationId + "]"); CorrelationIdHolder.set(correlationId); - MDC.put(CORRELATION_ID_HEADER, correlationId); + MDC.put(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); } } diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/UuidGenerator.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/UuidGenerator.java similarity index 93% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/UuidGenerator.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/UuidGenerator.java index e130097a8..a289a0a0a 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/UuidGenerator.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/UuidGenerator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation; +package org.springframework.cloud.sleuth.logging; import java.util.UUID; diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommand.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/hystrix/CorrelatedCommand.java similarity index 88% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommand.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/hystrix/CorrelatedCommand.java index 3012c0f8e..8d9e498ef 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommand.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/hystrix/CorrelatedCommand.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation.hystrix; +package org.springframework.cloud.sleuth.logging.hystrix; import com.netflix.hystrix.HystrixCommand; import com.netflix.hystrix.HystrixCommandGroupKey; -import org.springframework.cloud.sleuth.correlation.CorrelationIdHolder; -import org.springframework.cloud.sleuth.correlation.CorrelationIdUpdater; +import org.springframework.cloud.sleuth.logging.CorrelationIdHolder; +import org.springframework.cloud.sleuth.logging.CorrelationIdUpdater; import java.util.concurrent.Callable; diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/scheduling/ScheduledTaskWithCorrelationIdAspect.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/ScheduledTaskWithCorrelationIdAspect.java similarity index 91% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/scheduling/ScheduledTaskWithCorrelationIdAspect.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/ScheduledTaskWithCorrelationIdAspect.java index 6af07d5a7..63fed0ecc 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/scheduling/ScheduledTaskWithCorrelationIdAspect.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/ScheduledTaskWithCorrelationIdAspect.java @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation.scheduling; +package org.springframework.cloud.sleuth.logging.scheduling; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cloud.sleuth.correlation.CorrelationIdUpdater; -import org.springframework.cloud.sleuth.correlation.UuidGenerator; +import org.springframework.cloud.sleuth.logging.CorrelationIdUpdater; +import org.springframework.cloud.sleuth.logging.UuidGenerator; import org.springframework.scheduling.annotation.Scheduled; import java.lang.invoke.MethodHandles; diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/scheduling/TaskSchedulingConfiguration.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/TaskSchedulingConfiguration.java similarity index 90% rename from spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/scheduling/TaskSchedulingConfiguration.java rename to spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/TaskSchedulingConfiguration.java index e0ace7fbe..3e825f7ef 100644 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/correlation/scheduling/TaskSchedulingConfiguration.java +++ b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/TaskSchedulingConfiguration.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.correlation.scheduling; +package org.springframework.cloud.sleuth.logging.scheduling; -import org.springframework.cloud.sleuth.correlation.UuidGenerator; +import org.springframework.cloud.sleuth.logging.UuidGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; diff --git a/spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories index 387f34393..ec398fdbf 100644 --- a/spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories @@ -1,3 +1,3 @@ # Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.sleuth.correlation.CorrelationIdAutoConfiguration +org.springframework.cloud.sleuth.correlation.logging.CorrelationIdAutoConfiguration diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy index a5a368a2f..e47e47720 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy @@ -28,7 +28,7 @@ import java.util.concurrent.Callable import java.util.concurrent.TimeUnit import static com.github.tomakehurst.wiremock.client.WireMock.* -import static org.springframework.cloud.sleuth.correlation.CorrelationIdHolder.CORRELATION_ID_HEADER +import static org.springframework.cloud.sleuth.logging.CorrelationIdHolder.CORRELATION_ID_HEADER @ContextConfiguration(classes = [CorrelationIdAspectSpecConfiguration], loader = SpringApplicationContextLoader) class CorrelationIdAspectISpec extends MvcCorrelationIdSettingIntegrationSpec { diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy index f825632aa..282191849 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy @@ -4,6 +4,8 @@ import org.slf4j.MDC import org.springframework.boot.test.SpringApplicationContextLoader import org.springframework.cloud.sleuth.correlation.base.BaseConfiguration import org.springframework.cloud.sleuth.correlation.base.MvcCorrelationIdSettingIntegrationSpec +import org.springframework.cloud.sleuth.logging.CorrelationIdAutoConfiguration +import org.springframework.cloud.sleuth.logging.CorrelationIdHolder import org.springframework.http.MediaType import org.springframework.test.context.ContextConfiguration import org.springframework.test.web.servlet.MvcResult diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy index b4841a435..55dc7f241 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy @@ -1,5 +1,8 @@ package org.springframework.cloud.sleuth.correlation +import org.springframework.cloud.sleuth.logging.CorrelationIdFilter +import org.springframework.cloud.sleuth.logging.CorrelationIdHolder +import org.springframework.cloud.sleuth.logging.UuidGenerator import spock.lang.Specification import spock.lang.Unroll diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy index b6cd61c7f..1d68af8c1 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy @@ -1,6 +1,8 @@ package org.springframework.cloud.sleuth.correlation import groovyx.gpars.GParsPool +import org.springframework.cloud.sleuth.logging.CorrelationIdHolder +import org.springframework.cloud.sleuth.logging.CorrelationIdUpdater import spock.lang.Specification import java.util.concurrent.Callable diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy index 6c55d7e19..2361197b9 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy @@ -1,6 +1,6 @@ package org.springframework.cloud.sleuth.correlation.base -import org.springframework.cloud.sleuth.correlation.CorrelationIdFilter +import org.springframework.cloud.sleuth.logging.CorrelationIdFilter import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder class MvcCorrelationIdSettingIntegrationSpec extends org.springframework.cloud.sleuth.correlation.base.MvcWiremockIntegrationSpec { diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy index e97c65761..e572217a0 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy @@ -2,8 +2,9 @@ package org.springframework.cloud.sleuth.correlation.hystrix import com.netflix.hystrix.HystrixCommand import com.netflix.hystrix.HystrixCommandGroupKey -import org.springframework.cloud.sleuth.correlation.CorrelationIdHolder -import org.springframework.cloud.sleuth.correlation.CorrelationIdUpdater +import org.springframework.cloud.sleuth.logging.CorrelationIdHolder +import org.springframework.cloud.sleuth.logging.CorrelationIdUpdater +import org.springframework.cloud.sleuth.logging.hystrix.CorrelatedCommand import spock.lang.Specification class CorrelatedCommandSpec extends Specification { diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy index 1d58c1c50..aef08e234 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy @@ -2,7 +2,8 @@ package org.springframework.cloud.sleuth.correlation.scheduling import org.springframework.beans.factory.annotation.Autowired import org.springframework.cloud.sleuth.correlation.base.BaseConfiguration -import org.springframework.cloud.sleuth.correlation.CorrelationIdAutoConfiguration +import org.springframework.cloud.sleuth.logging.CorrelationIdAutoConfiguration +import org.springframework.cloud.sleuth.logging.scheduling.TaskSchedulingConfiguration import org.springframework.test.context.ContextConfiguration import spock.lang.Specification import spock.util.concurrent.PollingConditions diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy index 66eb128ed..212b159c3 100644 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy +++ b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy @@ -1,6 +1,6 @@ package org.springframework.cloud.sleuth.correlation.scheduling -import org.springframework.cloud.sleuth.correlation.CorrelationIdHolder +import org.springframework.cloud.sleuth.logging.CorrelationIdHolder import org.springframework.scheduling.annotation.Scheduled class TestBeanWithScheduledMethod { From 4d6f0cfcfd73065feabd4ab9186dda3bef926dee Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 22 Jun 2015 13:26:15 -0600 Subject: [PATCH 02/34] updates to interfaces and supporting classes --- pom.xml | 2 +- .../cloud/sleuth/trace/MilliSpan.java | 68 +++++++++++++++++++ .../cloud/sleuth/trace/Span.java | 25 ++----- .../cloud/sleuth/trace/SpanHolder.java | 16 +++++ .../cloud/sleuth/trace/Trace.java | 4 ++ .../cloud/sleuth/trace/TraceScope.java | 37 +++++++++- 6 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java diff --git a/pom.xml b/pom.xml index 58da79494..96e8782b4 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ org.projectlombok lombok - 1.12.6 + 1.16.4 provided diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java new file mode 100644 index 000000000..da2a320a4 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java @@ -0,0 +1,68 @@ +package org.springframework.cloud.sleuth.trace; + +import lombok.Builder; +import lombok.Data; +import lombok.Singular; + +import java.util.List; +import java.util.Map; + +/** + * @author Spencer Gibb + */ +@Data +@Builder +public class MilliSpan implements Span { + private final long begin; + private long end; + private final String description; + private final String traceId; + @Singular + private final List parents; + private final String spanId; + private final Map kVAnnotations; + private final String processId; + @Singular + private final List timelineAnnotations; + + @Override + public synchronized void stop() { + if (end == 0) { + if (begin == 0) + throw new IllegalStateException("Span for " + description + + " has not been started"); + end = System.currentTimeMillis(); + //TODO figure out how to Trace.deliver(this) + } + } + + @Override + public synchronized long getAccumulatedMillis() { + if (begin == 0) + return 0; + if (end > 0) + return end - begin; + return System.currentTimeMillis() - begin; + } + + @Override + public synchronized boolean isRunning() { + return begin != 0 && end == 0; + } + + @Override + public Span child(String description) { + return null; + } + + @Override + public void addKVAnnotation(String key, String value) { + kVAnnotations.put(key, value); + } + + @Override + public void addTimelineAnnotation(String msg) { + timelineAnnotations.add(new TimelineAnnotation(System.currentTimeMillis(), msg)); + } + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java index 48c8f656d..673b0d6be 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java @@ -1,5 +1,6 @@ package org.springframework.cloud.sleuth.trace; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -20,12 +21,12 @@ public interface Span { /** * Get the start time, in milliseconds */ - long getStartTimeMillis(); + long getBegin(); /** * Get the stop time, in milliseconds */ - long getStopTimeMillis(); + long getEnd(); /** * Return the total amount of time elapsed since start was called, if running, @@ -51,13 +52,13 @@ public interface Span { * The spanId is immutable and cannot be changed. It is safe to access this * from multiple threads. */ - long getSpanId(); + String getSpanId(); /** * A pseudo-unique (random) number assigned to the trace associated with this * span */ - long getTraceId(); + String getTraceId(); /** * Create a child span of this span with the given description @@ -67,16 +68,9 @@ public interface Span { /** * Returns the parent IDs of the span.

*

- * The array will be empty if there are no parents. + * The collection will be empty if there are no parents. */ - long[] getParents(); - - /** - * Set the parents of this span.

- *

- * Any existing parents will be cleared by this call. - */ - void setParents(long[] parents); + List getParents(); /** * Add a data annotation associated with this span @@ -108,9 +102,4 @@ public interface Span { * Will never be null. */ String getProcessId(); - - /** - * Set the process id of a span. - */ - void setProcessId(String s); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java new file mode 100644 index 000000000..38a054b16 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java @@ -0,0 +1,16 @@ +package org.springframework.cloud.sleuth.trace; + +/** + * @author Spencer Gibb + */ +public class SpanHolder { + private static final ThreadLocal currentSpan = new ThreadLocal<>(); + + public Span getCurrentSpan() { + return currentSpan.get(); + } + + public void setCurrentSpan(Span span) { + currentSpan.set(span); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java index 0728c44ab..6c1f57ea4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java @@ -1,5 +1,7 @@ package org.springframework.cloud.sleuth.trace; +import java.util.Collection; + /** * The Trace class is the primary way to interact with the library. It provides * methods to create and manipulate spans. @@ -85,4 +87,6 @@ public interface Trace { * @return Span representing the current trace, or null if not tracing. */ public Span currentSpan(); + + public void setSpanReceivers(Collection spanReceivers); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java index f138a5afa..803f84f4f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java @@ -1,7 +1,42 @@ package org.springframework.cloud.sleuth.trace; +import lombok.Data; + +import java.io.Closeable; +import java.io.IOException; + /** * @author Spencer Gibb */ -public class TraceScope { +@Data +public class TraceScope implements Closeable { + /** + * the span for this scope + */ + private final Span span; + + /** + * the span that was "current" before this scope was entered + */ + private final Span savedSpan; + + private boolean detached = false; + + /** + * Remove this span as the current thread, but don't stop it yet or + * send it for collection. This is useful if the span object is then + * passed to another thread for use with Trace.continueTrace(). + * + * @return the same Span object + */ + public Span detach() { + //TODO: implement detach + return span; + } + + @Override + public void close() throws IOException { + span.stop(); + //TODO: set savedSpan to currentSpan in SpanHolder + } } From 3a28d4abd709dacabcaac27cb7f54193978e249c Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 22 Jun 2015 13:32:10 -0600 Subject: [PATCH 03/34] updates to interfaces and supporting classes --- .../cloud/sleuth/trace/IdGenerator.java | 8 ++++++++ .../cloud/sleuth/trace/Span.java | 1 - .../cloud/sleuth/trace/Trace.java | 20 +++++++++---------- .../cloud/sleuth/trace/TraceInfo.java | 4 ++-- 4 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/IdGenerator.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/IdGenerator.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/IdGenerator.java new file mode 100644 index 000000000..239833367 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/IdGenerator.java @@ -0,0 +1,8 @@ +package org.springframework.cloud.sleuth.trace; + +/** + * @author Spencer Gibb + */ +public interface IdGenerator { + String create(); +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java index 673b0d6be..c1974b74f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java @@ -1,6 +1,5 @@ package org.springframework.cloud.sleuth.trace; -import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java index 6c1f57ea4..b6a1f2dd5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java @@ -47,9 +47,9 @@ public interface Trace { * * @param description The description field for the new span to create. */ - public TraceScope startSpan(String description); + TraceScope startSpan(String description); - public TraceScope startSpan(String description, TraceInfo tinfo); + TraceScope startSpan(String description, TraceInfo tinfo); /** * Creates a new trace scope. @@ -60,33 +60,33 @@ public interface Trace { * * @param description The description field for the new span to create. */ - public TraceScope startSpan(String description, Span parent); + TraceScope startSpan(String description, Span parent); - public TraceScope startSpan(String description, Sampler s); + TraceScope startSpan(String description, Sampler s); - public TraceScope startSpan(String description, Sampler s, T info); + TraceScope startSpan(String description, Sampler s, T info); /** * Pick up an existing span from another thread. */ - public TraceScope continueSpan(Span s); + TraceScope continueSpan(Span s); /** * Adds a data annotation to the current span if tracing is currently on. */ - public void addKVAnnotation(String key, String value); + void addKVAnnotation(String key, String value); /** * Returns true if the current thread is a part of a trace, false otherwise. */ - public boolean isTracing(); + boolean isTracing(); /** * If we are tracing, return the current span, else null * * @return Span representing the current trace, or null if not tracing. */ - public Span currentSpan(); + Span currentSpan(); - public void setSpanReceivers(Collection spanReceivers); + void setSpanReceivers(Collection spanReceivers); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java index 4a9f059dd..31c8e5dab 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java @@ -7,6 +7,6 @@ import lombok.Data; */ @Data public class TraceInfo { - private final long traceId; - private final long spanId; + private final String traceId; + private final String spanId; } From a7b910ed40002e51b331202edd29c50375a6ac28 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 22 Jun 2015 13:43:18 -0600 Subject: [PATCH 04/34] updates to supporting classes --- .../cloud/sleuth/trace/SpanHolder.java | 11 +++++- .../cloud/sleuth/trace/TraceScope.java | 39 +++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java index 38a054b16..7c04d4e80 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java @@ -1,16 +1,23 @@ package org.springframework.cloud.sleuth.trace; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + /** * @author Spencer Gibb */ public class SpanHolder { private static final ThreadLocal currentSpan = new ThreadLocal<>(); + private static final Log log = LogFactory.getLog(SpanHolder.class); - public Span getCurrentSpan() { + public static Span getCurrentSpan() { return currentSpan.get(); } - public void setCurrentSpan(Span span) { + public static void setCurrentSpan(Span span) { + if (log.isTraceEnabled()) { + log.trace("Setting current span " + span); + } currentSpan.set(span); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java index 803f84f4f..9719f8b52 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java @@ -1,6 +1,7 @@ package org.springframework.cloud.sleuth.trace; import lombok.Data; +import lombok.extern.apachecommons.CommonsLog; import java.io.Closeable; import java.io.IOException; @@ -9,6 +10,7 @@ import java.io.IOException; * @author Spencer Gibb */ @Data +@CommonsLog public class TraceScope implements Closeable { /** * the span for this scope @@ -30,13 +32,44 @@ public class TraceScope implements Closeable { * @return the same Span object */ public Span detach() { - //TODO: implement detach + if (detached) { + error("Tried to detach trace span " + span + " but " + + "it has already been detached."); + } + detached = true; + + Span cur = SpanHolder.getCurrentSpan(); + if (cur != span) { + error("Tried to detach trace span " + span + " but " + + "it is not the current span for the " + + Thread.currentThread().getName() + " thread. You have " + + "probably forgotten to close or detach " + cur); + } else { + SpanHolder.setCurrentSpan(savedSpan); + } return span; } @Override public void close() throws IOException { - span.stop(); - //TODO: set savedSpan to currentSpan in SpanHolder + if (detached) { + return; + } + detached = true; + Span cur = SpanHolder.getCurrentSpan(); + if (cur != span) { + error("Tried to close trace span " + span + " but " + + "it is not the current span for the " + + Thread.currentThread().getName() + " thread. You have " + + "probably forgotten to close or detach " + cur); + } else { + span.stop(); + SpanHolder.setCurrentSpan(savedSpan); + } + } + + private void error(String msg) { + log.error(msg); + throw new RuntimeException(msg); } } From d09f0655595731d5c86841f87138b204c157b006 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 13:50:16 -0600 Subject: [PATCH 05/34] DefaultTrace impl with basic test --- .../cloud/sleuth/trace/DefaultTrace.java | 147 ++++++++++++++++++ .../cloud/sleuth/trace/MilliSpan.java | 36 ++--- .../cloud/sleuth/trace/NullScope.java | 31 ++++ .../cloud/sleuth/trace/Span.java | 5 - .../cloud/sleuth/trace/SpanHolder.java | 5 +- .../cloud/sleuth/trace/Trace.java | 7 +- .../cloud/sleuth/trace/TraceScope.java | 31 ++-- .../cloud/sleuth/trace/Utils.java | 14 ++ .../trace/receiver/ArrayListSpanReceiver.java | 29 ++++ .../sleuth/trace/sampler/AlwaysSampler.java | 13 ++ .../trace/sampler/IsTracingSampler.java | 20 +++ .../cloud/sleuth/trace/DefaultTraceTests.java | 100 ++++++++++++ 12 files changed, 391 insertions(+), 47 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/NullScope.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Utils.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/receiver/ArrayListSpanReceiver.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/AlwaysSampler.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java create mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java new file mode 100644 index 000000000..43d29c228 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java @@ -0,0 +1,147 @@ +package org.springframework.cloud.sleuth.trace; + +import static org.springframework.cloud.sleuth.trace.Utils.error; + +import org.springframework.cloud.sleuth.trace.sampler.IsTracingSampler; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; + +/** + * @author Spencer Gibb + */ +public class DefaultTrace implements Trace { + + //TODO: no default?, let autoconfig + private Sampler defaultSampler = new IsTracingSampler(this); + + private IdGenerator idGenerator = new IdGenerator() { + @Override + public String create() { + return UUID.randomUUID().toString(); + } + }; + + private Collection spanReceivers; + + @Override + public TraceScope startSpan(String description) { + return this.startSpan(description, defaultSampler); + } + + @Override + public TraceScope startSpan(String description, TraceInfo tinfo) { + if (tinfo == null) return continueSpan(null); + MilliSpan span = MilliSpan.builder() + .begin(System.currentTimeMillis()) + .description(description) + .traceId(tinfo.getTraceId()) + .spanId(idGenerator.create()) + .parents(Collections.singletonList(tinfo.getSpanId())) + //TODO: when lombok plugin supports @Singular parent(tinfo.getSpanId()). + .build(); + return continueSpan(span); + } + + @Override + public TraceScope startSpan(String description, Span parent) { + if (parent == null) { + return startSpan(description); + } + Span currentSpan = getCurrentSpan(); + if ((currentSpan != null) && (currentSpan != parent)) { + error("HTrace client error: thread " + + Thread.currentThread().getName() + " tried to start a new Span " + + "with parent " + parent.toString() + ", but there is already a " + + "currentSpan " + currentSpan); + } + return continueSpan(createChild(parent, description)); + } + + @Override + public TraceScope startSpan(String description, Sampler s) { + return startSpan(description, s, null); + } + + @Override + public TraceScope startSpan(String description, Sampler s, T info) { + Span span = null; + if (isTracing() || s.next(info)) { + span = createNew(description); + } + return continueSpan(span); + } + + protected Span createNew(String description) { + Span parent = getCurrentSpan(); + if (parent == null) { + return MilliSpan.builder() + .begin(System.currentTimeMillis()) + .description(description) + .traceId(idGenerator.create()) + .spanId(idGenerator.create()) + .build(); + } else { + return createChild(parent, description); + } + } + + protected Span createChild(Span parent, String childDescription) { + return MilliSpan.builder(). + begin(System.currentTimeMillis()). + description(childDescription). + traceId(parent.getTraceId()). + parents(Collections.singletonList(parent.getSpanId())). + //TODO: when lombok plugin supports @Singular parent(parent.getSpanId()). + spanId(idGenerator.create()). + processId(parent.getProcessId()). + build(); + } + + @Override + public TraceScope continueSpan(Span span) { + // Return an empty TraceScope that does nothing on close + if (span == null) return NullScope.INSTANCE; + Span oldSpan = getCurrentSpan(); + SpanHolder.setCurrentSpan(span); + return new TraceScope(this, span, oldSpan); + } + + protected Span getCurrentSpan() { + return SpanHolder.getCurrentSpan(); + } + + @Override + public void addKVAnnotation(String key, String value) { + Span s = getCurrentSpan(); + if (s != null) { + s.addKVAnnotation(key, value); + } + } + + @Override + public boolean isTracing() { + return getCurrentSpan() != null; + } + + @Override + public void deliver(Span span) { + for (SpanReceiver receiver : spanReceivers) { + receiver.receiveSpan(span); + } + } + + public void setDefaultSampler(Sampler defaultSampler) { + this.defaultSampler = defaultSampler; + } + + public void setIdGenerator(IdGenerator idGenerator) { + this.idGenerator = idGenerator; + } + + @Override + public void setSpanReceivers(Collection spanReceivers) { + this.spanReceivers = spanReceivers; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java index da2a320a4..83124d988 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java @@ -1,29 +1,31 @@ package org.springframework.cloud.sleuth.trace; -import lombok.Builder; -import lombok.Data; -import lombok.Singular; - import java.util.List; import java.util.Map; +import lombok.Builder; +import lombok.Singular; +import lombok.Value; +import lombok.experimental.NonFinal; + /** * @author Spencer Gibb */ -@Data +@Value @Builder public class MilliSpan implements Span { - private final long begin; - private long end; - private final String description; - private final String traceId; + private long begin; + @NonFinal + private long end = 0; + private String description; + private String traceId; @Singular - private final List parents; - private final String spanId; - private final Map kVAnnotations; - private final String processId; + private List parents; + private String spanId; + private Map kVAnnotations; + private String processId; @Singular - private final List timelineAnnotations; + private List timelineAnnotations; @Override public synchronized void stop() { @@ -32,7 +34,6 @@ public class MilliSpan implements Span { throw new IllegalStateException("Span for " + description + " has not been started"); end = System.currentTimeMillis(); - //TODO figure out how to Trace.deliver(this) } } @@ -50,11 +51,6 @@ public class MilliSpan implements Span { return begin != 0 && end == 0; } - @Override - public Span child(String description) { - return null; - } - @Override public void addKVAnnotation(String key, String value) { kVAnnotations.put(key, value); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/NullScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/NullScope.java new file mode 100644 index 000000000..b5941fd77 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/NullScope.java @@ -0,0 +1,31 @@ +package org.springframework.cloud.sleuth.trace; + +/** + * @author Spencer Gibb + */ +/** + * Singleton instance representing an empty {@link TraceScope}. + */ +public final class NullScope extends TraceScope { + + public static final TraceScope INSTANCE = new NullScope(); + + private NullScope() { + super(null, null, null); + } + + @Override + public Span detach() { + return null; + } + + @Override + public void close() { + return; + } + + @Override + public String toString() { + return "NullScope"; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java index c1974b74f..dfd34b9d1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java @@ -59,11 +59,6 @@ public interface Span { */ String getTraceId(); - /** - * Create a child span of this span with the given description - */ - Span child(String description); - /** * Returns the parent IDs of the span.

*

diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java index 7c04d4e80..3b617fe97 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java @@ -1,14 +1,13 @@ package org.springframework.cloud.sleuth.trace; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import lombok.extern.apachecommons.CommonsLog; /** * @author Spencer Gibb */ +@CommonsLog public class SpanHolder { private static final ThreadLocal currentSpan = new ThreadLocal<>(); - private static final Log log = LogFactory.getLog(SpanHolder.class); public static Span getCurrentSpan() { return currentSpan.get(); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java index b6a1f2dd5..fee6cfb96 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java @@ -81,12 +81,7 @@ public interface Trace { */ boolean isTracing(); - /** - * If we are tracing, return the current span, else null - * - * @return Span representing the current trace, or null if not tracing. - */ - Span currentSpan(); + public void deliver(Span span); void setSpanReceivers(Collection spanReceivers); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java index 9719f8b52..3e0d74d54 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java @@ -1,17 +1,18 @@ package org.springframework.cloud.sleuth.trace; -import lombok.Data; -import lombok.extern.apachecommons.CommonsLog; - import java.io.Closeable; -import java.io.IOException; + +import lombok.Data; +import lombok.SneakyThrows; /** * @author Spencer Gibb */ @Data -@CommonsLog public class TraceScope implements Closeable { + + private final Trace trace; + /** * the span for this scope */ @@ -24,6 +25,12 @@ public class TraceScope implements Closeable { private boolean detached = false; + public TraceScope(Trace trace, Span span, Span savedSpan) { + this.trace = trace; + this.span = span; + this.savedSpan = savedSpan; + } + /** * Remove this span as the current thread, but don't stop it yet or * send it for collection. This is useful if the span object is then @@ -33,14 +40,14 @@ public class TraceScope implements Closeable { */ public Span detach() { if (detached) { - error("Tried to detach trace span " + span + " but " + + Utils.error("Tried to detach trace span " + span + " but " + "it has already been detached."); } detached = true; Span cur = SpanHolder.getCurrentSpan(); if (cur != span) { - error("Tried to detach trace span " + span + " but " + + Utils.error("Tried to detach trace span " + span + " but " + "it is not the current span for the " + Thread.currentThread().getName() + " thread. You have " + "probably forgotten to close or detach " + cur); @@ -51,25 +58,23 @@ public class TraceScope implements Closeable { } @Override - public void close() throws IOException { + @SneakyThrows + public void close() { if (detached) { return; } detached = true; Span cur = SpanHolder.getCurrentSpan(); if (cur != span) { - error("Tried to close trace span " + span + " but " + + Utils.error("Tried to close trace span " + span + " but " + "it is not the current span for the " + Thread.currentThread().getName() + " thread. You have " + "probably forgotten to close or detach " + cur); } else { span.stop(); + trace.deliver(span); SpanHolder.setCurrentSpan(savedSpan); } } - private void error(String msg) { - log.error(msg); - throw new RuntimeException(msg); - } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Utils.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Utils.java new file mode 100644 index 000000000..3c8ecc4ac --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Utils.java @@ -0,0 +1,14 @@ +package org.springframework.cloud.sleuth.trace; + +import lombok.extern.apachecommons.CommonsLog; + +/** + * @author Spencer Gibb + */ +@CommonsLog +public abstract class Utils { + public static void error(String msg) { + error(msg); + throw new RuntimeException(msg); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/receiver/ArrayListSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/receiver/ArrayListSpanReceiver.java new file mode 100644 index 000000000..1a50ddbac --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/receiver/ArrayListSpanReceiver.java @@ -0,0 +1,29 @@ +package org.springframework.cloud.sleuth.trace.receiver; + +import org.springframework.cloud.sleuth.trace.Span; +import org.springframework.cloud.sleuth.trace.SpanReceiver; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Spencer Gibb + */ +public class ArrayListSpanReceiver implements SpanReceiver { + private final ArrayList spans = new ArrayList<>(); + + @Override + public void receiveSpan(Span span) { + spans.add(span); + } + + public List getSpans() { + return spans; + } + + @Override + public void close() throws IOException { + + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/AlwaysSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/AlwaysSampler.java new file mode 100644 index 000000000..879371904 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/AlwaysSampler.java @@ -0,0 +1,13 @@ +package org.springframework.cloud.sleuth.trace.sampler; + +import org.springframework.cloud.sleuth.trace.Sampler; + +/** + * @author Spencer Gibb + */ +public class AlwaysSampler implements Sampler { + @Override + public boolean next(Object info) { + return true; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java new file mode 100644 index 000000000..f5a3c00f3 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.sleuth.trace.sampler; + +import org.springframework.cloud.sleuth.trace.Sampler; +import org.springframework.cloud.sleuth.trace.Trace; + +/** + * @author Spencer Gibb + */ +public class IsTracingSampler implements Sampler { + private final Trace trace; + + public IsTracingSampler(Trace trace) { + this.trace = trace; + } + + @Override + public boolean next(Object info) { + return this.trace.isTracing(); + } +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java new file mode 100644 index 000000000..6eb005738 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java @@ -0,0 +1,100 @@ +package org.springframework.cloud.sleuth.trace; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.sleuth.trace.receiver.ArrayListSpanReceiver; +import org.springframework.cloud.sleuth.trace.sampler.AlwaysSampler; + +/** + * @author Spencer Gibb + */ +public class DefaultTraceTests { + + public static final String CREATE_SIMPLE_TRACE = "createSimpleTrace"; + public static final String IMPORTANT_WORK_1 = "important work 1"; + public static final String IMPORTANT_WORK_2 = "important work 2"; + + @Test + public void tracingWorks() { + DefaultTrace trace = new DefaultTrace(); + ArrayListSpanReceiver spanReceiver = new ArrayListSpanReceiver(); + trace.setSpanReceivers(Collections. singletonList(spanReceiver)); + + TraceScope scope = trace.startSpan(CREATE_SIMPLE_TRACE, new AlwaysSampler()); + try { + importantWork1(trace); + } + finally { + scope.close(); + } + + List spans = spanReceiver.getSpans(); + assertThat("spans was null", spans, is(notNullValue())); + assertThat("spans was empty", spans.isEmpty(), not(true)); + assertThat("spans was wrong size", spans.size(), is(3)); + + Span root = assertSpan(spans, null, CREATE_SIMPLE_TRACE); + Span child = assertSpan(spans, root.getSpanId(), IMPORTANT_WORK_1); + Span grandChild = assertSpan(spans, child.getSpanId(), IMPORTANT_WORK_2); + + List gen4 = findSpans(spans, grandChild.getSpanId()); + assertThat("gen4 was non-empty", gen4.isEmpty(), is(true)); + } + + private Span assertSpan(List spans, String parentId, String desc) { + List found = findSpans(spans, parentId); + assertThat("more than one span with parentId " + parentId, found.size(), is(1)); + Span span = found.get(0); + assertThat("description is wrong for span with parentId " + parentId, + span.getDescription(), is(desc)); + return span; + } + + private List findSpans(List spans, String parentId) { + List found = new ArrayList<>(); + for (Span span : spans) { + if (parentId == null && span.getParents().isEmpty()) { + found.add(span); + } + else if (span.getParents().contains(parentId)) { + found.add(span); + } + } + return found; + } + + private void importantWork1(Trace trace) { + TraceScope cur = trace.startSpan(IMPORTANT_WORK_1); + try { + Thread.sleep((long) (50 * Math.random())); + importantWork2(trace); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + finally { + cur.close(); + } + } + + private void importantWork2(Trace trace) { + TraceScope cur = trace.startSpan(IMPORTANT_WORK_2); + try { + Thread.sleep((long) (50 * Math.random())); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + finally { + cur.close(); + } + } +} From 8680512edb5cb99f83c0f1a9ecdb7c67781f5c35 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 14:06:34 -0600 Subject: [PATCH 06/34] refactor DefaultTrace --- .../cloud/sleuth/{trace => }/IdGenerator.java | 2 +- .../cloud/sleuth/RandomUuidGenerator.java | 14 ++++++++ .../cloud/sleuth/trace/DefaultTrace.java | 35 ++++++------------- .../cloud/sleuth/trace/Trace.java | 4 +-- .../trace/sampler/IsTracingSampler.java | 9 ++--- 5 files changed, 29 insertions(+), 35 deletions(-) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/IdGenerator.java (63%) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/RandomUuidGenerator.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/IdGenerator.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/IdGenerator.java similarity index 63% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/IdGenerator.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/IdGenerator.java index 239833367..41e66284f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/IdGenerator.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/IdGenerator.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/RandomUuidGenerator.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/RandomUuidGenerator.java new file mode 100644 index 000000000..1a41f28e2 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/RandomUuidGenerator.java @@ -0,0 +1,14 @@ +package org.springframework.cloud.sleuth; + +import java.util.UUID; + +/** + * @author Spencer Gibb + */ +public class RandomUuidGenerator implements IdGenerator { + + @Override + public String create() { + return UUID.randomUUID().toString(); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java index 43d29c228..d2e2efaf6 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java @@ -2,28 +2,28 @@ package org.springframework.cloud.sleuth.trace; import static org.springframework.cloud.sleuth.trace.Utils.error; -import org.springframework.cloud.sleuth.trace.sampler.IsTracingSampler; +import org.springframework.cloud.sleuth.IdGenerator; import java.util.Collection; import java.util.Collections; -import java.util.UUID; /** * @author Spencer Gibb */ public class DefaultTrace implements Trace { - //TODO: no default?, let autoconfig - private Sampler defaultSampler = new IsTracingSampler(this); + private final Sampler defaultSampler; - private IdGenerator idGenerator = new IdGenerator() { - @Override - public String create() { - return UUID.randomUUID().toString(); - } - }; + private final IdGenerator idGenerator; - private Collection spanReceivers; + private final Collection spanReceivers; + + public DefaultTrace(Sampler defaultSampler, IdGenerator idGenerator, + Collection spanReceivers) { + this.defaultSampler = defaultSampler; + this.idGenerator = idGenerator; + this.spanReceivers = spanReceivers; + } @Override public TraceScope startSpan(String description) { @@ -131,17 +131,4 @@ public class DefaultTrace implements Trace { receiver.receiveSpan(span); } } - - public void setDefaultSampler(Sampler defaultSampler) { - this.defaultSampler = defaultSampler; - } - - public void setIdGenerator(IdGenerator idGenerator) { - this.idGenerator = idGenerator; - } - - @Override - public void setSpanReceivers(Collection spanReceivers) { - this.spanReceivers = spanReceivers; - } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java index fee6cfb96..91019c609 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java @@ -81,7 +81,5 @@ public interface Trace { */ boolean isTracing(); - public void deliver(Span span); - - void setSpanReceivers(Collection spanReceivers); + void deliver(Span span); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java index f5a3c00f3..be4b27447 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java @@ -1,20 +1,15 @@ package org.springframework.cloud.sleuth.trace.sampler; import org.springframework.cloud.sleuth.trace.Sampler; -import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.trace.SpanHolder; /** * @author Spencer Gibb */ public class IsTracingSampler implements Sampler { - private final Trace trace; - - public IsTracingSampler(Trace trace) { - this.trace = trace; - } @Override public boolean next(Object info) { - return this.trace.isTracing(); + return SpanHolder.getCurrentSpan() != null; } } From 51273f042f04418dd08763b9f85bcdeb5ba275dc Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 14:08:22 -0600 Subject: [PATCH 07/34] refactor DefaultTrace --- .../cloud/sleuth/trace/DefaultTraceTests.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java index 6eb005738..5613543a6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java @@ -10,8 +10,10 @@ import java.util.Collections; import java.util.List; import org.junit.Test; +import org.springframework.cloud.sleuth.RandomUuidGenerator; import org.springframework.cloud.sleuth.trace.receiver.ArrayListSpanReceiver; import org.springframework.cloud.sleuth.trace.sampler.AlwaysSampler; +import org.springframework.cloud.sleuth.trace.sampler.IsTracingSampler; /** * @author Spencer Gibb @@ -24,9 +26,11 @@ public class DefaultTraceTests { @Test public void tracingWorks() { - DefaultTrace trace = new DefaultTrace(); ArrayListSpanReceiver spanReceiver = new ArrayListSpanReceiver(); - trace.setSpanReceivers(Collections. singletonList(spanReceiver)); + List spanReceivers = Collections + . singletonList(spanReceiver); + DefaultTrace trace = new DefaultTrace(new IsTracingSampler(), + new RandomUuidGenerator(), spanReceivers); TraceScope scope = trace.startSpan(CREATE_SIMPLE_TRACE, new AlwaysSampler()); try { From 5afbc75ecb16dafa9e608f85ab17093776f24594 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 16:11:42 -0600 Subject: [PATCH 08/34] Added SpanStartListener and slf4j SpanStartListener and SpanReceiver --- pom.xml | 1 + .../SleuthRestTemplateAutoConfiguration.java | 2 +- .../slf4j/SleuthSlf4jAutoConfiguration.java | 24 +++++++ .../cloud/sleuth/slf4j/Slf4jSpanReceiver.java | 29 ++++++++ .../sleuth/slf4j/Slf4jSpanStartListener.java | 22 ++++++ .../cloud/sleuth/trace/DefaultTrace.java | 21 ++++-- .../cloud/sleuth/trace/SpanStartListener.java | 9 +++ .../cloud/sleuth/trace/Trace.java | 2 - .../sleuth/trace/TraceAutoConfiguration.java | 34 +++++++++ .../cloud/sleuth/trace/TraceScope.java | 1 + .../main/resources/META-INF/spring.factories | 4 +- .../cloud/sleuth/trace/DefaultTraceTests.java | 27 +++++-- spring-cloud-sleuth-sample/pom.xml | 2 +- .../sleuth/sample/SampleApplication.java | 71 ++++++++++++------- .../src/main/resources/logback.xml | 18 +++++ 15 files changed, 229 insertions(+), 38 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanStartListener.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceAutoConfiguration.java create mode 100644 spring-cloud-sleuth-sample/src/main/resources/logback.xml diff --git a/pom.xml b/pom.xml index 96e8782b4..8ab271c7d 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,7 @@ spring-cloud-sleuth-core + spring-cloud-sleuth-slf4j spring-cloud-sleuth-correlation spring-cloud-sleuth-zipkin spring-cloud-sleuth-sample diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java index 662176624..40d1d2e0f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java @@ -42,7 +42,7 @@ public class SleuthRestTemplateAutoConfiguration { @Configuration protected static class RestTemplateConfig { - @Autowired + @Autowired(required = false) private List clientHttpRequestInterceptors = new ArrayList<>(); @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java new file mode 100644 index 000000000..ea0781be7 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java @@ -0,0 +1,24 @@ +package org.springframework.cloud.sleuth.slf4j; + +import org.slf4j.MDC; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Spencer Gibb + */ +@Configuration +@ConditionalOnClass(MDC.class) +public class SleuthSlf4jAutoConfiguration { + + @Bean + public Slf4jSpanStartListener slf4jSpanStartListener() { + return new Slf4jSpanStartListener(); + } + + @Bean + public Slf4jSpanReceiver slf4jSpanReceiver() { + return new Slf4jSpanReceiver(); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java new file mode 100644 index 000000000..064b94c4f --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java @@ -0,0 +1,29 @@ +package org.springframework.cloud.sleuth.slf4j; + +import static org.springframework.cloud.sleuth.slf4j.Slf4jSpanStartListener.SPAN_ID_NAME; + +import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; +import org.springframework.cloud.sleuth.trace.Span; +import org.springframework.cloud.sleuth.trace.SpanReceiver; + +import javax.annotation.PostConstruct; +import java.io.IOException; + +/** + * @author Spencer Gibb + */ +@Slf4j +public class Slf4jSpanReceiver implements SpanReceiver { + @Override + public void receiveSpan(Span span) { + //TODO: what should this log level be? + log.info("Received span {}", span); + MDC.remove(SPAN_ID_NAME); + } + + @PostConstruct + @Override + public void close() throws IOException { + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java new file mode 100644 index 000000000..e68a1df72 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java @@ -0,0 +1,22 @@ +package org.springframework.cloud.sleuth.slf4j; + +import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; +import org.springframework.cloud.sleuth.trace.Span; +import org.springframework.cloud.sleuth.trace.SpanStartListener; + +/** + * @author Spencer Gibb + */ +@Slf4j +public class Slf4jSpanStartListener implements SpanStartListener { + //TODO: Where to put span id name? + public static final String SPAN_ID_NAME = "Span-Id"; + + @Override + public void startSpan(Span span) { + //TODO: what log level? + log.info("Starting span with id: [{}]", span.getSpanId()); + MDC.put(SPAN_ID_NAME, span.getSpanId()); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java index d2e2efaf6..2eff2ffa2 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java @@ -16,12 +16,15 @@ public class DefaultTrace implements Trace { private final IdGenerator idGenerator; + private final Collection spanStartListeners; private final Collection spanReceivers; public DefaultTrace(Sampler defaultSampler, IdGenerator idGenerator, + Collection spanStartListeners, Collection spanReceivers) { this.defaultSampler = defaultSampler; this.idGenerator = idGenerator; + this.spanStartListeners = spanStartListeners; this.spanReceivers = spanReceivers; } @@ -32,7 +35,7 @@ public class DefaultTrace implements Trace { @Override public TraceScope startSpan(String description, TraceInfo tinfo) { - if (tinfo == null) return continueSpan(null); + if (tinfo == null) return doStart(null); MilliSpan span = MilliSpan.builder() .begin(System.currentTimeMillis()) .description(description) @@ -41,7 +44,7 @@ public class DefaultTrace implements Trace { .parents(Collections.singletonList(tinfo.getSpanId())) //TODO: when lombok plugin supports @Singular parent(tinfo.getSpanId()). .build(); - return continueSpan(span); + return doStart(span); } @Override @@ -56,7 +59,7 @@ public class DefaultTrace implements Trace { "with parent " + parent.toString() + ", but there is already a " + "currentSpan " + currentSpan); } - return continueSpan(createChild(parent, description)); + return doStart(createChild(parent, description)); } @Override @@ -70,7 +73,7 @@ public class DefaultTrace implements Trace { if (isTracing() || s.next(info)) { span = createNew(description); } - return continueSpan(span); + return doStart(span); } protected Span createNew(String description) { @@ -99,6 +102,15 @@ public class DefaultTrace implements Trace { build(); } + protected TraceScope doStart(Span span) { + if (span != null) { + for (SpanStartListener listener : spanStartListeners) { + listener.startSpan(span); + } + } + return continueSpan(span); + } + @Override public TraceScope continueSpan(Span span) { // Return an empty TraceScope that does nothing on close @@ -125,6 +137,7 @@ public class DefaultTrace implements Trace { return getCurrentSpan() != null; } + //TODO: rename? this is the end of a Span lifecycle @Override public void deliver(Span span) { for (SpanReceiver receiver : spanReceivers) { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanStartListener.java new file mode 100644 index 000000000..276f2dfa8 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanStartListener.java @@ -0,0 +1,9 @@ +package org.springframework.cloud.sleuth.trace; + +/** + * @author Spencer Gibb + */ +//TODO: rename? +public interface SpanStartListener { + void startSpan(Span span); +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java index 91019c609..00dbc0e6f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java @@ -1,7 +1,5 @@ package org.springframework.cloud.sleuth.trace; -import java.util.Collection; - /** * The Trace class is the primary way to interact with the library. It provides * methods to create and manipulate spans. diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceAutoConfiguration.java new file mode 100644 index 000000000..71dad2f7e --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceAutoConfiguration.java @@ -0,0 +1,34 @@ +package org.springframework.cloud.sleuth.trace; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.sleuth.IdGenerator; +import org.springframework.cloud.sleuth.RandomUuidGenerator; +import org.springframework.cloud.sleuth.trace.sampler.IsTracingSampler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Collection; + +/** + * @author Spencer Gibb + */ +@Configuration +public class TraceAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public IdGenerator idGenerator() { + return new RandomUuidGenerator(); + } + + @Bean + public Sampler defaultSampler() { + return new IsTracingSampler(); + } + + @Bean + @ConditionalOnMissingBean + public Trace trace(Sampler sampler, IdGenerator idGenerator, Collection listeners, Collection receivers) { + return new DefaultTrace(sampler, idGenerator, listeners, receivers); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java index 3e0d74d54..3de9135ad 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java @@ -72,6 +72,7 @@ public class TraceScope implements Closeable { "probably forgotten to close or detach " + cur); } else { span.stop(); + //TODO: use ApplicationEvents here? trace.deliver(span); SpanHolder.setCurrentSpan(savedSpan); } diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories index 9d7ec500c..7b7f733f7 100644 --- a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories @@ -1,3 +1,5 @@ # Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration +org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration,\ +org.springframework.cloud.sleuth.trace.TraceAutoConfiguration,\ +org.springframework.cloud.sleuth.slf4j.SleuthSlf4jAutoConfiguration diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java index 5613543a6..05a8b4da7 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java @@ -1,7 +1,6 @@ package org.springframework.cloud.sleuth.trace; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; @@ -9,6 +8,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import lombok.Data; + import org.junit.Test; import org.springframework.cloud.sleuth.RandomUuidGenerator; import org.springframework.cloud.sleuth.trace.receiver.ArrayListSpanReceiver; @@ -23,14 +24,19 @@ public class DefaultTraceTests { public static final String CREATE_SIMPLE_TRACE = "createSimpleTrace"; public static final String IMPORTANT_WORK_1 = "important work 1"; public static final String IMPORTANT_WORK_2 = "important work 2"; + public static final int NUM_SPANS = 3; @Test public void tracingWorks() { ArrayListSpanReceiver spanReceiver = new ArrayListSpanReceiver(); + ListSpanStartListener listener = new ListSpanStartListener(); + List startListeners = Collections + . singletonList(listener); List spanReceivers = Collections . singletonList(spanReceiver); + DefaultTrace trace = new DefaultTrace(new IsTracingSampler(), - new RandomUuidGenerator(), spanReceivers); + new RandomUuidGenerator(), startListeners, spanReceivers); TraceScope scope = trace.startSpan(CREATE_SIMPLE_TRACE, new AlwaysSampler()); try { @@ -40,10 +46,13 @@ public class DefaultTraceTests { scope.close(); } + List startedSpans = listener.getSpans(); + assertThat("startedSpans was null", startedSpans, is(notNullValue())); + assertThat("startedSpans was wrong size", startedSpans.size(), is(NUM_SPANS)); + List spans = spanReceiver.getSpans(); assertThat("spans was null", spans, is(notNullValue())); - assertThat("spans was empty", spans.isEmpty(), not(true)); - assertThat("spans was wrong size", spans.size(), is(3)); + assertThat("spans was wrong size", spans.size(), is(NUM_SPANS)); Span root = assertSpan(spans, null, CREATE_SIMPLE_TRACE); Span child = assertSpan(spans, root.getSpanId(), IMPORTANT_WORK_1); @@ -101,4 +110,14 @@ public class DefaultTraceTests { cur.close(); } } + + @Data + class ListSpanStartListener implements SpanStartListener { + private ArrayList spans = new ArrayList<>(); + + @Override + public void startSpan(Span span) { + spans.add(span); + } + } } diff --git a/spring-cloud-sleuth-sample/pom.xml b/spring-cloud-sleuth-sample/pom.xml index 766232a85..012281b99 100644 --- a/spring-cloud-sleuth-sample/pom.xml +++ b/spring-cloud-sleuth-sample/pom.xml @@ -47,7 +47,7 @@ org.springframework.cloud - spring-cloud-sleuth-zipkin + spring-cloud-sleuth-core org.projectlombok diff --git a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java index ace29542f..1abd724c2 100644 --- a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java +++ b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java @@ -9,6 +9,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; +import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.cloud.sleuth.trace.sampler.AlwaysSampler; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,43 +25,61 @@ import org.springframework.web.client.RestTemplate; @EnableAutoConfiguration @RestController @Slf4j -public class SampleApplication implements ApplicationListener { +public class SampleApplication implements + ApplicationListener { public static final String CLIENT_NAME = "testApp"; - @Autowired - private RestTemplate restTemplate; - private int port; + @Autowired + private RestTemplate restTemplate; + @Autowired + private Trace trace; + private int port; - @SneakyThrows - @RequestMapping("/") + @SneakyThrows + @RequestMapping("/") public String hi() { - final Random random = new Random(); - Thread.sleep(random.nextInt(1000)); + final Random random = new Random(); + Thread.sleep(random.nextInt(1000)); - String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", String.class); - return "hi/"+s; + String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", + String.class); + return "hi/" + s; } - @SneakyThrows - @RequestMapping("/hi2") - public String hi2() { - final Random random = new Random(); - Thread.sleep(random.nextInt(1000)); - return "hi2"; - } + @SneakyThrows + @RequestMapping("/hi2") + public String hi2() { + final Random random = new Random(); + Thread.sleep(random.nextInt(1000)); + return "hi2"; + } + + @SneakyThrows + @RequestMapping("/traced") + public String traced() { + TraceScope scope = trace.startSpan("customTraceEndpoint", new AlwaysSampler()); + final Random random = new Random(); + int millis = random.nextInt(1000); + log.info("Sleeping for {} millis", millis); + Thread.sleep(millis); + + String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", String.class); + scope.close(); + return "hi/"+s; + } public static void main(String[] args) { SpringApplication.run(SampleApplication.class, args); } - /*@Bean - public SpanCollector spanCollector() { - return new LoggingSpanCollectorImpl(); - }*/ + /* + * @Bean public SpanCollector spanCollector() { return new LoggingSpanCollectorImpl(); + * } + */ - @Override - public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { - port = event.getEmbeddedServletContainer().getPort(); - } + @Override + public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { + port = event.getEmbeddedServletContainer().getPort(); + } } diff --git a/spring-cloud-sleuth-sample/src/main/resources/logback.xml b/spring-cloud-sleuth-sample/src/main/resources/logback.xml new file mode 100644 index 000000000..6ae7c6632 --- /dev/null +++ b/spring-cloud-sleuth-sample/src/main/resources/logback.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file From 7bb89e893fd79b1e6f1467cc1784b9ed928cb7d2 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 20:25:23 -0600 Subject: [PATCH 09/34] start to move instrumenting code to s-c-s-core --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8ab271c7d..96e8782b4 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,6 @@ spring-cloud-sleuth-core - spring-cloud-sleuth-slf4j spring-cloud-sleuth-correlation spring-cloud-sleuth-zipkin spring-cloud-sleuth-sample From 36da106c1bf9a3a29a49c6047ec1b5059e46b3d7 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 20:25:41 -0600 Subject: [PATCH 10/34] start to move instrumenting code to s-c-s-core --- spring-cloud-sleuth-core/pom.xml | 15 +++ .../cloud/sleuth/slf4j/Slf4jSpanReceiver.java | 2 +- .../sleuth/slf4j/Slf4jSpanStartListener.java | 6 +- .../cloud/sleuth/trace/Trace.java | 3 + .../circuitbreaker/TraceCommand.java | 59 +++++++++ .../scheduling/TraceSchedulingAspect.java | 39 ++++++ .../TraceSchedulingAutoConfiguration.java | 30 +++++ .../trace/intercept/web/TraceFilter.java | 122 +++++++++++++++++ .../trace/intercept/web/TraceWebAspect.java | 125 ++++++++++++++++++ .../web/TraceWebAutoConfiguration.java | 66 +++++++++ .../client/TraceRestTemplateInterceptor.java | 55 ++++++++ .../TraceWebClientAutoConfiguration.java | 26 ++++ .../main/resources/META-INF/spring.factories | 2 + 13 files changed, 546 insertions(+), 4 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/circuitbreaker/TraceCommand.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAspect.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAutoConfiguration.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceFilter.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAspect.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAutoConfiguration.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceRestTemplateInterceptor.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceWebClientAutoConfiguration.java diff --git a/spring-cloud-sleuth-core/pom.xml b/spring-cloud-sleuth-core/pom.xml index edcea1b3f..bcbab14b3 100644 --- a/spring-cloud-sleuth-core/pom.xml +++ b/spring-cloud-sleuth-core/pom.xml @@ -42,6 +42,21 @@ spring-boot-starter-actuator true + + com.netflix.hystrix + hystrix-core + true + + + io.reactivex + rxjava + true + + + org.aspectj + aspectjrt + true + org.projectlombok lombok diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java index 064b94c4f..3d1acd172 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java @@ -1,6 +1,6 @@ package org.springframework.cloud.sleuth.slf4j; -import static org.springframework.cloud.sleuth.slf4j.Slf4jSpanStartListener.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java index e68a1df72..c1ba9a5d0 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java @@ -1,22 +1,22 @@ package org.springframework.cloud.sleuth.slf4j; import lombok.extern.slf4j.Slf4j; + import org.slf4j.MDC; import org.springframework.cloud.sleuth.trace.Span; import org.springframework.cloud.sleuth.trace.SpanStartListener; +import org.springframework.cloud.sleuth.trace.Trace; /** * @author Spencer Gibb */ @Slf4j public class Slf4jSpanStartListener implements SpanStartListener { - //TODO: Where to put span id name? - public static final String SPAN_ID_NAME = "Span-Id"; @Override public void startSpan(Span span) { //TODO: what log level? log.info("Starting span with id: [{}]", span.getSpanId()); - MDC.put(SPAN_ID_NAME, span.getSpanId()); + MDC.put(Trace.SPAN_ID_NAME, span.getSpanId()); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java index 00dbc0e6f..0568118a7 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java @@ -35,6 +35,9 @@ package org.springframework.cloud.sleuth.trace; */ public interface Trace { + String SPAN_ID_NAME = "Span-Id"; + String TRACE_ID_NAME = "Trace-Id"; + /** * Creates a new trace scope. *

diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/circuitbreaker/TraceCommand.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/circuitbreaker/TraceCommand.java new file mode 100644 index 000000000..cb8ea6861 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/circuitbreaker/TraceCommand.java @@ -0,0 +1,59 @@ +package org.springframework.cloud.sleuth.trace.intercept.circuitbreaker; + +import com.netflix.hystrix.HystrixCommand; +import com.netflix.hystrix.HystrixCommandGroupKey; +import com.netflix.hystrix.HystrixThreadPoolKey; +import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.trace.TraceScope; + +/** + * Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting + * + * @see HystrixCommand + * @see CorrelationIdUpdater + * + * @author Tomasz Nurkiewicz, 4financeIT + * @author Marcin Grzejszczak, 4financeIT + * @author Spencer Gibb + */ +public abstract class TraceCommand extends HystrixCommand { + + private Trace trace; + + protected TraceCommand(Trace trace, HystrixCommandGroupKey group) { + super(group); + this.trace = trace; + } + + protected TraceCommand(Trace trace, HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool) { + super(group, threadPool); + this.trace = trace; + } + + protected TraceCommand(Trace trace, HystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds) { + super(group, executionIsolationThreadTimeoutInMilliseconds); + this.trace = trace; + } + + protected TraceCommand(Trace trace, HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds) { + super(group, threadPool, executionIsolationThreadTimeoutInMilliseconds); + this.trace = trace; + } + + protected TraceCommand(Trace trace, Setter setter) { + super(setter); + this.trace = trace; + } + + @Override + protected R run() throws Exception { + TraceScope scope = trace.startSpan(getCommandKey().name()); + try { + return doRun(); + } finally { + scope.close(); + } + } + + public abstract R doRun() throws Exception; +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAspect.java new file mode 100644 index 000000000..41d78ff25 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAspect.java @@ -0,0 +1,39 @@ +package org.springframework.cloud.sleuth.trace.intercept.scheduling; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.scheduling.annotation.Scheduled; + +/** + * Aspect that sets correlationId for running threads executing methods annotated with {@link Scheduled} annotation. + * For every execution of scheduled method a new, i.e. unique one, value of correlationId will be set. + * + * @author Tomasz Nurkewicz, 4financeIT + * @author Michal Chmielarz, 4financeIT + * @author Marcin Grzejszczak, 4financeIT + * @author Spencer Gibb + * + * @see org.springframework.cloud.sleuth.trace.Trace + */ +@Aspect +public class TraceSchedulingAspect { + + private final Trace trace; + + public TraceSchedulingAspect(Trace trace) { + this.trace = trace; + } + + @Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))") + public Object setNewCorrelationIdOnThread(final ProceedingJoinPoint pjp) throws Throwable { + TraceScope scope = trace.startSpan(pjp.toShortString()); + try { + return pjp.proceed(); + } finally { + scope.close(); + } + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAutoConfiguration.java new file mode 100644 index 000000000..590264775 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAutoConfiguration.java @@ -0,0 +1,30 @@ +package org.springframework.cloud.sleuth.trace.intercept.scheduling; + +/** + * @author Spencer Gibb + */ + +import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * Registers beans related to task scheduling. + * + * @see TraceSchedulingAspect + * + * @author Michal Chmielarz, 4financeIT + * @author Spencer Gibb + */ +@Configuration +@EnableScheduling +@EnableAspectJAutoProxy +public class TraceSchedulingAutoConfiguration { + + @Bean + public TraceSchedulingAspect traceSchedulingAspect(Trace trace) { + return new TraceSchedulingAspect(trace); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceFilter.java new file mode 100644 index 000000000..7b8972e2b --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceFilter.java @@ -0,0 +1,122 @@ +/* + * Copyright 2012-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.trace.intercept.web; + +import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; +import static org.springframework.util.StringUtils.hasText; + +import java.io.IOException; +import java.lang.invoke.MethodHandles; +import java.util.Collections; +import java.util.regex.Pattern; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.springframework.cloud.sleuth.trace.MilliSpan; +import org.springframework.cloud.sleuth.trace.Span; +import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.web.filter.OncePerRequestFilter; + +/** + * Filter that takes the value of the {@link CorrelationIdHolder#CORRELATION_ID_HEADER} + * header from either request or response and sets it in the {@link CorrelationIdHolder}. + * It also provides that value in {@link MDC} logging related class so that logger prints + * the value of correlation id at each log. + * + * @see Trace + * @see MDC + * + * @author Jakub Nabrdalik, 4financeIT + * @author Tomasz Nurkiewicz, 4financeIT + * @author Marcin Grzejszczak, 4financeIT + * @author Spencer Gibb + */ +public class TraceFilter extends OncePerRequestFilter { + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup() + .lookupClass()); + public static final Pattern DEFAULT_SKIP_PATTERN = Pattern + .compile("/api-docs.*|/autoconfig|/configprops|/dump|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html"); + + private final Trace trace; + private final Pattern skipPattern; + + public TraceFilter(Trace trace) { + this.trace = trace; + this.skipPattern = DEFAULT_SKIP_PATTERN; + } + + public TraceFilter(Trace trace, Pattern skipPattern) { + this.trace = trace; + this.skipPattern = skipPattern; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + String spanIdFromRequest = getSpanIdFrom(request); + String spanId = (hasText(spanIdFromRequest)) ? spanIdFromRequest + : getSpanIdFrom(response); + + TraceScope traceScope = null; + if (spanId != null) { + addCorrelationIdToResponseIfNotPresent(response, spanId); + + Span span = MilliSpan.builder().traceId("") // FIXME get traceId from request + .parents(Collections.singletonList(spanId)) + // TODO: use parent() when lombok plugin supports it + .build(); + traceScope = trace.startSpan("traceFilter", span); + } + else { + traceScope = trace.startSpan("traceFilter"); + } + + try { + filterChain.doFilter(request, response); + } + finally { + traceScope.close(); + } + } + + private String getSpanIdFrom(final HttpServletResponse response) { + return response.getHeader(SPAN_ID_NAME); + } + + private String getSpanIdFrom(final HttpServletRequest request) { + return request.getHeader(SPAN_ID_NAME); + } + + private void addCorrelationIdToResponseIfNotPresent(HttpServletResponse response, + String spanId) { + if (!hasText(response.getHeader(SPAN_ID_NAME))) { + response.addHeader(SPAN_ID_NAME, spanId); + } + } + + @Override + protected boolean shouldNotFilterAsyncDispatch() { + return false; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAspect.java new file mode 100644 index 000000000..adbd8620f --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAspect.java @@ -0,0 +1,125 @@ +package org.springframework.cloud.sleuth.trace.intercept.web; + +import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; + +import java.util.ArrayList; +import java.util.List; + +import lombok.extern.apachecommons.CommonsLog; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestOperations; + +/** + * Aspect that adds correlation id to + *

+ *

    + *
  • {@link RestController} annotated classes
  • + *
  • {@link Controller} annotated classes
  • + *
  • explicit {@link RestOperations}.exchange(..) method calls
  • + *
+ *

+ * For controllers an around aspect is created that create a {@link Span} for each call. + *

+ * For {@link RestOperations} we are wrapping all executions of the exchange + * methods and we are extracting {@link HttpHeaders} from the passed {@link HttpEntity}. + * Next we are adding span id header * {@link Trace#SPAN_ID_NAME} with the value taken + * from the current Span. Finally the method execution proceeds. + * + * @see RestController + * @see Controller + * @see RestOperations + * @see Trace + * + * @author Tomasz Nurkewicz, 4financeIT + * @author Marcin Grzejszczak, 4financeIT + * @author Michal Chmielarz, 4financeIT + * @author Spencer Gibb + */ +@CommonsLog +public class TraceWebAspect { + + private final Trace trace; + + public TraceWebAspect(Trace trace) { + this.trace = trace; + } + + private static final int HTTP_ENTITY_PARAM_INDEX = 2; + + @Pointcut("@target(org.springframework.web.bind.annotation.RestController)") + private void anyRestControllerAnnotated() { + } + + @Pointcut("@target(org.springframework.stereotype.Controller)") + private void anyControllerAnnotated() { + } + + @Pointcut("anyRestControllerAnnotated() || anyControllerAnnotated()") + private void anyControllerOrRestController() { + } + + @Around("anyControllerOrRestController()") + public Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable { + TraceScope scope = trace.startSpan(pjp.toShortString()); + try { + return pjp.proceed(); + } + finally { + scope.close(); + } + } + + @Pointcut("execution(public * org.springframework.web.client.RestOperations.exchange(..))") + private void anyExchangeRestOperationsMethod() { + } + + @Around("anyExchangeRestOperationsMethod()") + public Object wrapWithCorrelationIdForRestOperations(ProceedingJoinPoint pjp) + throws Throwable { + TraceScope scope = trace.startSpan(pjp.toShortString()); + try { + String spanId = scope.getSpan().getSpanId(); + //TODO: set traceId on restTemplate call as well + log.debug("Wrapping RestTemplate call with span id [" + spanId + "]"); + HttpEntity httpEntity = (HttpEntity) pjp.getArgs()[HTTP_ENTITY_PARAM_INDEX]; + HttpEntity newHttpEntity = createNewHttpEntity(httpEntity, spanId); + List newArgs = modifyHttpEntityInMethodArguments(pjp, newHttpEntity); + return pjp.proceed(newArgs.toArray()); + } + finally { + scope.close(); + } + } + + @SuppressWarnings("unchecked") + private HttpEntity createNewHttpEntity(HttpEntity httpEntity, String correlationId) { + HttpHeaders newHttpHeaders = new HttpHeaders(); + newHttpHeaders.putAll(httpEntity.getHeaders()); + newHttpHeaders.add(SPAN_ID_NAME, correlationId); + return new HttpEntity(httpEntity.getBody(), newHttpHeaders); + } + + private List modifyHttpEntityInMethodArguments(ProceedingJoinPoint pjp, + HttpEntity newHttpEntity) { + List newArgs = new ArrayList<>(); + for (int i = 0; i < pjp.getArgs().length; i++) { + Object arg = pjp.getArgs()[i]; + if (i != HTTP_ENTITY_PARAM_INDEX) { + newArgs.add(i, arg); + } + else { + newArgs.add(i, newHttpEntity); + } + } + return newArgs; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAutoConfiguration.java new file mode 100644 index 000000000..4c0316504 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAutoConfiguration.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012-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.trace.intercept.web; + +import java.util.regex.Pattern; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; + +/** + * Registers beans that add tracing to requests + * + * @author Tomasz Nurkewicz, 4financeIT + * @author Marcin Grzejszczak, 4financeIT + * @author Michal Chmielarz, 4financeIT + * @author Spencer Gibb + */ +@Configuration +@ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.enabled", matchIfMissing = true) +@ConditionalOnWebApplication +public class TraceWebAutoConfiguration { + + /** + * Pattern for URLs that should be skipped in correlationID setting + */ + @Value("${spring.cloud.sleuth.trace.web.skipPattern:}") + private String skipPattern; + + @Autowired + private Trace trace; + + @Bean + @ConditionalOnMissingBean + public TraceWebAspect traceWebAspect() { + return new TraceWebAspect(trace); + } + + @Bean + @ConditionalOnMissingBean + public FilterRegistrationBean correlationHeaderFilter() { + Pattern pattern = StringUtils.hasText(skipPattern) ? Pattern.compile(skipPattern) + : TraceFilter.DEFAULT_SKIP_PATTERN; + return new FilterRegistrationBean(new TraceFilter(trace, pattern)); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceRestTemplateInterceptor.java new file mode 100644 index 000000000..6e485e912 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceRestTemplateInterceptor.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-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.trace.intercept.web.client; + +import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.trace.Trace.TRACE_ID_NAME; + +import java.io.IOException; + +import org.springframework.cloud.sleuth.trace.SpanHolder; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; + +/** + * Interceptor that verifies whether the trance and span id has been set on the + * request and sets them if one or both of them are missing. + * + * @see org.springframework.web.client.RestTemplate + * @see org.springframework.cloud.sleuth.trace.Trace + * + * @author Marcin Grzejszczak, 4financeIT + * @author Spencer Gibb + */ +public class TraceRestTemplateInterceptor implements ClientHttpRequestInterceptor { + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution) throws IOException { + if (!request.getHeaders().containsKey(SPAN_ID_NAME)) { + request.getHeaders().add(SPAN_ID_NAME, + SpanHolder.getCurrentSpan().getSpanId()); + } + if (!request.getHeaders().containsKey(TRACE_ID_NAME)) { + request.getHeaders().add(TRACE_ID_NAME, + SpanHolder.getCurrentSpan().getSpanId()); + } + return execution.execute(request, body); + } + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceWebClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceWebClientAutoConfiguration.java new file mode 100644 index 000000000..96230a482 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceWebClientAutoConfiguration.java @@ -0,0 +1,26 @@ +package org.springframework.cloud.sleuth.trace.intercept.web.client; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * @author Spencer Gibb + */ +@Configuration +@ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.client.enabled", matchIfMissing = true) +@ConditionalOnClass(RestTemplate.class) +@AutoConfigureAfter(SleuthRestTemplateAutoConfiguration.class) +public class TraceWebClientAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public TraceRestTemplateInterceptor traceRestTemplateInterceptor() { + return new TraceRestTemplateInterceptor(); + } +} diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories index 7b7f733f7..674340da8 100644 --- a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories @@ -2,4 +2,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration,\ org.springframework.cloud.sleuth.trace.TraceAutoConfiguration,\ +org.springframework.cloud.sleuth.trace.intercept.web.TraceWebAutoConfiguration,\ +org.springframework.cloud.sleuth.trace.intercept.web.client.TraceWebClientAutoConfiguration,\ org.springframework.cloud.sleuth.slf4j.SleuthSlf4jAutoConfiguration From a5f3234bacfec8ec64ea810212257f0ac4c8a3fb Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 20:32:33 -0600 Subject: [PATCH 11/34] collapse trace and trace.intercept packages --- .../cloud/sleuth/{trace => }/DefaultTrace.java | 6 ++---- .../cloud/sleuth/{trace => }/MilliSpan.java | 2 +- .../cloud/sleuth/{trace => }/NullScope.java | 2 +- .../cloud/sleuth/{trace => }/Sampler.java | 2 +- .../cloud/sleuth/{trace => }/Span.java | 2 +- .../cloud/sleuth/{trace => }/SpanHolder.java | 2 +- .../cloud/sleuth/{trace => }/SpanReceiver.java | 2 +- .../cloud/sleuth/{trace => }/SpanStartListener.java | 2 +- .../cloud/sleuth/{trace => }/TimelineAnnotation.java | 2 +- .../cloud/sleuth/{trace => }/Trace.java | 2 +- .../sleuth/{trace => }/TraceAutoConfiguration.java | 6 ++---- .../cloud/sleuth/{trace => }/TraceInfo.java | 2 +- .../cloud/sleuth/{trace => }/TraceScope.java | 2 +- .../cloud/sleuth/{trace => }/Utils.java | 2 +- .../intercept => }/circuitbreaker/TraceCommand.java | 6 +++--- .../{trace => }/receiver/ArrayListSpanReceiver.java | 6 +++--- .../sleuth/{trace => }/sampler/AlwaysSampler.java | 4 ++-- .../sleuth/{trace => }/sampler/IsTracingSampler.java | 6 +++--- .../scheduling/TraceSchedulingAspect.java | 8 ++++---- .../scheduling/TraceSchedulingAutoConfiguration.java | 4 ++-- .../cloud/sleuth/slf4j/Slf4jSpanReceiver.java | 6 +++--- .../cloud/sleuth/slf4j/Slf4jSpanStartListener.java | 6 +++--- .../{trace/intercept => }/web/TraceFilter.java | 12 ++++++------ .../{trace/intercept => }/web/TraceWebAspect.java | 8 ++++---- .../web/TraceWebAutoConfiguration.java | 4 ++-- .../web/client/TraceRestTemplateInterceptor.java | 11 ++++++----- .../web/client/TraceWebClientAutoConfiguration.java | 2 +- .../src/main/resources/META-INF/spring.factories | 6 +++--- .../cloud/sleuth/{trace => }/DefaultTraceTests.java | 9 ++++----- .../cloud/sleuth/sample/SampleApplication.java | 6 +++--- 30 files changed, 68 insertions(+), 72 deletions(-) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/DefaultTrace.java (95%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/MilliSpan.java (96%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/NullScope.java (90%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/Sampler.java (95%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/Span.java (97%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/SpanHolder.java (89%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/SpanReceiver.java (85%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/SpanStartListener.java (70%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/TimelineAnnotation.java (75%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/Trace.java (98%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/TraceAutoConfiguration.java (76%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/TraceInfo.java (75%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/TraceScope.java (97%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/Utils.java (81%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/circuitbreaker/TraceCommand.java (89%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/receiver/ArrayListSpanReceiver.java (71%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/sampler/AlwaysSampler.java (58%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace => }/sampler/IsTracingSampler.java (53%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/scheduling/TraceSchedulingAspect.java (81%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/scheduling/TraceSchedulingAutoConfiguration.java (84%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/web/TraceFilter.java (91%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/web/TraceWebAspect.java (93%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/web/TraceWebAutoConfiguration.java (95%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/web/client/TraceRestTemplateInterceptor.java (84%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{trace/intercept => }/web/client/TraceWebClientAutoConfiguration.java (93%) rename spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/{trace => }/DefaultTraceTests.java (91%) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java similarity index 95% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java index 2eff2ffa2..603e33bdc 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java @@ -1,8 +1,6 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; -import static org.springframework.cloud.sleuth.trace.Utils.error; - -import org.springframework.cloud.sleuth.IdGenerator; +import static org.springframework.cloud.sleuth.Utils.error; import java.util.Collection; import java.util.Collections; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java similarity index 96% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java index 83124d988..50404f6cc 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/MilliSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import java.util.List; import java.util.Map; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/NullScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/NullScope.java similarity index 90% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/NullScope.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/NullScope.java index b5941fd77..82bad3bcf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/NullScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/NullScope.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Sampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Sampler.java similarity index 95% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Sampler.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Sampler.java index 033416eb9..4e00125ce 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Sampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Sampler.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; /** * Extremely simple callback to determine the frequency that an action should be diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java similarity index 97% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java index dfd34b9d1..a880e5b8a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Span.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import java.util.List; import java.util.Map; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java similarity index 89% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java index 3b617fe97..2735c7700 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanHolder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import lombok.extern.apachecommons.CommonsLog; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReceiver.java similarity index 85% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanReceiver.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReceiver.java index 5a42135dd..9d0d54702 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanReceiver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReceiver.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import java.io.Closeable; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanStartListener.java similarity index 70% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanStartListener.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanStartListener.java index 276f2dfa8..2958cbe1c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/SpanStartListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanStartListener.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TimelineAnnotation.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TimelineAnnotation.java similarity index 75% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TimelineAnnotation.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TimelineAnnotation.java index b0b18dc3e..7c31d6845 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TimelineAnnotation.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TimelineAnnotation.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import lombok.Data; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java similarity index 98% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java index 0568118a7..ab1601bdf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; /** * The Trace class is the primary way to interact with the library. It provides diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java similarity index 76% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java index 71dad2f7e..7d7c4cd6b 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java @@ -1,9 +1,7 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.cloud.sleuth.IdGenerator; -import org.springframework.cloud.sleuth.RandomUuidGenerator; -import org.springframework.cloud.sleuth.trace.sampler.IsTracingSampler; +import org.springframework.cloud.sleuth.sampler.IsTracingSampler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceInfo.java similarity index 75% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceInfo.java index 31c8e5dab..5f8485eab 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceInfo.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceInfo.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import lombok.Data; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java similarity index 97% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java index 3de9135ad..a7d36434a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import java.io.Closeable; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Utils.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Utils.java similarity index 81% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Utils.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Utils.java index 3c8ecc4ac..6c8feaf18 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/Utils.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Utils.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import lombok.extern.apachecommons.CommonsLog; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/circuitbreaker/TraceCommand.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/circuitbreaker/TraceCommand.java similarity index 89% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/circuitbreaker/TraceCommand.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/circuitbreaker/TraceCommand.java index cb8ea6861..cc28a9439 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/circuitbreaker/TraceCommand.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/circuitbreaker/TraceCommand.java @@ -1,10 +1,10 @@ -package org.springframework.cloud.sleuth.trace.intercept.circuitbreaker; +package org.springframework.cloud.sleuth.circuitbreaker; import com.netflix.hystrix.HystrixCommand; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixThreadPoolKey; -import org.springframework.cloud.sleuth.trace.Trace; -import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; /** * Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/receiver/ArrayListSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/receiver/ArrayListSpanReceiver.java similarity index 71% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/receiver/ArrayListSpanReceiver.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/receiver/ArrayListSpanReceiver.java index 1a50ddbac..167ab3ee9 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/receiver/ArrayListSpanReceiver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/receiver/ArrayListSpanReceiver.java @@ -1,7 +1,7 @@ -package org.springframework.cloud.sleuth.trace.receiver; +package org.springframework.cloud.sleuth.receiver; -import org.springframework.cloud.sleuth.trace.Span; -import org.springframework.cloud.sleuth.trace.SpanReceiver; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanReceiver; import java.io.IOException; import java.util.ArrayList; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/AlwaysSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/AlwaysSampler.java similarity index 58% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/AlwaysSampler.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/AlwaysSampler.java index 879371904..087912506 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/AlwaysSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/AlwaysSampler.java @@ -1,6 +1,6 @@ -package org.springframework.cloud.sleuth.trace.sampler; +package org.springframework.cloud.sleuth.sampler; -import org.springframework.cloud.sleuth.trace.Sampler; +import org.springframework.cloud.sleuth.Sampler; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/IsTracingSampler.java similarity index 53% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/IsTracingSampler.java index be4b27447..72eee8cbe 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/sampler/IsTracingSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/IsTracingSampler.java @@ -1,7 +1,7 @@ -package org.springframework.cloud.sleuth.trace.sampler; +package org.springframework.cloud.sleuth.sampler; -import org.springframework.cloud.sleuth.trace.Sampler; -import org.springframework.cloud.sleuth.trace.SpanHolder; +import org.springframework.cloud.sleuth.Sampler; +import org.springframework.cloud.sleuth.SpanHolder; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAspect.java similarity index 81% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAspect.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAspect.java index 41d78ff25..e4943adc5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAspect.java @@ -1,10 +1,10 @@ -package org.springframework.cloud.sleuth.trace.intercept.scheduling; +package org.springframework.cloud.sleuth.scheduling; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; -import org.springframework.cloud.sleuth.trace.Trace; -import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; import org.springframework.scheduling.annotation.Scheduled; /** @@ -16,7 +16,7 @@ import org.springframework.scheduling.annotation.Scheduled; * @author Marcin Grzejszczak, 4financeIT * @author Spencer Gibb * - * @see org.springframework.cloud.sleuth.trace.Trace + * @see Trace */ @Aspect public class TraceSchedulingAspect { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java similarity index 84% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java index 590264775..f0e31e71c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/scheduling/TraceSchedulingAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java @@ -1,10 +1,10 @@ -package org.springframework.cloud.sleuth.trace.intercept.scheduling; +package org.springframework.cloud.sleuth.scheduling; /** * @author Spencer Gibb */ -import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.Trace; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java index 3d1acd172..d46ef23b1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java @@ -1,11 +1,11 @@ package org.springframework.cloud.sleuth.slf4j; -import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; -import org.springframework.cloud.sleuth.trace.Span; -import org.springframework.cloud.sleuth.trace.SpanReceiver; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanReceiver; import javax.annotation.PostConstruct; import java.io.IOException; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java index c1ba9a5d0..ebf1c090e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java @@ -3,9 +3,9 @@ package org.springframework.cloud.sleuth.slf4j; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; -import org.springframework.cloud.sleuth.trace.Span; -import org.springframework.cloud.sleuth.trace.SpanStartListener; -import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanStartListener; +import org.springframework.cloud.sleuth.Trace; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java similarity index 91% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceFilter.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java index 7b8972e2b..0faec9184 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.trace.intercept.web; +package org.springframework.cloud.sleuth.web; -import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.util.StringUtils.hasText; import java.io.IOException; @@ -31,10 +31,10 @@ import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; -import org.springframework.cloud.sleuth.trace.MilliSpan; -import org.springframework.cloud.sleuth.trace.Span; -import org.springframework.cloud.sleuth.trace.Trace; -import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.cloud.sleuth.MilliSpan; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; import org.springframework.web.filter.OncePerRequestFilter; /** diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java similarity index 93% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAspect.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java index adbd8620f..9397c7849 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java @@ -1,6 +1,6 @@ -package org.springframework.cloud.sleuth.trace.intercept.web; +package org.springframework.cloud.sleuth.web; -import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import java.util.ArrayList; import java.util.List; @@ -10,8 +10,8 @@ import lombok.extern.apachecommons.CommonsLog; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Pointcut; -import org.springframework.cloud.sleuth.trace.Trace; -import org.springframework.cloud.sleuth.trace.TraceScope; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Controller; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java similarity index 95% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java index 4c0316504..df7719d21 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.trace.intercept.web; +package org.springframework.cloud.sleuth.web; import java.util.regex.Pattern; @@ -23,7 +23,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.embedded.FilterRegistrationBean; -import org.springframework.cloud.sleuth.trace.Trace; +import org.springframework.cloud.sleuth.Trace; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java similarity index 84% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceRestTemplateInterceptor.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java index 6e485e912..4dc7b9332 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceRestTemplateInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.trace.intercept.web.client; +package org.springframework.cloud.sleuth.web.client; -import static org.springframework.cloud.sleuth.trace.Trace.SPAN_ID_NAME; -import static org.springframework.cloud.sleuth.trace.Trace.TRACE_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; import java.io.IOException; -import org.springframework.cloud.sleuth.trace.SpanHolder; +import org.springframework.cloud.sleuth.SpanHolder; +import org.springframework.cloud.sleuth.Trace; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; @@ -31,7 +32,7 @@ import org.springframework.http.client.ClientHttpResponse; * request and sets them if one or both of them are missing. * * @see org.springframework.web.client.RestTemplate - * @see org.springframework.cloud.sleuth.trace.Trace + * @see Trace * * @author Marcin Grzejszczak, 4financeIT * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceWebClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceWebClientAutoConfiguration.java similarity index 93% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceWebClientAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceWebClientAutoConfiguration.java index 96230a482..2fc38fe4d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/intercept/web/client/TraceWebClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceWebClientAutoConfiguration.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace.intercept.web.client; +package org.springframework.cloud.sleuth.web.client; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories index 674340da8..f13ffc5a5 100644 --- a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories @@ -1,7 +1,7 @@ # Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration,\ -org.springframework.cloud.sleuth.trace.TraceAutoConfiguration,\ -org.springframework.cloud.sleuth.trace.intercept.web.TraceWebAutoConfiguration,\ -org.springframework.cloud.sleuth.trace.intercept.web.client.TraceWebClientAutoConfiguration,\ +org.springframework.cloud.sleuth.TraceAutoConfiguration,\ +org.springframework.cloud.sleuth.web.TraceWebAutoConfiguration,\ +org.springframework.cloud.sleuth.web.client.TraceWebClientAutoConfiguration,\ org.springframework.cloud.sleuth.slf4j.SleuthSlf4jAutoConfiguration diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java similarity index 91% rename from spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java rename to spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java index 05a8b4da7..a85f21995 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTraceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.trace; +package org.springframework.cloud.sleuth; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -11,10 +11,9 @@ import java.util.List; import lombok.Data; import org.junit.Test; -import org.springframework.cloud.sleuth.RandomUuidGenerator; -import org.springframework.cloud.sleuth.trace.receiver.ArrayListSpanReceiver; -import org.springframework.cloud.sleuth.trace.sampler.AlwaysSampler; -import org.springframework.cloud.sleuth.trace.sampler.IsTracingSampler; +import org.springframework.cloud.sleuth.receiver.ArrayListSpanReceiver; +import org.springframework.cloud.sleuth.sampler.AlwaysSampler; +import org.springframework.cloud.sleuth.sampler.IsTracingSampler; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java index 1abd724c2..f235a9cdf 100644 --- a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java +++ b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java @@ -9,9 +9,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; -import org.springframework.cloud.sleuth.trace.Trace; -import org.springframework.cloud.sleuth.trace.TraceScope; -import org.springframework.cloud.sleuth.trace.sampler.AlwaysSampler; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; +import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.RequestMapping; From 53feadd8420a566c7268810fdb2b27c0f44f3b4a Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jun 2015 21:28:23 -0600 Subject: [PATCH 12/34] remove s-c-s-correlation, functionality moved to s-c-s-core --- spring-cloud-sleuth-correlation/pom.xml | 132 --------------- .../sleuth/logging/CorrelationIdAspect.java | 132 --------------- .../CorrelationIdAutoConfiguration.java | 74 --------- .../sleuth/logging/CorrelationIdFilter.java | 150 ------------------ .../sleuth/logging/CorrelationIdHolder.java | 39 ----- ...ationIdSettingRestTemplateInterceptor.java | 56 ------- .../sleuth/logging/CorrelationIdUpdater.java | 118 -------------- .../cloud/sleuth/logging/UuidGenerator.java | 29 ---- .../logging/hystrix/CorrelatedCommand.java | 57 ------- .../ScheduledTaskWithCorrelationIdAspect.java | 67 -------- .../TaskSchedulingConfiguration.java | 40 ----- .../main/resources/META-INF/spring.factories | 3 - .../CorrelationIdAspectISpec.groovy | 118 -------------- .../CorrelationIdFilterISpec.groovy | 59 ------- .../CorrelationIdFilterSkipPatternSpec.groovy | 68 -------- .../CorrelationIdUpdaterSpec.groovy | 68 -------- .../correlation/base/BaseConfiguration.groovy | 17 -- .../correlation/base/HttpMockServer.groovy | 31 ---- .../base/MockServerConfiguration.groovy | 25 --- ...CorrelationIdSettingIntegrationSpec.groovy | 13 -- .../base/MvcIntegrationSpec.groovy | 45 ------ .../base/MvcWiremockIntegrationSpec.groovy | 37 ----- .../hystrix/CorrelatedCommandSpec.groovy | 41 ----- ...CorrelationIdOnScheduledMethodISpec.groovy | 25 --- .../ScheduledBeanConfiguration.groovy | 14 -- .../TestBeanWithScheduledMethod.groovy | 15 -- 26 files changed, 1473 deletions(-) delete mode 100644 spring-cloud-sleuth-correlation/pom.xml delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAspect.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAutoConfiguration.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdFilter.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdHolder.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdSettingRestTemplateInterceptor.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdUpdater.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/UuidGenerator.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/hystrix/CorrelatedCommand.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/ScheduledTaskWithCorrelationIdAspect.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/TaskSchedulingConfiguration.java delete mode 100644 spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/BaseConfiguration.groovy delete mode 100755 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/HttpMockServer.groovy delete mode 100755 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MockServerConfiguration.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy delete mode 100755 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcIntegrationSpec.groovy delete mode 100755 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcWiremockIntegrationSpec.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/ScheduledBeanConfiguration.groovy delete mode 100644 spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy diff --git a/spring-cloud-sleuth-correlation/pom.xml b/spring-cloud-sleuth-correlation/pom.xml deleted file mode 100644 index 697ebf14a..000000000 --- a/spring-cloud-sleuth-correlation/pom.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - 4.0.0 - - spring-cloud-sleuth-correlation - jar - Spring Cloud Sleuth Correlation - Spring Cloud Sleuth Correlation - - - org.springframework.cloud - spring-cloud-sleuth - 1.0.0.BUILD-SNAPSHOT - .. - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.codehaus.gmavenplus - gmavenplus-plugin - - - maven-surefire-plugin - - - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.cloud - spring-cloud-sleuth-core - - - org.springframework.boot - spring-boot-starter-actuator - true - - - commons-lang - commons-lang - - - org.projectlombok - lombok - - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - com.netflix.hystrix - hystrix-core - - - org.aspectj - aspectjrt - - - org.aspectj - aspectjweaver - runtime - - - io.reactivex - rxjava - - - - org.spockframework - spock-core - test - - - org.spockframework - spock-spring - test - - - cglib - cglib-nodep - test - - - org.objenesis - objenesis - test - - - org.hamcrest - hamcrest-core - test - - - org.codehaus.groovy - groovy-all - test - - - org.codehaus.gpars - gpars - 1.2.1 - test - - - com.github.tomakehurst - wiremock - 1.53 - test - - - com.github.stefanbirkner - system-rules - 1.9.0 - test - - - - diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAspect.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAspect.java deleted file mode 100644 index 23b995ded..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAspect.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2012-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.logging; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.RestOperations; - -import java.lang.invoke.MethodHandles; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; - -/** - * Aspect that adds correlation id to - *

- *

    - *
  • {@link RestController} annotated classes - * with public {@link Callable} methods
  • - *
  • {@link Controller} annotated classes - * with public {@link Callable} methods
  • - *
  • explicit {@link RestOperations}.exchange(..) method calls
  • - *
- *

- * For controllers an around aspect is created that wraps the {@link Callable#call()} method execution - * in {@link CorrelationIdUpdater#wrapCallableWithId(Callable)} - *

- * For {@link RestOperations} we are wrapping all executions of the - * exchange methods and we are extracting {@link HttpHeaders} from the passed {@link HttpEntity}. - * Next we are adding correlation id header {@link CorrelationIdHolder#CORRELATION_ID_HEADER} with - * the value taken from {@link CorrelationIdHolder}. Finally the method execution proceeds. - * - * @see RestController - * @see Controller - * @see RestOperations - * @see CorrelationIdHolder - * @see CorrelationIdFilter - * - * @author Tomasz Nurkewicz, 4financeIT - * @author Marcin Grzejszczak, 4financeIT - * @author Michal Chmielarz, 4financeIT - */ -@Aspect -public class CorrelationIdAspect { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private static final int HTTP_ENTITY_PARAM_INDEX = 2; - - @Pointcut("@target(org.springframework.web.bind.annotation.RestController)") - private void anyRestControllerAnnotated() { - } - - @Pointcut("@target(org.springframework.stereotype.Controller)") - private void anyControllerAnnotated() { - } - - @Pointcut("execution(public java.util.concurrent.Callable *(..))") - private void anyPublicMethodReturningCallable() { - } - - @Pointcut("(anyRestControllerAnnotated() || anyControllerAnnotated()) && anyPublicMethodReturningCallable()") - private void anyControllerOrRestControllerWithPublicAsyncMethod() { - } - - @Around("anyControllerOrRestControllerWithPublicAsyncMethod()") - public Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable { - final Callable callable = (Callable) pjp.proceed(); - log.debug("Wrapping callable with correlation id [" + CorrelationIdHolder.get() + "]"); - return CorrelationIdUpdater.wrapCallableWithId(new Callable() { - @Override - public Object call() throws Exception { - return callable.call(); - } - }); - } - - @Pointcut("execution(public * org.springframework.web.client.RestOperations.exchange(..))") - private void anyExchangeRestOperationsMethod() { - } - - @Around("anyExchangeRestOperationsMethod()") - public Object wrapWithCorrelationIdForRestOperations(ProceedingJoinPoint pjp) throws Throwable { - String correlationId = CorrelationIdHolder.get(); - log.debug("Wrapping RestTemplate call with correlation id [" + correlationId + "]"); - HttpEntity httpEntity = (HttpEntity) pjp.getArgs()[HTTP_ENTITY_PARAM_INDEX]; - HttpEntity newHttpEntity = createNewHttpEntity(httpEntity, correlationId); - List newArgs = modifyHttpEntityInMethodArguments(pjp, newHttpEntity); - return pjp.proceed(newArgs.toArray()); - } - - @SuppressWarnings("unchecked") - private HttpEntity createNewHttpEntity(HttpEntity httpEntity, String correlationId) { - HttpHeaders newHttpHeaders = new HttpHeaders(); - newHttpHeaders.putAll(httpEntity.getHeaders()); - newHttpHeaders.add(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); - return new HttpEntity(httpEntity.getBody(), newHttpHeaders); - } - - private List modifyHttpEntityInMethodArguments(ProceedingJoinPoint pjp, HttpEntity newHttpEntity) { - List newArgs = new ArrayList<>(); - for (int i = 0; i < pjp.getArgs().length; i++) { - Object arg = pjp.getArgs()[i]; - if (i != HTTP_ENTITY_PARAM_INDEX) { - newArgs.add(i, arg); - } else { - newArgs.add(i, newHttpEntity); - } - } - return newArgs; - } -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAutoConfiguration.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAutoConfiguration.java deleted file mode 100644 index 4d5f4aac2..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdAutoConfiguration.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012-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.logging; - -import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.embedded.FilterRegistrationBean; -import org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.regex.Pattern; - -/** - * Registers beans that add correlation id to requests - * - * @see CorrelationIdAspect - * @see CorrelationIdFilter - * - * @author Tomasz Nurkewicz, 4financeIT - * @author Marcin Grzejszczak, 4financeIT - * @author Michal Chmielarz, 4financeIT - */ -@Configuration -@ConditionalOnProperty(value = "spring.cloud.sleuth.correlation.enabled", matchIfMissing = true) -@AutoConfigureAfter(SleuthRestTemplateAutoConfiguration.class) -public class CorrelationIdAutoConfiguration { - - /** - * Pattern for URLs that should be skipped in correlationID setting - */ - @Value("${spring.cloud.sleuth.correlation.skipPattern:}") - private String skipPattern; - - @Bean - @ConditionalOnMissingBean - public CorrelationIdAspect correlationIdAspect() { - return new CorrelationIdAspect(); - } - - @Bean - @ConditionalOnMissingBean - public FilterRegistrationBean correlationHeaderFilter(UuidGenerator uuidGenerator) { - Pattern pattern = StringUtils.isBlank(skipPattern) ? Pattern.compile(skipPattern) : CorrelationIdFilter.DEFAULT_SKIP_PATTERN; - return new FilterRegistrationBean(new CorrelationIdFilter(uuidGenerator, pattern)); - } - - @Bean - @ConditionalOnMissingBean - public UuidGenerator uuidGenerator() { - return new UuidGenerator(); - } - - @Bean - public CorrelationIdSettingRestTemplateInterceptor correlationIdSettingRestTemplateInterceptor() { - return new CorrelationIdSettingRestTemplateInterceptor(); - } -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdFilter.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdFilter.java deleted file mode 100644 index 78aabfd99..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdFilter.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2012-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.logging; - -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.util.concurrent.Callable; -import java.util.regex.Pattern; - -import static org.springframework.util.StringUtils.hasText; - -/** - * Filter that takes the value of the {@link CorrelationIdHolder#CORRELATION_ID_HEADER} header - * from either request or response and sets it in the {@link CorrelationIdHolder}. It also provides - * that value in {@link MDC} logging related class so that logger prints the value of - * correlation id at each log. - * - * @see CorrelationIdHolder - * @see MDC - * - * @author Jakub Nabrdalik, 4financeIT - * @author Tomasz Nurkiewicz, 4financeIT - * @author Marcin Grzejszczak, 4financeIT - */ -public class CorrelationIdFilter extends OncePerRequestFilter { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - public static final Pattern DEFAULT_SKIP_PATTERN = Pattern.compile("/api-docs.*|/autoconfig|/configprops|/dump|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html"); - - private final Pattern skipCorrId; - private final UuidGenerator uuidGenerator; - - public CorrelationIdFilter() { - this.uuidGenerator = new UuidGenerator(); - this.skipCorrId = null; - } - - public CorrelationIdFilter(UuidGenerator uuidGenerator, Pattern skipCorrId) { - this.uuidGenerator = uuidGenerator; - this.skipCorrId = skipCorrId; - } - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - setupCorrelationId(request, response); - try { - filterChain.doFilter(request, response); - } finally { - cleanupCorrelationId(); - } - } - - private void setupCorrelationId(HttpServletRequest request, HttpServletResponse response) { - String correlationIdFromRequest = getCorrelationIdFrom(request); - String correlationId = (hasText(correlationIdFromRequest)) ? correlationIdFromRequest : getCorrelationIdFrom(response); - if (!hasText(correlationId) && shouldGenerateCorrId(request)) { - correlationId = createNewCorrIdIfEmpty(); - } - CorrelationIdHolder.set(correlationId); - addCorrelationIdToResponseIfNotPresent(response, correlationId); - } - - private String getCorrelationIdFrom(final HttpServletResponse response) { - return withLoggingAs("response", new Callable() { - @Override - public String call() throws Exception { - return response.getHeader(CorrelationIdHolder.CORRELATION_ID_HEADER); - } - }); - } - - private String getCorrelationIdFrom(final HttpServletRequest request) { - return withLoggingAs("request", new Callable() { - @Override - public String call() throws Exception { - return request.getHeader(CorrelationIdHolder.CORRELATION_ID_HEADER); - } - }); - } - - private String withLoggingAs(String whereWasFound, Callable correlationIdGetter) { - String correlationId = tryToGetCorrelationId(correlationIdGetter); - if (hasText(correlationId)) { - MDC.put(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); - log.debug("Found correlationId in " + whereWasFound + ": " + correlationId); - } - return correlationId; - } - - private String tryToGetCorrelationId(Callable correlationIdGetter) { - try { - return correlationIdGetter.call(); - } catch (Exception e) { - log.error("Exception occurred while trying to retrieve request header", e); - return StringUtils.EMPTY; - } - } - - private String createNewCorrIdIfEmpty() { - String currentCorrId = uuidGenerator.create(); - MDC.put(CorrelationIdHolder.CORRELATION_ID_HEADER, currentCorrId); - log.debug("Generating new correlationId: " + currentCorrId); - return currentCorrId; - } - - protected boolean shouldGenerateCorrId(HttpServletRequest request) { - final String i = request.getRequestURI(); - final String uri = StringUtils.defaultIfEmpty(i, StringUtils.EMPTY); - boolean skip = skipCorrId != null && skipCorrId.matcher(uri).matches(); - return !skip; - } - - private void addCorrelationIdToResponseIfNotPresent(HttpServletResponse response, String correlationId) { - if (!hasText(response.getHeader(CorrelationIdHolder.CORRELATION_ID_HEADER))) { - response.addHeader(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); - } - } - - private void cleanupCorrelationId() { - MDC.remove(CorrelationIdHolder.CORRELATION_ID_HEADER); - CorrelationIdHolder.remove(); - } - - @Override - protected boolean shouldNotFilterAsyncDispatch() { - return false; - } -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdHolder.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdHolder.java deleted file mode 100644 index 291bc747a..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdHolder.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012-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.logging; - -/** - * Component that stores correlation id using {@link ThreadLocal} - * - * @author Jakub Nabrdalik, 4financeIT - * @author Marcin Zajaczkowski, 4financeIT - */ -public class CorrelationIdHolder { - public static final String CORRELATION_ID_HEADER = "Correlation-Id"; - private static final ThreadLocal id = new ThreadLocal(); - - public static void set(String correlationId) { - id.set(correlationId); - } - - public static String get() { - return id.get(); - } - - public static void remove() { - id.remove(); - } -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdSettingRestTemplateInterceptor.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdSettingRestTemplateInterceptor.java deleted file mode 100644 index c17a6fc57..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdSettingRestTemplateInterceptor.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012-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.logging; - -import lombok.SneakyThrows; -import org.springframework.http.HttpRequest; -import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.http.client.ClientHttpResponse; - -import java.io.IOException; - -/** - * Interceptor that verifies whether the correlation id has been - * set on the request and sets it if it's missing. - * - * @see org.springframework.web.client.RestTemplate - * @see CorrelationIdHolder - * - * @author Marcin Grzejszczak, 4financeIT - */ -public class CorrelationIdSettingRestTemplateInterceptor implements ClientHttpRequestInterceptor { - - @SneakyThrows - @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { - appendCorrelationIdToRequestIfMissing(request); - ClientHttpResponse response = null; - try { - response = execution.execute(request, body); - } catch (final Exception e) { - throw new RuntimeException(e); - } - return response; - } - - private void appendCorrelationIdToRequestIfMissing(HttpRequest request) { - if (!request.getHeaders().containsKey(CorrelationIdHolder.CORRELATION_ID_HEADER)) { - request.getHeaders().add(CorrelationIdHolder.CORRELATION_ID_HEADER, CorrelationIdHolder.get()); - } - } - -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdUpdater.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdUpdater.java deleted file mode 100644 index 29f2afbcc..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/CorrelationIdUpdater.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2012-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.logging; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.springframework.util.StringUtils; - -import java.lang.invoke.MethodHandles; -import java.util.concurrent.Callable; - -/** - * Class that takes care of updating all necessary components with new value - * of correlation id. - * It sets correlationId on {@link ThreadLocal} in {@link CorrelationIdHolder} - * and in {@link MDC}. - * - * @see CorrelationIdHolder - * @see MDC - * - * @author Jakub Nabrdalik, 4financeIT - * @author Michal Chmielarz, 4financeIT - */ -public class CorrelationIdUpdater { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - public static void updateCorrelationId(String correlationId) { - if (StringUtils.hasText(correlationId)) { - log.debug("Updating correlationId with value: [" + correlationId + "]"); - CorrelationIdHolder.set(correlationId); - MDC.put(CorrelationIdHolder.CORRELATION_ID_HEADER, correlationId); - } - } - - /** - * Temporarily updates correlation ID inside block of code. - * Makes sure previous ID is restored after block's execution - * - * @param temporaryCorrelationId - correlationID to passed to the executed block of code - * @param block Callable to be executed with new ID - * @return the result of Callable block execution - */ - public static T withId(String temporaryCorrelationId, Callable block) { - final String oldCorrelationId = CorrelationIdHolder.get(); - try { - updateCorrelationId(temporaryCorrelationId); - return block.call(); - } catch (RuntimeException e) { - logException(e); - throw e; - } catch (Exception e) { - logException(e); - throw new RuntimeException(e); - } finally { - updateCorrelationId(oldCorrelationId); - } - - } - - private static void logException(Throwable e) { - log.error("Exception occurred while trying to execute the function", e); - } - - /** - * Wraps given {@link Callable} with another {@link Callable Callable} propagating correlation ID inside nested - * Callable/Closure. - *

- *

- * Useful in a situation when a Callable should be executed in a separate thread, for example in aspects. - *

- *


-	 * @Around('...')
-	 * Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable {
-	 *     Callable callable = pjp.proceed() as Callable
-	 *     return CorrelationIdUpdater.wrapCallableWithId {
-	 *         callable.call()
-	 *     }
-	 * }
-	 * 
- *

- * Note: Passing only one input parameter currently is supported. - * - * @param block code block to execute in a thread with a correlation ID taken from the original thread - * @return wrapping block as Callable - */ - @SuppressWarnings("unchecked") - public static Callable wrapCallableWithId(final Callable block) { - final String temporaryCorrelationId = CorrelationIdHolder.get(); - // unchecked assignment due to groovyc issues with - return new Callable() { - @Override - public Object call() throws Exception { - final String oldCorrelationId = CorrelationIdHolder.get(); - try { - updateCorrelationId(temporaryCorrelationId); - return block.call(); - } finally { - updateCorrelationId(oldCorrelationId); - } - } - }; - } -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/UuidGenerator.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/UuidGenerator.java deleted file mode 100644 index a289a0a0a..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/UuidGenerator.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012-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.logging; - -import java.util.UUID; - -/** - * Default Uuid generator - * - * @author extends HystrixCommand { - private final String clientCorrelationId = CorrelationIdHolder.get(); - - protected CorrelatedCommand(HystrixCommandGroupKey group) { - super(group); - } - - protected CorrelatedCommand(Setter setter) { - super(setter); - } - - @Override - protected final R run() throws Exception { - return CorrelationIdUpdater.withId(clientCorrelationId, new Callable() { - @Override - public R call() throws Exception { - return doRun(); - } - - }); - } - - public abstract R doRun() throws Exception; -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/ScheduledTaskWithCorrelationIdAspect.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/ScheduledTaskWithCorrelationIdAspect.java deleted file mode 100644 index 63fed0ecc..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/ScheduledTaskWithCorrelationIdAspect.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2012-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.logging.scheduling; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.sleuth.logging.CorrelationIdUpdater; -import org.springframework.cloud.sleuth.logging.UuidGenerator; -import org.springframework.scheduling.annotation.Scheduled; - -import java.lang.invoke.MethodHandles; -import java.util.concurrent.Callable; - -/** - * Aspect that sets correlationId for running threads executing methods annotated with {@link Scheduled} annotation. - * For every execution of scheduled method a new, i.e. unique one, value of correlationId will be set. - * - * @author Tomasz Nurkewicz, 4financeIT - * @author Michal Chmielarz, 4financeIT - * @author Marcin Grzejszczak, 4financeIT - * - * @see UuidGenerator - * @see CorrelationIdUpdater - */ -@Aspect -public class ScheduledTaskWithCorrelationIdAspect { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private final UuidGenerator uuidGenerator; - - public ScheduledTaskWithCorrelationIdAspect(UuidGenerator uuidGenerator) { - this.uuidGenerator = uuidGenerator; - } - - @Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))") - public Object setNewCorrelationIdOnThread(final ProceedingJoinPoint pjp) throws Throwable { - String correlationId = uuidGenerator.create(); - return CorrelationIdUpdater.withId(correlationId, new Callable() { - @Override - public Object call() throws Exception { - try { - return pjp.proceed(); - } catch (Throwable throwable) { - log.error("Didn't manage to proceed with the pointcut", throwable); - throw new RuntimeException(throwable); - } - } - }); - } -} diff --git a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/TaskSchedulingConfiguration.java b/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/TaskSchedulingConfiguration.java deleted file mode 100644 index 3e825f7ef..000000000 --- a/spring-cloud-sleuth-correlation/src/main/java/org/springframework/cloud/sleuth/logging/scheduling/TaskSchedulingConfiguration.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012-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.logging.scheduling; - -import org.springframework.cloud.sleuth.logging.UuidGenerator; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.scheduling.annotation.EnableScheduling; - -/** - * Registers beans related to task scheduling. - * - * @see ScheduledTaskWithCorrelationIdAspect - * - * @author Michal Chmielarz, 4financeIT - */ -@Configuration -@EnableScheduling -@EnableAspectJAutoProxy -public class TaskSchedulingConfiguration { - @Bean - public ScheduledTaskWithCorrelationIdAspect scheduledTaskPointcut(UuidGenerator uuidGenerator) { - return new ScheduledTaskWithCorrelationIdAspect(uuidGenerator); - } - -} diff --git a/spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories deleted file mode 100644 index ec398fdbf..000000000 --- a/spring-cloud-sleuth-correlation/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -# Auto Configuration -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.sleuth.correlation.logging.CorrelationIdAutoConfiguration diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy deleted file mode 100644 index e47e47720..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdAspectISpec.groovy +++ /dev/null @@ -1,118 +0,0 @@ -package org.springframework.cloud.sleuth.correlation -import groovy.transform.CompileStatic -import groovy.transform.PackageScope -import groovy.transform.TypeChecked -import org.hamcrest.Description -import org.hamcrest.TypeSafeMatcher -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.boot.test.SpringApplicationContextLoader -import org.springframework.cloud.sleuth.correlation.base.HttpMockServer -import org.springframework.cloud.sleuth.correlation.base.MvcCorrelationIdSettingIntegrationSpec -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.EnableAspectJAutoProxy -import org.springframework.http.MediaType -import org.springframework.scheduling.annotation.EnableAsync -import org.springframework.test.context.ContextConfiguration -import org.springframework.test.web.servlet.MvcResult -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders -import org.springframework.test.web.servlet.result.MockMvcResultHandlers -import org.springframework.test.web.servlet.result.MockMvcResultMatchers -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestMethod -import org.springframework.web.bind.annotation.RestController -import org.springframework.web.client.RestTemplate - -import java.util.concurrent.Callable -import java.util.concurrent.TimeUnit - -import static com.github.tomakehurst.wiremock.client.WireMock.* -import static org.springframework.cloud.sleuth.logging.CorrelationIdHolder.CORRELATION_ID_HEADER - -@ContextConfiguration(classes = [CorrelationIdAspectSpecConfiguration], loader = SpringApplicationContextLoader) -class CorrelationIdAspectISpec extends MvcCorrelationIdSettingIntegrationSpec { - - public static final String CORRELATION_ID_PATTERN = /^(?!\s*$).+/ - public static final TypeSafeMatcher hasCorrelationIdSet = new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(String item) { - return item.matches(CORRELATION_ID_PATTERN) - } - - @Override - void describeTo(Description description) { - - } - } - - def "should set correlationId on header via aspect in synchronous call"() { - given: - stubInteraction(get(urlMatching('.*')), aResponse().withStatus(200)) - when: - mockMvc.perform(MockMvcRequestBuilders.get('/syncPing').accept(MediaType.TEXT_PLAIN)) - .andExpect(MockMvcResultMatchers.header().string(CORRELATION_ID_HEADER, hasCorrelationIdSet)) - then: - wireMock.verifyThat(getRequestedFor(urlMatching('.*')).withHeader(CORRELATION_ID_HEADER, matching(CORRELATION_ID_PATTERN))) - - } - - def "should set correlationId on header via aspect in asynchronous call"() { - given: - stubInteraction(get(urlMatching('.*')), aResponse().withStatus(200)) - when: - MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get('/asyncPing').accept(MediaType.TEXT_PLAIN)) - .andExpect(MockMvcResultMatchers.request().asyncStarted()) - .andReturn() - and: - mvcResult.getAsyncResult(TimeUnit.SECONDS.toMillis(2)) - then: - mockMvc.perform(MockMvcRequestBuilders.asyncDispatch(mvcResult)). - andDo(MockMvcResultHandlers.print()). - andExpect(MockMvcResultMatchers.status().isOk()). - andExpect(MockMvcResultMatchers.header().string(CORRELATION_ID_HEADER, hasCorrelationIdSet)) - and: - wireMock.verifyThat(getRequestedFor(urlMatching('.*')).withHeader(CORRELATION_ID_HEADER, matching(CORRELATION_ID_PATTERN))) - } - - @CompileStatic - @Configuration - @EnableAsync - @EnableAutoConfiguration - @EnableAspectJAutoProxy(proxyTargetClass = true) - static class CorrelationIdAspectSpecConfiguration { - @Bean - AspectTestingController aspectTestingController() { - return new AspectTestingController() - } - } - - @RestController - @TypeChecked - @PackageScope - static class AspectTestingController { - - @Autowired - private HttpMockServer httpMockServer - @Autowired - private RestTemplate restTemplate - - @RequestMapping(value = "/syncPing", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) - String syncPing() { - callWiremockAndReturnOk() - } - - @RequestMapping(value = "/asyncPing", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) - Callable asyncPing() { - return { - callWiremockAndReturnOk() - } - } - - private String callWiremockAndReturnOk() { - restTemplate.getForObject("http://localhost:${httpMockServer.port()}", String) - return "OK" - } - } - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy deleted file mode 100644 index 282191849..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterISpec.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package org.springframework.cloud.sleuth.correlation - -import org.slf4j.MDC -import org.springframework.boot.test.SpringApplicationContextLoader -import org.springframework.cloud.sleuth.correlation.base.BaseConfiguration -import org.springframework.cloud.sleuth.correlation.base.MvcCorrelationIdSettingIntegrationSpec -import org.springframework.cloud.sleuth.logging.CorrelationIdAutoConfiguration -import org.springframework.cloud.sleuth.logging.CorrelationIdHolder -import org.springframework.http.MediaType -import org.springframework.test.context.ContextConfiguration -import org.springframework.test.web.servlet.MvcResult -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders - -@ContextConfiguration(classes = [BaseConfiguration, CorrelationIdAutoConfiguration], loader = SpringApplicationContextLoader) -class CorrelationIdFilterISpec extends MvcCorrelationIdSettingIntegrationSpec { - - def "should create and return correlationId in HTTP header"() { - when: - MvcResult mvcResult = sendPingWithoutCorrelationId() - - then: - getCorrelationIdFromResponseHeader(mvcResult) != null - } - - def "when correlationId is sent, should not create a new one, but return the existing one instead"() { - given: - String passedCorrelationId = "passedCorId" - - when: - MvcResult mvcResult = sendPingWithCorrelationId(passedCorrelationId) - - then: - getCorrelationIdFromResponseHeader(mvcResult) == passedCorrelationId - } - - def "should clean up MDC after the call"() { - given: - String passedCorrelationId = "passedCorId" - - when: - sendPingWithCorrelationId(passedCorrelationId) - - then: - MDC.get(CorrelationIdHolder.CORRELATION_ID_HEADER) == null - } - - private MvcResult sendPingWithCorrelationId(String passedCorrelationId) { - mockMvc.perform(MockMvcRequestBuilders.get('/ping').accept(MediaType.TEXT_PLAIN) - .header(CorrelationIdHolder.CORRELATION_ID_HEADER, passedCorrelationId)).andReturn() - } - - private MvcResult sendPingWithoutCorrelationId() { - mockMvc.perform(MockMvcRequestBuilders.get('/ping').accept(MediaType.TEXT_PLAIN)).andReturn() - } - - private String getCorrelationIdFromResponseHeader(MvcResult mvcResult) { - mvcResult.response.getHeader(CorrelationIdHolder.CORRELATION_ID_HEADER) - } -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy deleted file mode 100644 index 55dc7f241..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdFilterSkipPatternSpec.groovy +++ /dev/null @@ -1,68 +0,0 @@ -package org.springframework.cloud.sleuth.correlation - -import org.springframework.cloud.sleuth.logging.CorrelationIdFilter -import org.springframework.cloud.sleuth.logging.CorrelationIdHolder -import org.springframework.cloud.sleuth.logging.UuidGenerator -import spock.lang.Specification -import spock.lang.Unroll - -import javax.servlet.FilterChain -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -@Unroll -class CorrelationIdFilterSkipPatternSpec extends Specification { - - CorrelationIdFilter filter = new CorrelationIdFilter(Stub(UuidGenerator), CorrelationIdFilter.DEFAULT_SKIP_PATTERN) - - def 'should skip meaningless URIs like #uri'() { - given: - HttpServletResponse responseMock = Mock(HttpServletResponse) - HttpServletRequest requestMock = Mock(HttpServletRequest) - and: - requestMock.getRequestURI() >> uri - when: - filter.doFilter(requestMock, responseMock, Stub(FilterChain)) - then: - 0 * responseMock.addHeader(CorrelationIdHolder.CORRELATION_ID_HEADER, _ as String) - where: - uri | _ - '/api-docs' | _ - '/api-docs/default' | _ - '/swagger' | _ - '/trace' | _ - '/metrics' | _ - '/metrics/foo' | _ - '/mappings' | _ - '/autoconfig' | _ - '/configprops' | _ - '/info' | _ - '/dump' | _ - '/swagger/foo' | _ - '/foo.js' | _ - '/foo/bar.png' | _ - '/foo/bar.html' | _ - '/foo/bar.css' | _ - '/foo/bar.js' | _ - '/foo/bar.js' | _ - } - - def 'should not skip #uri'() { - given: - HttpServletResponse responseMock = Mock(HttpServletResponse) - HttpServletRequest requestMock = Mock(HttpServletRequest) - and: - requestMock.getRequestURI() >> uri - when: - filter.doFilter(requestMock, responseMock, Stub(FilterChain)) - then: - 1 * responseMock.addHeader(CorrelationIdHolder.CORRELATION_ID_HEADER, _ as String) - where: - uri | _ - '/business/api-docs' | _ - '/business/swagger/foo' | _ - '/foo.js/service' | _ - } - - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy deleted file mode 100644 index 1d68af8c1..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/CorrelationIdUpdaterSpec.groovy +++ /dev/null @@ -1,68 +0,0 @@ -package org.springframework.cloud.sleuth.correlation - -import groovyx.gpars.GParsPool -import org.springframework.cloud.sleuth.logging.CorrelationIdHolder -import org.springframework.cloud.sleuth.logging.CorrelationIdUpdater -import spock.lang.Specification - -import java.util.concurrent.Callable -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - -class CorrelationIdUpdaterSpec extends Specification { - - def cleanup() { - CorrelationIdHolder.remove() - } - - def "correlation ID should not be propagated to other thread by default"() { - given: - CorrelationIdUpdater.updateCorrelationId('A') - expect: - GParsPool.withPool(1) { - ["1"].eachParallel { - assert CorrelationIdHolder.get() == null - } - } - } - - def "should propagate correlation ID into nested Callable"() { - given: - ExecutorService threadPool = Executors.newFixedThreadPool(1) - CorrelationIdUpdater.updateCorrelationId('A') - Callable callable = new CorrelationIdTestCallable() - when: - Callable wrappedCallable = CorrelationIdUpdater.wrapCallableWithId(callable) - String nestedCorrelationId = threadPool.submit(wrappedCallable).get(1, TimeUnit.SECONDS) - then: - nestedCorrelationId == 'A' - cleanup: - threadPool.shutdown() - } - - def "should restore previous correlation ID after Callable execution in other thread"() { - given: - ExecutorService threadPool = Executors.newFixedThreadPool(1) - CorrelationIdUpdater.updateCorrelationId('A') - Callable callable = new CorrelationIdTestCallable() - and: - threadPool.submit({ CorrelationIdHolder.set('B') }).get(1, TimeUnit.SECONDS) - when: - threadPool.submit(CorrelationIdUpdater.wrapCallableWithId(callable)).get(1, TimeUnit.SECONDS) - then: - def restoredCorrelationId = threadPool.submit({ - CorrelationIdHolder.get() - } as Callable).get(1, TimeUnit.SECONDS) - restoredCorrelationId == 'B' - cleanup: - threadPool.shutdown() - } - - private static class CorrelationIdTestCallable implements Callable { - @Override - String call() throws Exception { - CorrelationIdHolder.get() - } - } -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/BaseConfiguration.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/BaseConfiguration.groovy deleted file mode 100644 index d3fc8744f..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/BaseConfiguration.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.base - -import groovy.transform.CompileStatic -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer - -@CompileStatic -@Configuration -class BaseConfiguration { - - @Bean - static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { - return new PropertySourcesPlaceholderConfigurer() - } - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/HttpMockServer.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/HttpMockServer.groovy deleted file mode 100755 index 629190b34..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/HttpMockServer.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.base - -import com.github.tomakehurst.wiremock.WireMockServer -import groovy.transform.CompileStatic - -/** - * Custom implementation of {@link WireMockServer} that by default registers itself at port - * {@link HttpMockServer#DEFAULT_PORT}. - * - * @see WireMockServer - */ -@CompileStatic -class HttpMockServer extends WireMockServer { - - public static final int DEFAULT_PORT = 8030 - - HttpMockServer(int port) { - super(port) - } - - HttpMockServer() { - super(DEFAULT_PORT) - } - - void shutdownServer() { - if (isRunning()) { - stop() - } - shutdown() - } -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MockServerConfiguration.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MockServerConfiguration.groovy deleted file mode 100755 index 7e9a97c61..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MockServerConfiguration.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.base - -import groovy.transform.CompileStatic -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.util.SocketUtils - -/** - * Configuration that registers {@link HttpMockServer} as a Spring bean. Takes care - * of graceful shutdown process. - * - * @see HttpMockServer - */ -@CompileStatic -@Configuration -class MockServerConfiguration { - - @Bean(destroyMethod = 'shutdownServer') - HttpMockServer httpMockServer() { - HttpMockServer httpMockServer = new HttpMockServer(SocketUtils.findAvailableTcpPort()) - httpMockServer.start() - return httpMockServer - } - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy deleted file mode 100644 index 2361197b9..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcCorrelationIdSettingIntegrationSpec.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.base - -import org.springframework.cloud.sleuth.logging.CorrelationIdFilter -import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder - -class MvcCorrelationIdSettingIntegrationSpec extends org.springframework.cloud.sleuth.correlation.base.MvcWiremockIntegrationSpec { - - @Override - protected void configureMockMvcBuilder(ConfigurableMockMvcBuilder mockMvcBuilder) { - super.configureMockMvcBuilder(mockMvcBuilder) - mockMvcBuilder.addFilter(new CorrelationIdFilter()) - } -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcIntegrationSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcIntegrationSpec.groovy deleted file mode 100755 index 4cd63fd9e..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcIntegrationSpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.base - -import groovy.transform.CompileStatic -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.context.ApplicationContext -import org.springframework.test.context.web.WebAppConfiguration -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder -import org.springframework.test.web.servlet.setup.MockMvcBuilders -import org.springframework.web.context.WebApplicationContext -import spock.lang.Specification - -/** - * Base for specifications that use Spring's {@link MockMvc}. Provides also {@link WebApplicationContext}, - * {@link ApplicationContext}. The latter you can use to specify what - * kind of address should be returned for a given dependency name. - * - * @see WebApplicationContext - * @see ApplicationContext - */ -@CompileStatic -@WebAppConfiguration -abstract class MvcIntegrationSpec extends Specification { - - @Autowired - protected WebApplicationContext webApplicationContext - @Autowired - protected ApplicationContext applicationContext - - protected MockMvc mockMvc - - void setup() { - ConfigurableMockMvcBuilder mockMvcBuilder = MockMvcBuilders.webAppContextSetup(webApplicationContext) - configureMockMvcBuilder(mockMvcBuilder) - mockMvc = mockMvcBuilder.build() - } - - /** - * Override in a subclass to modify mockMvcBuilder configuration (e.g. add filter). - * - * The method from super class should be called. - */ - protected void configureMockMvcBuilder(ConfigurableMockMvcBuilder mockMvcBuilder) { - } -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcWiremockIntegrationSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcWiremockIntegrationSpec.groovy deleted file mode 100755 index 5e84ff830..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/base/MvcWiremockIntegrationSpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.base - -import com.github.tomakehurst.wiremock.client.MappingBuilder -import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder -import com.github.tomakehurst.wiremock.client.WireMock -import groovy.transform.CompileStatic -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.test.context.ContextConfiguration - -/** - * Base specification for tests that use Wiremock as HTTP server stub. - * By extending this specification you gain a bean with {@link HttpMockServer} and a {@link WireMock} - * instance that you can stub by using {@link MvcWiremockIntegrationSpec#stubInteraction(com.github.tomakehurst.wiremock.client.MappingBuilder, com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder)} - * - * @see MockServerConfiguration - * @see WireMock - * @see HttpMockServer - * @see MvcIntegrationSpec - */ -@CompileStatic -@ContextConfiguration(classes = [MockServerConfiguration]) -abstract class MvcWiremockIntegrationSpec extends MvcIntegrationSpec { - - @Autowired - protected HttpMockServer httpMockServer - protected WireMock wireMock - - void setup() { - wireMock = new WireMock('localhost', httpMockServer.port()) - wireMock.resetToDefaultMappings() - } - - protected void stubInteraction(MappingBuilder mapping, ResponseDefinitionBuilder response) { - wireMock.register(mapping.willReturn(response)) - } - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy deleted file mode 100644 index e572217a0..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/hystrix/CorrelatedCommandSpec.groovy +++ /dev/null @@ -1,41 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.hystrix - -import com.netflix.hystrix.HystrixCommand -import com.netflix.hystrix.HystrixCommandGroupKey -import org.springframework.cloud.sleuth.logging.CorrelationIdHolder -import org.springframework.cloud.sleuth.logging.CorrelationIdUpdater -import org.springframework.cloud.sleuth.logging.hystrix.CorrelatedCommand -import spock.lang.Specification - -class CorrelatedCommandSpec extends Specification { - - public static final String CORRELATION_ID = 'A' - - def 'should run Hystrix command with client correlation ID'() { - given: - CorrelationIdUpdater.updateCorrelationId(CORRELATION_ID) - def command = new CorrelatedCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(""))) { - String doRun() { - return CorrelationIdHolder.get() - } - } - when: - def result = command.execute() - then: - result == CORRELATION_ID - } - - def 'should run Hystrix command in different thread'() { - given: - def command = new CorrelatedCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(""))) { - String doRun() { - return Thread.currentThread().name - } - } - when: - def threadName = command.execute() - then: - Thread.currentThread().name != threadName - } - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy deleted file mode 100644 index aef08e234..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/CorrelationIdOnScheduledMethodISpec.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.scheduling - -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.cloud.sleuth.correlation.base.BaseConfiguration -import org.springframework.cloud.sleuth.logging.CorrelationIdAutoConfiguration -import org.springframework.cloud.sleuth.logging.scheduling.TaskSchedulingConfiguration -import org.springframework.test.context.ContextConfiguration -import spock.lang.Specification -import spock.util.concurrent.PollingConditions - -@ContextConfiguration(classes = [TaskSchedulingConfiguration, ScheduledBeanConfiguration, CorrelationIdAutoConfiguration, BaseConfiguration]) -class CorrelationIdOnScheduledMethodISpec extends Specification { - - @Autowired - TestBeanWithScheduledMethod beanWithScheduledMethod - - def "should have correlationId set after scheduled method has been called"() { - PollingConditions conditions = new PollingConditions(timeout: 1.5, initialDelay: 0.1, factor: 1.05) - expect: - conditions.eventually { - beanWithScheduledMethod.correlationId != null - } - } - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/ScheduledBeanConfiguration.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/ScheduledBeanConfiguration.groovy deleted file mode 100644 index 7bddf1cdb..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/ScheduledBeanConfiguration.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.scheduling - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - -@Configuration -class ScheduledBeanConfiguration { - - @Bean - TestBeanWithScheduledMethod testBeanWithScheduledMethod() { - return new TestBeanWithScheduledMethod() - } - -} diff --git a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy b/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy deleted file mode 100644 index 212b159c3..000000000 --- a/spring-cloud-sleuth-correlation/src/test/groovy/org/springframework/cloud/sleuth/correlation/scheduling/TestBeanWithScheduledMethod.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package org.springframework.cloud.sleuth.correlation.scheduling - -import org.springframework.cloud.sleuth.logging.CorrelationIdHolder -import org.springframework.scheduling.annotation.Scheduled - -class TestBeanWithScheduledMethod { - - String correlationId - - @Scheduled(fixedDelay = 50L) - void scheduledMethod() { - correlationId = CorrelationIdHolder.get() - } - -} From 956843fd01c241c08c0e377a5a3bc70eb6f27043 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 24 Jun 2015 09:59:39 -0600 Subject: [PATCH 13/34] update TraceFilter to get TraceId from request --- .../cloud/sleuth/web/TraceFilter.java | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java index 0faec9184..1b7d97de3 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java @@ -16,10 +16,10 @@ package org.springframework.cloud.sleuth.web; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; import static org.springframework.util.StringUtils.hasText; import java.io.IOException; -import java.lang.invoke.MethodHandles; import java.util.Collections; import java.util.regex.Pattern; @@ -28,9 +28,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; import org.springframework.cloud.sleuth.MilliSpan; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; @@ -38,13 +35,11 @@ import org.springframework.cloud.sleuth.TraceScope; import org.springframework.web.filter.OncePerRequestFilter; /** - * Filter that takes the value of the {@link CorrelationIdHolder#CORRELATION_ID_HEADER} - * header from either request or response and sets it in the {@link CorrelationIdHolder}. - * It also provides that value in {@link MDC} logging related class so that logger prints - * the value of correlation id at each log. + * Filter that takes the value of the {@link Trace#SPAN_ID_NAME} and + * {@link Trace#TRACE_ID_NAME} header from either request or response and uses them to + * create a new span. * * @see Trace - * @see MDC * * @author Jakub Nabrdalik, 4financeIT * @author Tomasz Nurkiewicz, 4financeIT @@ -52,8 +47,7 @@ import org.springframework.web.filter.OncePerRequestFilter; * @author Spencer Gibb */ public class TraceFilter extends OncePerRequestFilter { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup() - .lookupClass()); + public static final Pattern DEFAULT_SKIP_PATTERN = Pattern .compile("/api-docs.*|/autoconfig|/configprops|/dump|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html"); @@ -74,44 +68,51 @@ public class TraceFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - String spanIdFromRequest = getSpanIdFrom(request); - String spanId = (hasText(spanIdFromRequest)) ? spanIdFromRequest - : getSpanIdFrom(response); + + String uri = hasText(request.getRequestURI()) ? request.getRequestURI() : ""; + boolean skip = skipPattern.matcher(uri).matches(); TraceScope traceScope = null; - if (spanId != null) { - addCorrelationIdToResponseIfNotPresent(response, spanId); + if (!skip) { + String spanId = getHeader(request, response, SPAN_ID_NAME); + String traceId = getHeader(request, response, TRACE_ID_NAME); + if (hasText(spanId) && hasText(traceId)) { - Span span = MilliSpan.builder().traceId("") // FIXME get traceId from request - .parents(Collections.singletonList(spanId)) - // TODO: use parent() when lombok plugin supports it - .build(); - traceScope = trace.startSpan("traceFilter", span); - } - else { - traceScope = trace.startSpan("traceFilter"); + Span span = MilliSpan.builder() + .traceId(traceId) + .parents(Collections.singletonList(spanId)) + // TODO: use parent() when lombok plugin supports it + .build(); + // Send new span id back + addToResponseIfNotPresent(response, SPAN_ID_NAME, span.getSpanId()); + + traceScope = trace.startSpan("traceFilter", span); + } + else { + traceScope = trace.startSpan("traceFilter"); + } } try { filterChain.doFilter(request, response); } finally { - traceScope.close(); + if (traceScope != null) { + traceScope.close(); + } } } - private String getSpanIdFrom(final HttpServletResponse response) { - return response.getHeader(SPAN_ID_NAME); + private String getHeader(HttpServletRequest request, HttpServletResponse response, + String name) { + String value = request.getHeader(name); + return hasText(value) ? value : response.getHeader(name); } - private String getSpanIdFrom(final HttpServletRequest request) { - return request.getHeader(SPAN_ID_NAME); - } - - private void addCorrelationIdToResponseIfNotPresent(HttpServletResponse response, - String spanId) { - if (!hasText(response.getHeader(SPAN_ID_NAME))) { - response.addHeader(SPAN_ID_NAME, spanId); + private void addToResponseIfNotPresent(HttpServletResponse response, String name, + String value) { + if (!hasText(response.getHeader(name))) { + response.addHeader(name, value); } } From cd74691d6a1757fee027ffdc28c5bf4f382f621d Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 24 Jun 2015 10:22:04 -0600 Subject: [PATCH 14/34] find and update headers using arg type rather than index --- .../cloud/sleuth/web/TraceWebAspect.java | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java index 9397c7849..fe10515e5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java @@ -1,6 +1,7 @@ package org.springframework.cloud.sleuth.web; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; import java.util.ArrayList; import java.util.List; @@ -10,6 +11,7 @@ import lombok.extern.apachecommons.CommonsLog; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Pointcut; +import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; import org.springframework.cloud.sleuth.TraceScope; import org.springframework.http.HttpEntity; @@ -53,8 +55,6 @@ public class TraceWebAspect { this.trace = trace; } - private static final int HTTP_ENTITY_PARAM_INDEX = 2; - @Pointcut("@target(org.springframework.web.bind.annotation.RestController)") private void anyRestControllerAnnotated() { } @@ -83,41 +83,53 @@ public class TraceWebAspect { } @Around("anyExchangeRestOperationsMethod()") - public Object wrapWithCorrelationIdForRestOperations(ProceedingJoinPoint pjp) + public Object traceRestOperations(ProceedingJoinPoint pjp) throws Throwable { TraceScope scope = trace.startSpan(pjp.toShortString()); try { String spanId = scope.getSpan().getSpanId(); - //TODO: set traceId on restTemplate call as well - log.debug("Wrapping RestTemplate call with span id [" + spanId + "]"); - HttpEntity httpEntity = (HttpEntity) pjp.getArgs()[HTTP_ENTITY_PARAM_INDEX]; - HttpEntity newHttpEntity = createNewHttpEntity(httpEntity, spanId); + String traceId = scope.getSpan().getTraceId(); + log.debug("Wrapping RestTemplate call with trace id [" + traceId + "] and span id [" + spanId + "]"); + HttpEntity httpEntity = findHttpEntity(pjp.getArgs()); + HttpEntity newHttpEntity = createNewHttpEntity(httpEntity, spanId, traceId); List newArgs = modifyHttpEntityInMethodArguments(pjp, newHttpEntity); - return pjp.proceed(newArgs.toArray()); + return pjp.proceed(); } finally { scope.close(); } } + protected HttpEntity findHttpEntity(Object[] args) { + for (Object arg : args) { + if (isHttpEntity(arg)) { + return HttpEntity.class.cast(arg); + } + } + return null; + } + + protected boolean isHttpEntity(Object arg) { + return HttpEntity.class.isAssignableFrom(arg.getClass()); + } + @SuppressWarnings("unchecked") - private HttpEntity createNewHttpEntity(HttpEntity httpEntity, String correlationId) { + private HttpEntity createNewHttpEntity(HttpEntity httpEntity, String spanId, String traceId) { HttpHeaders newHttpHeaders = new HttpHeaders(); newHttpHeaders.putAll(httpEntity.getHeaders()); - newHttpHeaders.add(SPAN_ID_NAME, correlationId); + newHttpHeaders.add(SPAN_ID_NAME, spanId); + newHttpHeaders.add(TRACE_ID_NAME, traceId); return new HttpEntity(httpEntity.getBody(), newHttpHeaders); } private List modifyHttpEntityInMethodArguments(ProceedingJoinPoint pjp, HttpEntity newHttpEntity) { List newArgs = new ArrayList<>(); - for (int i = 0; i < pjp.getArgs().length; i++) { - Object arg = pjp.getArgs()[i]; - if (i != HTTP_ENTITY_PARAM_INDEX) { - newArgs.add(i, arg); - } - else { - newArgs.add(i, newHttpEntity); + for (Object arg : pjp.getArgs()) { + if (isHttpEntity(arg)) { + newArgs.add(newHttpEntity); + } else { + newArgs.add(arg); } } return newArgs; From e14128072042517fa2013917828b69e96101206d Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 24 Jun 2015 10:24:15 -0600 Subject: [PATCH 15/34] just set headers rather than creating a new HttpEntity. --- .../cloud/sleuth/web/TraceWebAspect.java | 34 ++++--------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java index fe10515e5..4d7fa44dc 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java @@ -3,9 +3,6 @@ package org.springframework.cloud.sleuth.web; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; -import java.util.ArrayList; -import java.util.List; - import lombok.extern.apachecommons.CommonsLog; import org.aspectj.lang.ProceedingJoinPoint; @@ -21,7 +18,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestOperations; /** - * Aspect that adds correlation id to + * Aspect that adds trace information to *

*

    *
  • {@link RestController} annotated classes
  • @@ -69,6 +66,7 @@ public class TraceWebAspect { @Around("anyControllerOrRestController()") public Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable { + //TODO: get trace data from request? TraceScope scope = trace.startSpan(pjp.toShortString()); try { return pjp.proceed(); @@ -91,8 +89,10 @@ public class TraceWebAspect { String traceId = scope.getSpan().getTraceId(); log.debug("Wrapping RestTemplate call with trace id [" + traceId + "] and span id [" + spanId + "]"); HttpEntity httpEntity = findHttpEntity(pjp.getArgs()); - HttpEntity newHttpEntity = createNewHttpEntity(httpEntity, spanId, traceId); - List newArgs = modifyHttpEntityInMethodArguments(pjp, newHttpEntity); + if (httpEntity != null) { + httpEntity.getHeaders().set(SPAN_ID_NAME, spanId); + httpEntity.getHeaders().set(TRACE_ID_NAME, traceId); + } return pjp.proceed(); } finally { @@ -112,26 +112,4 @@ public class TraceWebAspect { protected boolean isHttpEntity(Object arg) { return HttpEntity.class.isAssignableFrom(arg.getClass()); } - - @SuppressWarnings("unchecked") - private HttpEntity createNewHttpEntity(HttpEntity httpEntity, String spanId, String traceId) { - HttpHeaders newHttpHeaders = new HttpHeaders(); - newHttpHeaders.putAll(httpEntity.getHeaders()); - newHttpHeaders.add(SPAN_ID_NAME, spanId); - newHttpHeaders.add(TRACE_ID_NAME, traceId); - return new HttpEntity(httpEntity.getBody(), newHttpHeaders); - } - - private List modifyHttpEntityInMethodArguments(ProceedingJoinPoint pjp, - HttpEntity newHttpEntity) { - List newArgs = new ArrayList<>(); - for (Object arg : pjp.getArgs()) { - if (isHttpEntity(arg)) { - newArgs.add(newHttpEntity); - } else { - newArgs.add(arg); - } - } - return newArgs; - } } From 05a5709136f757405e6c6d97bb6c0e9cce933d14 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 25 Jun 2015 13:58:28 -0600 Subject: [PATCH 16/34] Updates to get tracing working on sample app. --- .../cloud/sleuth/SpanHolder.java | 4 + .../cloud/sleuth/TraceAutoConfiguration.java | 1 + .../TraceSchedulingAutoConfiguration.java | 3 + .../sleuth/slf4j/Slf4jSpanStartListener.java | 3 +- .../sleuth/web/TraceWebAutoConfiguration.java | 5 + .../client/TraceRestTemplateInterceptor.java | 16 ++-- spring-cloud-sleuth-sample/pom.xml | 4 + .../sleuth/sample/SampleApplication.java | 92 +++++++++++-------- .../src/main/resources/logback.xml | 4 +- 9 files changed, 81 insertions(+), 51 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java index 2735c7700..8efd31be1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java @@ -19,4 +19,8 @@ public class SpanHolder { } currentSpan.set(span); } + + public static boolean isTracing() { + return currentSpan.get() != null; + } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java index 7d7c4cd6b..a46b743b7 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java @@ -20,6 +20,7 @@ public class TraceAutoConfiguration { } @Bean + @ConditionalOnMissingBean public Sampler defaultSampler() { return new IsTracingSampler(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java index f0e31e71c..7c8900ddd 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java @@ -4,6 +4,8 @@ package org.springframework.cloud.sleuth.scheduling; * @author Spencer Gibb */ +import org.aspectj.lang.ProceedingJoinPoint; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.cloud.sleuth.Trace; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,6 +23,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @Configuration @EnableScheduling @EnableAspectJAutoProxy +@ConditionalOnClass(ProceedingJoinPoint.class) public class TraceSchedulingAutoConfiguration { @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java index ebf1c090e..98ab81ace 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java @@ -16,7 +16,8 @@ public class Slf4jSpanStartListener implements SpanStartListener { @Override public void startSpan(Span span) { //TODO: what log level? - log.info("Starting span with id: [{}]", span.getSpanId()); + log.info("Starting span: {}", span); MDC.put(Trace.SPAN_ID_NAME, span.getSpanId()); + MDC.put(Trace.TRACE_ID_NAME, span.getTraceId()); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java index df7719d21..bc815172e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java @@ -17,8 +17,10 @@ package org.springframework.cloud.sleuth.web; import java.util.regex.Pattern; +import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; @@ -26,6 +28,7 @@ import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.cloud.sleuth.Trace; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.util.StringUtils; /** @@ -37,8 +40,10 @@ import org.springframework.util.StringUtils; * @author Spencer Gibb */ @Configuration +@EnableAspectJAutoProxy @ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.enabled", matchIfMissing = true) @ConditionalOnWebApplication +@ConditionalOnClass(ProceedingJoinPoint.class) public class TraceWebAutoConfiguration { /** diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java index 4dc7b9332..ba61ec3cc 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java @@ -42,15 +42,15 @@ public class TraceRestTemplateInterceptor implements ClientHttpRequestIntercepto @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { - if (!request.getHeaders().containsKey(SPAN_ID_NAME)) { - request.getHeaders().add(SPAN_ID_NAME, - SpanHolder.getCurrentSpan().getSpanId()); - } - if (!request.getHeaders().containsKey(TRACE_ID_NAME)) { - request.getHeaders().add(TRACE_ID_NAME, - SpanHolder.getCurrentSpan().getSpanId()); - } + setHeader(request, SPAN_ID_NAME, SpanHolder.getCurrentSpan().getSpanId()); + setHeader(request, TRACE_ID_NAME, SpanHolder.getCurrentSpan().getTraceId()); return execution.execute(request, body); } + public void setHeader(HttpRequest request, String spanIdName, String spanId) { + if (!request.getHeaders().containsKey(spanIdName) && SpanHolder.isTracing()) { + request.getHeaders().add(spanIdName, spanId); + } + } + } diff --git a/spring-cloud-sleuth-sample/pom.xml b/spring-cloud-sleuth-sample/pom.xml index 012281b99..4b6422b47 100644 --- a/spring-cloud-sleuth-sample/pom.xml +++ b/spring-cloud-sleuth-sample/pom.xml @@ -49,6 +49,10 @@ org.springframework.cloud spring-cloud-sleuth-core + + org.springframework.boot + spring-boot-starter-aop + org.projectlombok lombok diff --git a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java index f235a9cdf..90b1f9d88 100644 --- a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java +++ b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java @@ -9,11 +9,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; +import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Trace; import org.springframework.cloud.sleuth.TraceScope; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @@ -23,50 +26,63 @@ import org.springframework.web.client.RestTemplate; */ @Configuration @EnableAutoConfiguration -@RestController +@EnableAspectJAutoProxy @Slf4j -public class SampleApplication implements - ApplicationListener { +public class SampleApplication { public static final String CLIENT_NAME = "testApp"; - @Autowired - private RestTemplate restTemplate; - @Autowired - private Trace trace; - private int port; + @RestController + protected static class SampleController implements + ApplicationListener { + @Autowired + private RestTemplate restTemplate; + @Autowired + private Trace trace; + private int port; - @SneakyThrows - @RequestMapping("/") - public String hi() { - final Random random = new Random(); - Thread.sleep(random.nextInt(1000)); + @SneakyThrows + @RequestMapping("/") + public String hi() { + final Random random = new Random(); + Thread.sleep(random.nextInt(1000)); - String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", - String.class); - return "hi/" + s; + String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", + String.class); + return "hi/" + s; + } + + @SneakyThrows + @RequestMapping("/hi2") + public String hi2() { + final Random random = new Random(); + Thread.sleep(random.nextInt(1000)); + return "hi2"; + } + + @SneakyThrows + @RequestMapping("/traced") + public String traced() { + TraceScope scope = trace.startSpan("customTraceEndpoint", new AlwaysSampler()); + final Random random = new Random(); + int millis = random.nextInt(1000); + log.info("Sleeping for {} millis", millis); + Thread.sleep(millis); + + String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", String.class); + scope.close(); + return "hi/" + s; + } + + @Override + public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { + port = event.getEmbeddedServletContainer().getPort(); + } } - @SneakyThrows - @RequestMapping("/hi2") - public String hi2() { - final Random random = new Random(); - Thread.sleep(random.nextInt(1000)); - return "hi2"; - } - - @SneakyThrows - @RequestMapping("/traced") - public String traced() { - TraceScope scope = trace.startSpan("customTraceEndpoint", new AlwaysSampler()); - final Random random = new Random(); - int millis = random.nextInt(1000); - log.info("Sleeping for {} millis", millis); - Thread.sleep(millis); - - String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", String.class); - scope.close(); - return "hi/"+s; + @Bean + public Sampler defaultSampler() { + return new AlwaysSampler(); } public static void main(String[] args) { @@ -78,8 +94,4 @@ public class SampleApplication implements * } */ - @Override - public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { - port = event.getEmbeddedServletContainer().getPort(); - } } diff --git a/spring-cloud-sleuth-sample/src/main/resources/logback.xml b/spring-cloud-sleuth-sample/src/main/resources/logback.xml index 6ae7c6632..1698a3b29 100644 --- a/spring-cloud-sleuth-sample/src/main/resources/logback.xml +++ b/spring-cloud-sleuth-sample/src/main/resources/logback.xml @@ -3,8 +3,8 @@ - - + + From 07844b769f70754a1d76e8db7b0717f5f312a23d Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 25 Jun 2015 14:13:13 -0600 Subject: [PATCH 17/34] rename SpanHolder to TraceContextHolder --- .../springframework/cloud/sleuth/DefaultTrace.java | 11 +++-------- .../java/org/springframework/cloud/sleuth/Trace.java | 5 ----- .../{SpanHolder.java => TraceContextHolder.java} | 5 +++-- .../org/springframework/cloud/sleuth/TraceScope.java | 8 ++++---- .../cloud/sleuth/sampler/IsTracingSampler.java | 4 ++-- .../web/client/TraceRestTemplateInterceptor.java | 9 +++++---- 6 files changed, 17 insertions(+), 25 deletions(-) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{SpanHolder.java => TraceContextHolder.java} (71%) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java index 603e33bdc..9b5507595 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java @@ -68,7 +68,7 @@ public class DefaultTrace implements Trace { @Override public TraceScope startSpan(String description, Sampler s, T info) { Span span = null; - if (isTracing() || s.next(info)) { + if (TraceContextHolder.isTracing() || s.next(info)) { span = createNew(description); } return doStart(span); @@ -114,12 +114,12 @@ public class DefaultTrace implements Trace { // Return an empty TraceScope that does nothing on close if (span == null) return NullScope.INSTANCE; Span oldSpan = getCurrentSpan(); - SpanHolder.setCurrentSpan(span); + TraceContextHolder.setCurrentSpan(span); return new TraceScope(this, span, oldSpan); } protected Span getCurrentSpan() { - return SpanHolder.getCurrentSpan(); + return TraceContextHolder.getCurrentSpan(); } @Override @@ -130,11 +130,6 @@ public class DefaultTrace implements Trace { } } - @Override - public boolean isTracing() { - return getCurrentSpan() != null; - } - //TODO: rename? this is the end of a Span lifecycle @Override public void deliver(Span span) { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java index ab1601bdf..1a3ae11c4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java @@ -77,10 +77,5 @@ public interface Trace { */ void addKVAnnotation(String key, String value); - /** - * Returns true if the current thread is a part of a trace, false otherwise. - */ - boolean isTracing(); - void deliver(Span span); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceContextHolder.java similarity index 71% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceContextHolder.java index 8efd31be1..f544c1a9d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanHolder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceContextHolder.java @@ -1,13 +1,14 @@ package org.springframework.cloud.sleuth; import lombok.extern.apachecommons.CommonsLog; +import org.springframework.core.NamedThreadLocal; /** * @author Spencer Gibb */ @CommonsLog -public class SpanHolder { - private static final ThreadLocal currentSpan = new ThreadLocal<>(); +public class TraceContextHolder { + private static final ThreadLocal currentSpan = new NamedThreadLocal<>("Trace Context"); public static Span getCurrentSpan() { return currentSpan.get(); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java index a7d36434a..b33b1af4a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java @@ -45,14 +45,14 @@ public class TraceScope implements Closeable { } detached = true; - Span cur = SpanHolder.getCurrentSpan(); + Span cur = TraceContextHolder.getCurrentSpan(); if (cur != span) { Utils.error("Tried to detach trace span " + span + " but " + "it is not the current span for the " + Thread.currentThread().getName() + " thread. You have " + "probably forgotten to close or detach " + cur); } else { - SpanHolder.setCurrentSpan(savedSpan); + TraceContextHolder.setCurrentSpan(savedSpan); } return span; } @@ -64,7 +64,7 @@ public class TraceScope implements Closeable { return; } detached = true; - Span cur = SpanHolder.getCurrentSpan(); + Span cur = TraceContextHolder.getCurrentSpan(); if (cur != span) { Utils.error("Tried to close trace span " + span + " but " + "it is not the current span for the " + @@ -74,7 +74,7 @@ public class TraceScope implements Closeable { span.stop(); //TODO: use ApplicationEvents here? trace.deliver(span); - SpanHolder.setCurrentSpan(savedSpan); + TraceContextHolder.setCurrentSpan(savedSpan); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/IsTracingSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/IsTracingSampler.java index 72eee8cbe..3c8eaaf07 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/IsTracingSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/IsTracingSampler.java @@ -1,7 +1,7 @@ package org.springframework.cloud.sleuth.sampler; import org.springframework.cloud.sleuth.Sampler; -import org.springframework.cloud.sleuth.SpanHolder; +import org.springframework.cloud.sleuth.TraceContextHolder; /** * @author Spencer Gibb @@ -10,6 +10,6 @@ public class IsTracingSampler implements Sampler { @Override public boolean next(Object info) { - return SpanHolder.getCurrentSpan() != null; + return TraceContextHolder.getCurrentSpan() != null; } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java index ba61ec3cc..52eb99d11 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java @@ -17,10 +17,11 @@ package org.springframework.cloud.sleuth.web.client; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; +import static org.springframework.cloud.sleuth.TraceContextHolder.getCurrentSpan; +import static org.springframework.cloud.sleuth.TraceContextHolder.isTracing; import java.io.IOException; -import org.springframework.cloud.sleuth.SpanHolder; import org.springframework.cloud.sleuth.Trace; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; @@ -42,13 +43,13 @@ public class TraceRestTemplateInterceptor implements ClientHttpRequestIntercepto @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { - setHeader(request, SPAN_ID_NAME, SpanHolder.getCurrentSpan().getSpanId()); - setHeader(request, TRACE_ID_NAME, SpanHolder.getCurrentSpan().getTraceId()); + setHeader(request, SPAN_ID_NAME, getCurrentSpan().getSpanId()); + setHeader(request, TRACE_ID_NAME, getCurrentSpan().getTraceId()); return execution.execute(request, body); } public void setHeader(HttpRequest request, String spanIdName, String spanId) { - if (!request.getHeaders().containsKey(spanIdName) && SpanHolder.isTracing()) { + if (!request.getHeaders().containsKey(spanIdName) && isTracing()) { request.getHeaders().add(spanIdName, spanId); } } From 553645f7cfb8bb7d3a544ed325da63222f2ca2bf Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 25 Jun 2015 14:36:16 -0600 Subject: [PATCH 18/34] moved instrumenting classes to instrument package. removed unneeded RestTemplate infrastructure. --- .../circuitbreaker/TraceCommand.java | 2 +- .../scheduling/TraceSchedulingAspect.java | 2 +- .../TraceSchedulingAutoConfiguration.java | 2 +- .../{ => instrument}/web/TraceFilter.java | 2 +- .../{ => instrument}/web/TraceWebAspect.java | 2 +- .../web/TraceWebAutoConfiguration.java | 2 +- .../client/TraceRestTemplateInterceptor.java | 2 +- .../TraceWebClientAutoConfiguration.java | 30 ++++++++- .../DefaultRestTemplateConfigurer.java | 46 -------------- .../resttemplate/RestTemplateConfigurer.java | 30 --------- .../SleuthRestTemplateAutoConfiguration.java | 63 ------------------- .../main/resources/META-INF/spring.factories | 7 +-- 12 files changed, 37 insertions(+), 153 deletions(-) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/circuitbreaker/TraceCommand.java (96%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/scheduling/TraceSchedulingAspect.java (94%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/scheduling/TraceSchedulingAutoConfiguration.java (93%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/web/TraceFilter.java (98%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/web/TraceWebAspect.java (98%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/web/TraceWebAutoConfiguration.java (97%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/web/client/TraceRestTemplateInterceptor.java (97%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/{ => instrument}/web/client/TraceWebClientAutoConfiguration.java (56%) delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/DefaultRestTemplateConfigurer.java delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/RestTemplateConfigurer.java delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/circuitbreaker/TraceCommand.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCommand.java similarity index 96% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/circuitbreaker/TraceCommand.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCommand.java index cc28a9439..6a2ae6507 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/circuitbreaker/TraceCommand.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCommand.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.circuitbreaker; +package org.springframework.cloud.sleuth.instrument.circuitbreaker; import com.netflix.hystrix.HystrixCommand; import com.netflix.hystrix.HystrixCommandGroupKey; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java similarity index 94% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAspect.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java index e4943adc5..588763d1f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.scheduling; +package org.springframework.cloud.sleuth.instrument.scheduling; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java similarity index 93% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java index 7c8900ddd..8444b4793 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/scheduling/TraceSchedulingAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.scheduling; +package org.springframework.cloud.sleuth.instrument.scheduling; /** * @author Spencer Gibb diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java similarity index 98% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java index 1b7d97de3..4429cafbb 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.web; +package org.springframework.cloud.sleuth.instrument.web; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java similarity index 98% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java index 4d7fa44dc..5956e991b 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.sleuth.web; +package org.springframework.cloud.sleuth.instrument.web; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java similarity index 97% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index bc815172e..848554127 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.web; +package org.springframework.cloud.sleuth.instrument.web; import java.util.regex.Pattern; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java similarity index 97% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java index 52eb99d11..334fd8b50 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceRestTemplateInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.sleuth.web.client; +package org.springframework.cloud.sleuth.instrument.web.client; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceWebClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java similarity index 56% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceWebClientAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java index 2fc38fe4d..c45cabd06 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/web/client/TraceWebClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java @@ -1,21 +1,22 @@ -package org.springframework.cloud.sleuth.web.client; +package org.springframework.cloud.sleuth.instrument.web.client; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; +import javax.annotation.PostConstruct; + /** * @author Spencer Gibb */ @Configuration @ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.client.enabled", matchIfMissing = true) @ConditionalOnClass(RestTemplate.class) -@AutoConfigureAfter(SleuthRestTemplateAutoConfiguration.class) public class TraceWebClientAutoConfiguration { @Bean @@ -23,4 +24,27 @@ public class TraceWebClientAutoConfiguration { public TraceRestTemplateInterceptor traceRestTemplateInterceptor() { return new TraceRestTemplateInterceptor(); } + + @Bean + @ConditionalOnMissingBean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + + @Configuration + protected static class TraceInterceptorConfiguration { + + @Autowired(required = false) + private RestTemplate restTemplate; + + @Autowired + private TraceRestTemplateInterceptor traceRestTemplateInterceptor; + + @PostConstruct + public void init() { + if (restTemplate != null) { + restTemplate.getInterceptors().add(traceRestTemplateInterceptor); + } + } + } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/DefaultRestTemplateConfigurer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/DefaultRestTemplateConfigurer.java deleted file mode 100644 index f7e33be80..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/DefaultRestTemplateConfigurer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012-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.resttemplate; - -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.web.client.RestTemplate; - -import java.util.List; - -/** - * Default configure of {@code RestTemplate} that adds a list {@code ClientHttpRequestInterceptor} - * to {@code RestTemplate} - * - * @see ClientHttpRequestInterceptor - * @see RestTemplate - * - * @author Marcin Grzejszczak, 4financeIT - */ -public class DefaultRestTemplateConfigurer implements RestTemplateConfigurer { - - private final List clientHttpRequestInterceptors; - - public DefaultRestTemplateConfigurer(List clientHttpRequestInterceptors) { - this.clientHttpRequestInterceptors = clientHttpRequestInterceptors; - } - - @Override - public void modifyRestTemplate(RestTemplate restTemplate) { - for (ClientHttpRequestInterceptor clientHttpRequestInterceptor : clientHttpRequestInterceptors) { - restTemplate.getInterceptors().add(clientHttpRequestInterceptor); - } - } -} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/RestTemplateConfigurer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/RestTemplateConfigurer.java deleted file mode 100644 index 54b643d40..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/RestTemplateConfigurer.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012-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.resttemplate; - -import org.springframework.web.client.RestTemplate; - -/** - * Interface that allows to modify the {@code RestTemplate} parameters - * - * @see RestTemplate - * - * @author Marcin Grzejszczak, 4financeIT - */ -public interface RestTemplateConfigurer { - - void modifyRestTemplate(RestTemplate restTemplate); -} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java deleted file mode 100644 index 40d1d2e0f..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/resttemplate/SleuthRestTemplateAutoConfiguration.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012-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.resttemplate; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.web.client.RestTemplate; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * Autoconfiguration that sets up a {@code RestTemplate} as a bean if one is not present - * and performs its additional modification via a {@code RestTemplateConfigurer}. - * - * @author Marcin Grzejszczak, 4financeIT - */ -@Configuration -@ConditionalOnWebApplication -@ConditionalOnProperty(value = "spring.cloud.sleuth.resttemplate.enabled", matchIfMissing = true) -public class SleuthRestTemplateAutoConfiguration { - - @Configuration - protected static class RestTemplateConfig { - - @Autowired(required = false) - private List clientHttpRequestInterceptors = new ArrayList<>(); - - @Bean - @ConditionalOnMissingBean - public RestTemplate restTemplate() { - return new RestTemplate(); - } - - @Bean - @ConditionalOnMissingBean - public RestTemplateConfigurer restTemplateConfigurer(RestTemplate restTemplate) { - DefaultRestTemplateConfigurer configurer = new DefaultRestTemplateConfigurer(clientHttpRequestInterceptors); - configurer.modifyRestTemplate(restTemplate); - return configurer; - } - } - -} diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories index f13ffc5a5..d1c8cd4aa 100644 --- a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories @@ -1,7 +1,6 @@ # Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.sleuth.resttemplate.SleuthRestTemplateAutoConfiguration,\ org.springframework.cloud.sleuth.TraceAutoConfiguration,\ -org.springframework.cloud.sleuth.web.TraceWebAutoConfiguration,\ -org.springframework.cloud.sleuth.web.client.TraceWebClientAutoConfiguration,\ -org.springframework.cloud.sleuth.slf4j.SleuthSlf4jAutoConfiguration +org.springframework.cloud.sleuth.slf4j.SleuthSlf4jAutoConfiguration,\ +org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration,\ +org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration From 4cc3e1c9de400c8d45212820a783d608da752caf Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 25 Jun 2015 14:37:24 -0600 Subject: [PATCH 19/34] fixed build --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 96e8782b4..1e06126d4 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,6 @@ spring-cloud-sleuth-core - spring-cloud-sleuth-correlation spring-cloud-sleuth-zipkin spring-cloud-sleuth-sample docs From 7ee4c99fa9551b0995633a7ef30fe3fd75fa77ce Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 25 Jun 2015 15:02:23 -0600 Subject: [PATCH 20/34] move trace intercepting from aop to spring mvc interceptors --- .../web/TraceHandlerInterceptor.java | 45 +++++++ .../sleuth/instrument/web/TraceWebAspect.java | 115 ------------------ .../web/TraceWebAutoConfiguration.java | 28 ++++- .../client/TraceRestTemplateInterceptor.java | 6 +- .../cloud/sleuth/slf4j/Slf4jSpanReceiver.java | 4 +- 5 files changed, 74 insertions(+), 124 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java new file mode 100644 index 000000000..8d8b8a4f1 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java @@ -0,0 +1,45 @@ +package org.springframework.cloud.sleuth.instrument.web; + +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @author Spencer Gibb + */ +public class TraceHandlerInterceptor implements HandlerInterceptor { + + private static final String ATTR_NAME = "__CURRENT_TRACE_HANDLER_TRACE_SCOPE_ATTR___"; + + private final Trace trace; + + public TraceHandlerInterceptor(Trace trace) { + this.trace = trace; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + //TODO: get trace data from request? + //TODO: what is the description? + TraceScope scope = trace.startSpan(""); + request.setAttribute(ATTR_NAME, scope); + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + TraceScope scope = TraceScope.class.cast(request.getAttribute(ATTR_NAME)); + if (scope != null) { + scope.close(); + } + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java deleted file mode 100644 index 5956e991b..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.springframework.cloud.sleuth.instrument.web; - -import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; -import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; - -import lombok.extern.apachecommons.CommonsLog; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Pointcut; -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.Trace; -import org.springframework.cloud.sleuth.TraceScope; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.RestOperations; - -/** - * Aspect that adds trace information to - *

    - *

      - *
    • {@link RestController} annotated classes
    • - *
    • {@link Controller} annotated classes
    • - *
    • explicit {@link RestOperations}.exchange(..) method calls
    • - *
    - *

    - * For controllers an around aspect is created that create a {@link Span} for each call. - *

    - * For {@link RestOperations} we are wrapping all executions of the exchange - * methods and we are extracting {@link HttpHeaders} from the passed {@link HttpEntity}. - * Next we are adding span id header * {@link Trace#SPAN_ID_NAME} with the value taken - * from the current Span. Finally the method execution proceeds. - * - * @see RestController - * @see Controller - * @see RestOperations - * @see Trace - * - * @author Tomasz Nurkewicz, 4financeIT - * @author Marcin Grzejszczak, 4financeIT - * @author Michal Chmielarz, 4financeIT - * @author Spencer Gibb - */ -@CommonsLog -public class TraceWebAspect { - - private final Trace trace; - - public TraceWebAspect(Trace trace) { - this.trace = trace; - } - - @Pointcut("@target(org.springframework.web.bind.annotation.RestController)") - private void anyRestControllerAnnotated() { - } - - @Pointcut("@target(org.springframework.stereotype.Controller)") - private void anyControllerAnnotated() { - } - - @Pointcut("anyRestControllerAnnotated() || anyControllerAnnotated()") - private void anyControllerOrRestController() { - } - - @Around("anyControllerOrRestController()") - public Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable { - //TODO: get trace data from request? - TraceScope scope = trace.startSpan(pjp.toShortString()); - try { - return pjp.proceed(); - } - finally { - scope.close(); - } - } - - @Pointcut("execution(public * org.springframework.web.client.RestOperations.exchange(..))") - private void anyExchangeRestOperationsMethod() { - } - - @Around("anyExchangeRestOperationsMethod()") - public Object traceRestOperations(ProceedingJoinPoint pjp) - throws Throwable { - TraceScope scope = trace.startSpan(pjp.toShortString()); - try { - String spanId = scope.getSpan().getSpanId(); - String traceId = scope.getSpan().getTraceId(); - log.debug("Wrapping RestTemplate call with trace id [" + traceId + "] and span id [" + spanId + "]"); - HttpEntity httpEntity = findHttpEntity(pjp.getArgs()); - if (httpEntity != null) { - httpEntity.getHeaders().set(SPAN_ID_NAME, spanId); - httpEntity.getHeaders().set(TRACE_ID_NAME, traceId); - } - return pjp.proceed(); - } - finally { - scope.close(); - } - } - - protected HttpEntity findHttpEntity(Object[] args) { - for (Object arg : args) { - if (isHttpEntity(arg)) { - return HttpEntity.class.cast(arg); - } - } - return null; - } - - protected boolean isHttpEntity(Object arg) { - return HttpEntity.class.isAssignableFrom(arg.getClass()); - } -} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 848554127..710c56493 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -17,10 +17,8 @@ package org.springframework.cloud.sleuth.instrument.web; import java.util.regex.Pattern; -import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; @@ -30,6 +28,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.util.StringUtils; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Registers beans that add tracing to requests @@ -43,7 +43,6 @@ import org.springframework.util.StringUtils; @EnableAspectJAutoProxy @ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.enabled", matchIfMissing = true) @ConditionalOnWebApplication -@ConditionalOnClass(ProceedingJoinPoint.class) public class TraceWebAutoConfiguration { /** @@ -57,8 +56,14 @@ public class TraceWebAutoConfiguration { @Bean @ConditionalOnMissingBean - public TraceWebAspect traceWebAspect() { - return new TraceWebAspect(trace); + public TraceHandlerInterceptor traceHandlerInterceptor() { + return new TraceHandlerInterceptor(trace); + } + + @Bean + public WebMvcConfigurerAdapter webMvcConfigurerAdapter( + TraceHandlerInterceptor handlerInterceptor) { + return new TraceWebConfigurer(handlerInterceptor); } @Bean @@ -68,4 +73,17 @@ public class TraceWebAutoConfiguration { : TraceFilter.DEFAULT_SKIP_PATTERN; return new FilterRegistrationBean(new TraceFilter(trace, pattern)); } + + protected static class TraceWebConfigurer extends WebMvcConfigurerAdapter { + private TraceHandlerInterceptor interceptor; + + public TraceWebConfigurer(TraceHandlerInterceptor interceptor) { + this.interceptor = interceptor; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(interceptor).addPathPatterns("/**"); + } + } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java index 334fd8b50..3be3db292 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java @@ -48,9 +48,9 @@ public class TraceRestTemplateInterceptor implements ClientHttpRequestIntercepto return execution.execute(request, body); } - public void setHeader(HttpRequest request, String spanIdName, String spanId) { - if (!request.getHeaders().containsKey(spanIdName) && isTracing()) { - request.getHeaders().add(spanIdName, spanId); + public void setHeader(HttpRequest request, String name, String value) { + if (!request.getHeaders().containsKey(name) && isTracing()) { + request.getHeaders().add(name, value); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java index d46ef23b1..078c24889 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java @@ -1,6 +1,7 @@ package org.springframework.cloud.sleuth.slf4j; import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; @@ -18,8 +19,9 @@ public class Slf4jSpanReceiver implements SpanReceiver { @Override public void receiveSpan(Span span) { //TODO: what should this log level be? - log.info("Received span {}", span); + log.info("Received span: {}", span); MDC.remove(SPAN_ID_NAME); + MDC.remove(TRACE_ID_NAME); } @PostConstruct From 0425bf333a7a6fc1ab959332696bec9110bdc185 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 25 Jun 2015 15:02:49 -0600 Subject: [PATCH 21/34] removed unneeded aop annotation --- .../cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 710c56493..140159a6f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -26,7 +26,6 @@ import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.cloud.sleuth.Trace; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.util.StringUtils; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @@ -40,7 +39,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter * @author Spencer Gibb */ @Configuration -@EnableAspectJAutoProxy @ConditionalOnProperty(value = "spring.cloud.sleuth.trace.web.enabled", matchIfMissing = true) @ConditionalOnWebApplication public class TraceWebAutoConfiguration { From 2fdae442627d9b78bf55723f327277b529588c77 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 25 Jun 2015 15:03:29 -0600 Subject: [PATCH 22/34] rename property --- .../cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 140159a6f..8a6146b0d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -46,7 +46,7 @@ public class TraceWebAutoConfiguration { /** * Pattern for URLs that should be skipped in correlationID setting */ - @Value("${spring.cloud.sleuth.trace.web.skipPattern:}") + @Value("${spring.cloud.sleuth.instrument.web.skipPattern:}") private String skipPattern; @Autowired From 9829ff99033a869dcaede89e3fa30f45e0efd1e4 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 12:37:05 -0600 Subject: [PATCH 23/34] Move to event driven interceptors. use Span{Started|Stopped}Event rather than SpanStartListener/SpanReceiver --- .../sleuth/ArrayListSpanAccumulator.java | 21 ++++++++ .../cloud/sleuth/DefaultTrace.java | 27 +++------- .../cloud/sleuth/SpanReceiver.java | 13 ----- .../cloud/sleuth/SpanStartListener.java | 9 ---- .../springframework/cloud/sleuth/Trace.java | 2 - .../cloud/sleuth/TraceAutoConfiguration.java | 8 +-- .../cloud/sleuth/TraceScope.java | 11 ++-- .../cloud/sleuth/event/SpanStartedEvent.java | 19 +++++++ .../cloud/sleuth/event/SpanStoppedEvent.java | 19 +++++++ .../receiver/ArrayListSpanReceiver.java | 29 ----------- .../slf4j/SleuthSlf4jAutoConfiguration.java | 8 +-- ...ner.java => Slf4jSpanStartedListener.java} | 8 +-- ...ver.java => Slf4jSpanStoppedListener.java} | 19 +++---- .../cloud/sleuth/DefaultTraceTests.java | 52 +++++++++---------- 14 files changed, 117 insertions(+), 128 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/ArrayListSpanAccumulator.java delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReceiver.java delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanStartListener.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStartedEvent.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStoppedEvent.java delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/receiver/ArrayListSpanReceiver.java rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/{Slf4jSpanStartListener.java => Slf4jSpanStartedListener.java} (58%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/{Slf4jSpanReceiver.java => Slf4jSpanStoppedListener.java} (51%) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/ArrayListSpanAccumulator.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/ArrayListSpanAccumulator.java new file mode 100644 index 000000000..543ac1d04 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/ArrayListSpanAccumulator.java @@ -0,0 +1,21 @@ +package org.springframework.cloud.sleuth; + +import java.util.ArrayList; + +import lombok.Value; + +import org.springframework.cloud.sleuth.event.SpanStoppedEvent; +import org.springframework.context.ApplicationListener; + +/** + * @author Spencer Gibb + */ +@Value +public class ArrayListSpanAccumulator implements ApplicationListener { + private final ArrayList spans = new ArrayList<>(); + + @Override + public void onApplicationEvent(SpanStoppedEvent event) { + spans.add(event.getSpan()); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java index 9b5507595..1da2c7d5b 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java @@ -2,9 +2,11 @@ package org.springframework.cloud.sleuth; import static org.springframework.cloud.sleuth.Utils.error; -import java.util.Collection; import java.util.Collections; +import org.springframework.cloud.sleuth.event.SpanStartedEvent; +import org.springframework.context.ApplicationEventPublisher; + /** * @author Spencer Gibb */ @@ -14,16 +16,13 @@ public class DefaultTrace implements Trace { private final IdGenerator idGenerator; - private final Collection spanStartListeners; - private final Collection spanReceivers; + private final ApplicationEventPublisher publisher; public DefaultTrace(Sampler defaultSampler, IdGenerator idGenerator, - Collection spanStartListeners, - Collection spanReceivers) { + ApplicationEventPublisher publisher) { this.defaultSampler = defaultSampler; this.idGenerator = idGenerator; - this.spanStartListeners = spanStartListeners; - this.spanReceivers = spanReceivers; + this.publisher = publisher; } @Override @@ -102,9 +101,7 @@ public class DefaultTrace implements Trace { protected TraceScope doStart(Span span) { if (span != null) { - for (SpanStartListener listener : spanStartListeners) { - listener.startSpan(span); - } + publisher.publishEvent(new SpanStartedEvent(this, span)); } return continueSpan(span); } @@ -115,7 +112,7 @@ public class DefaultTrace implements Trace { if (span == null) return NullScope.INSTANCE; Span oldSpan = getCurrentSpan(); TraceContextHolder.setCurrentSpan(span); - return new TraceScope(this, span, oldSpan); + return new TraceScope(this.publisher, span, oldSpan); } protected Span getCurrentSpan() { @@ -129,12 +126,4 @@ public class DefaultTrace implements Trace { s.addKVAnnotation(key, value); } } - - //TODO: rename? this is the end of a Span lifecycle - @Override - public void deliver(Span span) { - for (SpanReceiver receiver : spanReceivers) { - receiver.receiveSpan(span); - } - } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReceiver.java deleted file mode 100644 index 9d0d54702..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReceiver.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.springframework.cloud.sleuth; - -import java.io.Closeable; - -/** - * The collector within a process that is the destination of Spans when a trace is running. - */ -public interface SpanReceiver extends Closeable { - /** - * Called when a Span is stopped and can now be stored. - */ - public void receiveSpan(Span span); -} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanStartListener.java deleted file mode 100644 index 2958cbe1c..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanStartListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.springframework.cloud.sleuth; - -/** - * @author Spencer Gibb - */ -//TODO: rename? -public interface SpanStartListener { - void startSpan(Span span); -} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java index 1a3ae11c4..35e5e8039 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java @@ -76,6 +76,4 @@ public interface Trace { * Adds a data annotation to the current span if tracing is currently on. */ void addKVAnnotation(String key, String value); - - void deliver(Span span); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java index a46b743b7..84ff1e3b6 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceAutoConfiguration.java @@ -2,11 +2,10 @@ package org.springframework.cloud.sleuth; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.sleuth.sampler.IsTracingSampler; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Collection; - /** * @author Spencer Gibb */ @@ -27,7 +26,8 @@ public class TraceAutoConfiguration { @Bean @ConditionalOnMissingBean - public Trace trace(Sampler sampler, IdGenerator idGenerator, Collection listeners, Collection receivers) { - return new DefaultTrace(sampler, idGenerator, listeners, receivers); + public Trace trace(Sampler sampler, IdGenerator idGenerator, + ApplicationEventPublisher publisher) { + return new DefaultTrace(sampler, idGenerator, publisher); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java index b33b1af4a..6ff9fc130 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java @@ -4,6 +4,8 @@ import java.io.Closeable; import lombok.Data; import lombok.SneakyThrows; +import org.springframework.cloud.sleuth.event.SpanStoppedEvent; +import org.springframework.context.ApplicationEventPublisher; /** * @author Spencer Gibb @@ -11,7 +13,7 @@ import lombok.SneakyThrows; @Data public class TraceScope implements Closeable { - private final Trace trace; + private final ApplicationEventPublisher publisher; /** * the span for this scope @@ -25,8 +27,8 @@ public class TraceScope implements Closeable { private boolean detached = false; - public TraceScope(Trace trace, Span span, Span savedSpan) { - this.trace = trace; + public TraceScope(ApplicationEventPublisher publisher, Span span, Span savedSpan) { + this.publisher = publisher; this.span = span; this.savedSpan = savedSpan; } @@ -72,8 +74,7 @@ public class TraceScope implements Closeable { "probably forgotten to close or detach " + cur); } else { span.stop(); - //TODO: use ApplicationEvents here? - trace.deliver(span); + this.publisher.publishEvent(new SpanStoppedEvent(this, span)); TraceContextHolder.setCurrentSpan(savedSpan); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStartedEvent.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStartedEvent.java new file mode 100644 index 000000000..49e5a7cdb --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStartedEvent.java @@ -0,0 +1,19 @@ +package org.springframework.cloud.sleuth.event; + +import lombok.Value; +import org.springframework.cloud.sleuth.Span; +import org.springframework.context.ApplicationEvent; + +/** + * @author Spencer Gibb + */ +@Value +public class SpanStartedEvent extends ApplicationEvent { + + private final Span span; + + public SpanStartedEvent(Object source, Span span) { + super(source); + this.span = span; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStoppedEvent.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStoppedEvent.java new file mode 100644 index 000000000..5272bfc92 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/event/SpanStoppedEvent.java @@ -0,0 +1,19 @@ +package org.springframework.cloud.sleuth.event; + +import lombok.Value; +import org.springframework.cloud.sleuth.Span; +import org.springframework.context.ApplicationEvent; + +/** + * @author Spencer Gibb + */ +@Value +public class SpanStoppedEvent extends ApplicationEvent { + + private final Span span; + + public SpanStoppedEvent(Object source, Span span) { + super(source); + this.span = span; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/receiver/ArrayListSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/receiver/ArrayListSpanReceiver.java deleted file mode 100644 index 167ab3ee9..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/receiver/ArrayListSpanReceiver.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.springframework.cloud.sleuth.receiver; - -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.SpanReceiver; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Spencer Gibb - */ -public class ArrayListSpanReceiver implements SpanReceiver { - private final ArrayList spans = new ArrayList<>(); - - @Override - public void receiveSpan(Span span) { - spans.add(span); - } - - public List getSpans() { - return spans; - } - - @Override - public void close() throws IOException { - - } -} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java index ea0781be7..f17d0cba9 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/SleuthSlf4jAutoConfiguration.java @@ -13,12 +13,12 @@ import org.springframework.context.annotation.Configuration; public class SleuthSlf4jAutoConfiguration { @Bean - public Slf4jSpanStartListener slf4jSpanStartListener() { - return new Slf4jSpanStartListener(); + public Slf4jSpanStartedListener slf4jSpanStartedListener() { + return new Slf4jSpanStartedListener(); } @Bean - public Slf4jSpanReceiver slf4jSpanReceiver() { - return new Slf4jSpanReceiver(); + public Slf4jSpanStoppedListener slf4jSpanStoppedListener() { + return new Slf4jSpanStoppedListener(); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartedListener.java similarity index 58% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartedListener.java index 98ab81ace..6653a4115 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStartedListener.java @@ -4,17 +4,19 @@ import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.SpanStartListener; import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.event.SpanStartedEvent; +import org.springframework.context.ApplicationListener; /** * @author Spencer Gibb */ @Slf4j -public class Slf4jSpanStartListener implements SpanStartListener { +public class Slf4jSpanStartedListener implements ApplicationListener { @Override - public void startSpan(Span span) { + public void onApplicationEvent(SpanStartedEvent event) { + Span span = event.getSpan(); //TODO: what log level? log.info("Starting span: {}", span); MDC.put(Trace.SPAN_ID_NAME, span.getSpanId()); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStoppedListener.java similarity index 51% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStoppedListener.java index 078c24889..b5b12d053 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanReceiver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/slf4j/Slf4jSpanStoppedListener.java @@ -4,28 +4,21 @@ import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; import lombok.extern.slf4j.Slf4j; -import org.slf4j.MDC; -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.SpanReceiver; -import javax.annotation.PostConstruct; -import java.io.IOException; +import org.slf4j.MDC; +import org.springframework.cloud.sleuth.event.SpanStoppedEvent; +import org.springframework.context.ApplicationListener; /** * @author Spencer Gibb */ @Slf4j -public class Slf4jSpanReceiver implements SpanReceiver { +public class Slf4jSpanStoppedListener implements ApplicationListener { @Override - public void receiveSpan(Span span) { + public void onApplicationEvent(SpanStoppedEvent event) { //TODO: what should this log level be? - log.info("Received span: {}", span); + log.info("Received span: {}", event.getSpan()); MDC.remove(SPAN_ID_NAME); MDC.remove(TRACE_ID_NAME); } - - @PostConstruct - @Override - public void close() throws IOException { - } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java index a85f21995..199215f39 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java @@ -1,19 +1,24 @@ package org.springframework.cloud.sleuth; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import lombok.Data; - import org.junit.Test; -import org.springframework.cloud.sleuth.receiver.ArrayListSpanReceiver; +import org.mockito.ArgumentCaptor; +import org.springframework.cloud.sleuth.event.SpanStartedEvent; +import org.springframework.cloud.sleuth.event.SpanStoppedEvent; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.sampler.IsTracingSampler; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationEventPublisher; /** * @author Spencer Gibb @@ -27,15 +32,10 @@ public class DefaultTraceTests { @Test public void tracingWorks() { - ArrayListSpanReceiver spanReceiver = new ArrayListSpanReceiver(); - ListSpanStartListener listener = new ListSpanStartListener(); - List startListeners = Collections - . singletonList(listener); - List spanReceivers = Collections - . singletonList(spanReceiver); + ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class); DefaultTrace trace = new DefaultTrace(new IsTracingSampler(), - new RandomUuidGenerator(), startListeners, spanReceivers); + new RandomUuidGenerator(), publisher); TraceScope scope = trace.startSpan(CREATE_SIMPLE_TRACE, new AlwaysSampler()); try { @@ -45,12 +45,20 @@ public class DefaultTraceTests { scope.close(); } - List startedSpans = listener.getSpans(); - assertThat("startedSpans was null", startedSpans, is(notNullValue())); - assertThat("startedSpans was wrong size", startedSpans.size(), is(NUM_SPANS)); + verify(publisher, times(NUM_SPANS)).publishEvent(isA(SpanStartedEvent.class)); + verify(publisher, times(NUM_SPANS)).publishEvent(isA(SpanStoppedEvent.class)); + + ArgumentCaptor captor = ArgumentCaptor + .forClass(ApplicationEvent.class); + verify(publisher, atLeast(NUM_SPANS)).publishEvent(captor.capture()); + + List spans = new ArrayList<>(); + for (ApplicationEvent event : captor.getAllValues()) { + if (event instanceof SpanStoppedEvent) { + spans.add(((SpanStoppedEvent) event).getSpan()); + } + } - List spans = spanReceiver.getSpans(); - assertThat("spans was null", spans, is(notNullValue())); assertThat("spans was wrong size", spans.size(), is(NUM_SPANS)); Span root = assertSpan(spans, null, CREATE_SIMPLE_TRACE); @@ -109,14 +117,4 @@ public class DefaultTraceTests { cur.close(); } } - - @Data - class ListSpanStartListener implements SpanStartListener { - private ArrayList spans = new ArrayList<>(); - - @Override - public void startSpan(Span span) { - spans.add(span); - } - } } From 6e7e090a1ccc5d33a15a8ce3a028bcccfff3b5c6 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 12:58:27 -0600 Subject: [PATCH 24/34] Add zuul instrumentation --- pom.xml | 6 +- spring-cloud-sleuth-core/pom.xml | 5 ++ .../sleuth/instrument/web/TraceFilter.java | 1 + .../instrument/zuul/TracePostFilter.java | 46 ++++++++++++ .../instrument/zuul/TracePreFilter.java | 72 +++++++++++++++++++ .../zuul/TraceZuulAutoConfiguration.java | 28 ++++++++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostFilter.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java diff --git a/pom.xml b/pom.xml index 1e06126d4..a9823192e 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,6 @@ spring-cloud-sleuth-core - spring-cloud-sleuth-zipkin spring-cloud-sleuth-sample docs @@ -155,6 +154,11 @@ hystrix-core 1.4.5 + + com.netflix.zuul + zuul-core + 1.0.28 + org.aspectj aspectjrt diff --git a/spring-cloud-sleuth-core/pom.xml b/spring-cloud-sleuth-core/pom.xml index bcbab14b3..e1ca6b9d9 100644 --- a/spring-cloud-sleuth-core/pom.xml +++ b/spring-cloud-sleuth-core/pom.xml @@ -47,6 +47,11 @@ hystrix-core true + + com.netflix.zuul + zuul-core + true + io.reactivex rxjava diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java index 4429cafbb..d757d1f82 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java @@ -86,6 +86,7 @@ public class TraceFilter extends OncePerRequestFilter { // Send new span id back addToResponseIfNotPresent(response, SPAN_ID_NAME, span.getSpanId()); + //TODO: trace description? traceScope = trace.startSpan("traceFilter", span); } else { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostFilter.java new file mode 100644 index 000000000..910dbadb3 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostFilter.java @@ -0,0 +1,46 @@ +package org.springframework.cloud.sleuth.instrument.zuul; + +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; + +/** + * @author Spencer Gibb + */ +public class TracePostFilter extends ZuulFilter { + + private Trace trace; + + public TracePostFilter(Trace trace) { + this.trace = trace; + } + + @Override + public String filterType() { + return "post"; + } + + @Override + public int filterOrder() { + return 0; + } + + @Override + public boolean shouldFilter() { + return true; + } + + @Override + public Object run() { + TraceScope traceScope = (TraceScope) RequestContext.getCurrentContext().get( + "traceScope"); + + if (traceScope != null) { + traceScope.close(); + } + + return null; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java new file mode 100644 index 000000000..6d7e0e3a6 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java @@ -0,0 +1,72 @@ +package org.springframework.cloud.sleuth.instrument.zuul; + +import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; +import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; +import static org.springframework.util.StringUtils.hasText; + +import java.util.Collections; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.cloud.sleuth.MilliSpan; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; + +/** + * @author Spencer Gibb + */ +public class TracePreFilter extends ZuulFilter { + + private Trace trace; + + public TracePreFilter(Trace trace) { + this.trace = trace; + } + + @Override + public String filterType() { + return "pre"; + } + + @Override + public int filterOrder() { + return 0; + } + + @Override + public boolean shouldFilter() { + return true; + } + + @Override + public Object run() { + RequestContext context = RequestContext.getCurrentContext(); + HttpServletRequest request = context.getRequest(); + + String spanId = request.getHeader(SPAN_ID_NAME); + String traceId = request.getHeader(TRACE_ID_NAME); + TraceScope traceScope = null; + if (hasText(spanId) && hasText(traceId)) { + + Span span = MilliSpan.builder().traceId(traceId) + .parents(Collections.singletonList(spanId)) + // TODO: use parent() when lombok plugin supports it + .build(); + + // TODO: trace description? + traceScope = trace.startSpan("traceZuulFilter", span); + } + else { + traceScope = trace.startSpan("traceZuulFilter"); + + } + + context.set("traceScope", traceScope); + + return null; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java new file mode 100644 index 000000000..18d542435 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java @@ -0,0 +1,28 @@ +package org.springframework.cloud.sleuth.instrument.zuul; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.netflix.zuul.ZuulFilter; + +/** + * @author Spencer Gibb + */ +@Configuration +@ConditionalOnClass(ZuulFilter.class) +@ConditionalOnBean(Trace.class) +public class TraceZuulAutoConfiguration { + + @Bean + public TracePreFilter tracePreFilter(Trace trace) { + return new TracePreFilter(trace); + } + + @Bean + public TracePostFilter tracePostFilter(Trace trace) { + return new TracePostFilter(trace); + } +} From fa5996e38e2fde2a72973432231f4ffbfead9d76 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 13:21:04 -0600 Subject: [PATCH 25/34] change span.description to span.name --- .../cloud/sleuth/DefaultTrace.java | 32 +++++++++---------- .../cloud/sleuth/MilliSpan.java | 4 +-- .../springframework/cloud/sleuth/Span.java | 4 +-- .../springframework/cloud/sleuth/Trace.java | 16 +++++----- .../cloud/sleuth/DefaultTraceTests.java | 6 ++-- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java index 1da2c7d5b..af067bb4e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java @@ -26,16 +26,16 @@ public class DefaultTrace implements Trace { } @Override - public TraceScope startSpan(String description) { - return this.startSpan(description, defaultSampler); + public TraceScope startSpan(String name) { + return this.startSpan(name, defaultSampler); } @Override - public TraceScope startSpan(String description, TraceInfo tinfo) { + public TraceScope startSpan(String name, TraceInfo tinfo) { if (tinfo == null) return doStart(null); MilliSpan span = MilliSpan.builder() .begin(System.currentTimeMillis()) - .description(description) + .name(name) .traceId(tinfo.getTraceId()) .spanId(idGenerator.create()) .parents(Collections.singletonList(tinfo.getSpanId())) @@ -45,9 +45,9 @@ public class DefaultTrace implements Trace { } @Override - public TraceScope startSpan(String description, Span parent) { + public TraceScope startSpan(String name, Span parent) { if (parent == null) { - return startSpan(description); + return startSpan(name); } Span currentSpan = getCurrentSpan(); if ((currentSpan != null) && (currentSpan != parent)) { @@ -56,41 +56,41 @@ public class DefaultTrace implements Trace { "with parent " + parent.toString() + ", but there is already a " + "currentSpan " + currentSpan); } - return doStart(createChild(parent, description)); + return doStart(createChild(parent, name)); } @Override - public TraceScope startSpan(String description, Sampler s) { - return startSpan(description, s, null); + public TraceScope startSpan(String name, Sampler s) { + return startSpan(name, s, null); } @Override - public TraceScope startSpan(String description, Sampler s, T info) { + public TraceScope startSpan(String name, Sampler s, T info) { Span span = null; if (TraceContextHolder.isTracing() || s.next(info)) { - span = createNew(description); + span = createNew(name); } return doStart(span); } - protected Span createNew(String description) { + protected Span createNew(String name) { Span parent = getCurrentSpan(); if (parent == null) { return MilliSpan.builder() .begin(System.currentTimeMillis()) - .description(description) + .name(name) .traceId(idGenerator.create()) .spanId(idGenerator.create()) .build(); } else { - return createChild(parent, description); + return createChild(parent, name); } } - protected Span createChild(Span parent, String childDescription) { + protected Span createChild(Span parent, String childname) { return MilliSpan.builder(). begin(System.currentTimeMillis()). - description(childDescription). + name(childname). traceId(parent.getTraceId()). parents(Collections.singletonList(parent.getSpanId())). //TODO: when lombok plugin supports @Singular parent(parent.getSpanId()). diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java index 50404f6cc..450068fcc 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java @@ -17,7 +17,7 @@ public class MilliSpan implements Span { private long begin; @NonFinal private long end = 0; - private String description; + private String name; private String traceId; @Singular private List parents; @@ -31,7 +31,7 @@ public class MilliSpan implements Span { public synchronized void stop() { if (end == 0) { if (begin == 0) - throw new IllegalStateException("Span for " + description + throw new IllegalStateException("Span for " + name + " has not been started"); end = System.currentTimeMillis(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java index a880e5b8a..14117f572 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java @@ -39,11 +39,11 @@ public interface Span { boolean isRunning(); /** - * Return a textual description of this span.

    + * Return a textual name of this span.

    *

    * Will never be null. */ - String getDescription(); + String getName(); /** * A pseudo-unique (random) number assigned to this span instance.

    diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java index 35e5e8039..f86e489e7 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java @@ -5,7 +5,7 @@ package org.springframework.cloud.sleuth; * methods to create and manipulate spans. * * A 'Span' represents a length of time. It has many other attributes such as a - * description, ID, and even potentially a set of key/value strings attached to + * name, ID, and even potentially a set of key/value strings attached to * it. * * Each thread in your application has a single currently active currentSpan @@ -46,11 +46,11 @@ public interface Trace { * If there is no currently active trace span, the trace scope we create will * be empty. * - * @param description The description field for the new span to create. + * @param name The name field for the new span to create. */ - TraceScope startSpan(String description); + TraceScope startSpan(String name); - TraceScope startSpan(String description, TraceInfo tinfo); + TraceScope startSpan(String name, TraceInfo tinfo); /** * Creates a new trace scope. @@ -59,13 +59,13 @@ public interface Trace { * span that you pass in here as a parameter. The trace scope we create here * will contain a new span which is a child of 'parent'. * - * @param description The description field for the new span to create. + * @param name The name field for the new span to create. */ - TraceScope startSpan(String description, Span parent); + TraceScope startSpan(String name, Span parent); - TraceScope startSpan(String description, Sampler s); + TraceScope startSpan(String name, Sampler s); - TraceScope startSpan(String description, Sampler s, T info); + TraceScope startSpan(String name, Sampler s, T info); /** * Pick up an existing span from another thread. diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java index 199215f39..bd287981d 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceTests.java @@ -69,12 +69,12 @@ public class DefaultTraceTests { assertThat("gen4 was non-empty", gen4.isEmpty(), is(true)); } - private Span assertSpan(List spans, String parentId, String desc) { + private Span assertSpan(List spans, String parentId, String name) { List found = findSpans(spans, parentId); assertThat("more than one span with parentId " + parentId, found.size(), is(1)); Span span = found.get(0); - assertThat("description is wrong for span with parentId " + parentId, - span.getDescription(), is(desc)); + assertThat("name is wrong for span with parentId " + parentId, + span.getName(), is(name)); return span; } From 4320bbc6632bd37aff2030a0a71003a344b2c2db Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 13:30:59 -0600 Subject: [PATCH 26/34] removed setters --- .../java/org/springframework/cloud/sleuth/TraceScope.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java index 6ff9fc130..695f913b0 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TraceScope.java @@ -2,15 +2,18 @@ package org.springframework.cloud.sleuth; import java.io.Closeable; -import lombok.Data; import lombok.SneakyThrows; +import lombok.Value; +import lombok.experimental.NonFinal; + import org.springframework.cloud.sleuth.event.SpanStoppedEvent; import org.springframework.context.ApplicationEventPublisher; /** * @author Spencer Gibb */ -@Data +@Value +@NonFinal public class TraceScope implements Closeable { private final ApplicationEventPublisher publisher; @@ -25,6 +28,7 @@ public class TraceScope implements Closeable { */ private final Span savedSpan; + @NonFinal private boolean detached = false; public TraceScope(ApplicationEventPublisher publisher, Span span, Span savedSpan) { From a4e92c2c38b592913f13228d69b3bb09b9e7eee9 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 13:48:13 -0600 Subject: [PATCH 27/34] remove unneeded qualifier --- .../src/main/java/org/springframework/cloud/sleuth/Sampler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Sampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Sampler.java index 4e00125ce..336aa6896 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Sampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Sampler.java @@ -29,5 +29,5 @@ package org.springframework.cloud.sleuth; * This would trace 50% of all gets, 75% of all puts and would not trace any other requests. */ public interface Sampler { - public boolean next(T info); + boolean next(T info); } From 17f27a4cceb5923aa97473e10f60a52a786755fb Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 13:48:30 -0600 Subject: [PATCH 28/34] use TraceInfo instead of creating a bogus parent span --- .../sleuth/instrument/web/TraceFilter.java | 18 ++++++------------ .../sleuth/instrument/zuul/TracePreFilter.java | 13 +++---------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java index d757d1f82..b6dee3321 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java @@ -20,7 +20,6 @@ import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; import static org.springframework.util.StringUtils.hasText; import java.io.IOException; -import java.util.Collections; import java.util.regex.Pattern; import javax.servlet.FilterChain; @@ -28,9 +27,8 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.cloud.sleuth.MilliSpan; -import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceInfo; import org.springframework.cloud.sleuth.TraceScope; import org.springframework.web.filter.OncePerRequestFilter; @@ -78,16 +76,12 @@ public class TraceFilter extends OncePerRequestFilter { String traceId = getHeader(request, response, TRACE_ID_NAME); if (hasText(spanId) && hasText(traceId)) { - Span span = MilliSpan.builder() - .traceId(traceId) - .parents(Collections.singletonList(spanId)) - // TODO: use parent() when lombok plugin supports it - .build(); + TraceInfo traceInfo = new TraceInfo(traceId, spanId); + // TODO: trace description? + traceScope = trace.startSpan("traceFilter", traceInfo); // Send new span id back - addToResponseIfNotPresent(response, SPAN_ID_NAME, span.getSpanId()); - - //TODO: trace description? - traceScope = trace.startSpan("traceFilter", span); + addToResponseIfNotPresent(response, SPAN_ID_NAME, traceScope.getSpan() + .getSpanId()); } else { traceScope = trace.startSpan("traceFilter"); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java index 6d7e0e3a6..f48d377f6 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreFilter.java @@ -4,13 +4,10 @@ import static org.springframework.cloud.sleuth.Trace.SPAN_ID_NAME; import static org.springframework.cloud.sleuth.Trace.TRACE_ID_NAME; import static org.springframework.util.StringUtils.hasText; -import java.util.Collections; - import javax.servlet.http.HttpServletRequest; -import org.springframework.cloud.sleuth.MilliSpan; -import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceInfo; import org.springframework.cloud.sleuth.TraceScope; import com.netflix.zuul.ZuulFilter; @@ -52,13 +49,9 @@ public class TracePreFilter extends ZuulFilter { TraceScope traceScope = null; if (hasText(spanId) && hasText(traceId)) { - Span span = MilliSpan.builder().traceId(traceId) - .parents(Collections.singletonList(spanId)) - // TODO: use parent() when lombok plugin supports it - .build(); - + TraceInfo traceInfo = new TraceInfo(traceId, spanId); // TODO: trace description? - traceScope = trace.startSpan("traceZuulFilter", span); + traceScope = trace.startSpan("traceZuulFilter", traceInfo); } else { traceScope = trace.startSpan("traceZuulFilter"); From 749e492bd5a55de1f14c67ad16fea018d33767e5 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 14:24:09 -0600 Subject: [PATCH 29/34] removed references to correlation id --- .../sleuth/instrument/circuitbreaker/TraceCommand.java | 2 +- .../sleuth/instrument/scheduling/TraceSchedulingAspect.java | 6 +++--- .../sleuth/instrument/web/TraceWebAutoConfiguration.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCommand.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCommand.java index 6a2ae6507..60fb09713 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCommand.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCommand.java @@ -10,7 +10,7 @@ import org.springframework.cloud.sleuth.TraceScope; * Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting * * @see HystrixCommand - * @see CorrelationIdUpdater + * @see Trace * * @author Tomasz Nurkiewicz, 4financeIT * @author Marcin Grzejszczak, 4financeIT diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java index 588763d1f..cfa788e7f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java @@ -8,8 +8,8 @@ import org.springframework.cloud.sleuth.TraceScope; import org.springframework.scheduling.annotation.Scheduled; /** - * Aspect that sets correlationId for running threads executing methods annotated with {@link Scheduled} annotation. - * For every execution of scheduled method a new, i.e. unique one, value of correlationId will be set. + * Aspect that creates a new Span for running threads executing methods annotated with {@link Scheduled} annotation. + * For every execution of scheduled method a new trace will be started. * * @author Tomasz Nurkewicz, 4financeIT * @author Michal Chmielarz, 4financeIT @@ -28,7 +28,7 @@ public class TraceSchedulingAspect { } @Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))") - public Object setNewCorrelationIdOnThread(final ProceedingJoinPoint pjp) throws Throwable { + public Object traceSceduledThread(final ProceedingJoinPoint pjp) throws Throwable { TraceScope scope = trace.startSpan(pjp.toShortString()); try { return pjp.proceed(); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 8a6146b0d..00aebe585 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -44,7 +44,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter public class TraceWebAutoConfiguration { /** - * Pattern for URLs that should be skipped in correlationID setting + * Pattern for URLs that should be skipped in tracing */ @Value("${spring.cloud.sleuth.instrument.web.skipPattern:}") private String skipPattern; @@ -66,7 +66,7 @@ public class TraceWebAutoConfiguration { @Bean @ConditionalOnMissingBean - public FilterRegistrationBean correlationHeaderFilter() { + public FilterRegistrationBean traceFilter() { Pattern pattern = StringUtils.hasText(skipPattern) ? Pattern.compile(skipPattern) : TraceFilter.DEFAULT_SKIP_PATTERN; return new FilterRegistrationBean(new TraceFilter(trace, pattern)); From 3a24b6f472151b5581c4a6a1f2f29b821c4b4c6d Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 15:36:35 -0600 Subject: [PATCH 30/34] add wrappers for Runnable and Callable --- .../cloud/sleuth/DefaultTrace.java | 29 ++++++++++++ .../springframework/cloud/sleuth/Trace.java | 6 +++ .../sleuth/instrument/TraceCallable.java | 47 +++++++++++++++++++ .../sleuth/instrument/TraceDelegate.java | 40 ++++++++++++++++ .../sleuth/instrument/TraceRunnable.java | 43 +++++++++++++++++ 5 files changed, 165 insertions(+) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceDelegate.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java index af067bb4e..847bd8c46 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java @@ -3,8 +3,11 @@ package org.springframework.cloud.sleuth; import static org.springframework.cloud.sleuth.Utils.error; import java.util.Collections; +import java.util.concurrent.Callable; import org.springframework.cloud.sleuth.event.SpanStartedEvent; +import org.springframework.cloud.sleuth.instrument.TraceCallable; +import org.springframework.cloud.sleuth.instrument.TraceRunnable; import org.springframework.context.ApplicationEventPublisher; /** @@ -126,4 +129,30 @@ public class DefaultTrace implements Trace { s.addKVAnnotation(key, value); } } + + /** + * Wrap the callable in a TraceCallable, if tracing. + * + * @return The callable provided, wrapped if tracing, 'callable' if not. + */ + @Override + public Callable wrap(Callable callable) { + if (TraceContextHolder.isTracing()) { + return new TraceCallable<>(this, callable, TraceContextHolder.getCurrentSpan()); + } + return callable; + } + + /** + * Wrap the runnable in a TraceRunnable, if tracing. + * + * @return The runnable provided, wrapped if tracing, 'runnable' if not. + */ + @Override + public Runnable wrap(Runnable runnable) { + if (TraceContextHolder.isTracing()) { + return new TraceRunnable(this, runnable, TraceContextHolder.getCurrentSpan()); + } + return runnable; + } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java index f86e489e7..6c9f04116 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Trace.java @@ -1,5 +1,7 @@ package org.springframework.cloud.sleuth; +import java.util.concurrent.Callable; + /** * The Trace class is the primary way to interact with the library. It provides * methods to create and manipulate spans. @@ -76,4 +78,8 @@ public interface Trace { * Adds a data annotation to the current span if tracing is currently on. */ void addKVAnnotation(String key, String value); + + Callable wrap(Callable callable); + + Runnable wrap(Runnable runnable); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java new file mode 100644 index 000000000..c2aaa1e1f --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java @@ -0,0 +1,47 @@ +package org.springframework.cloud.sleuth.instrument; + +import java.util.concurrent.Callable; + +import lombok.Value; + +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; + +/** + * @author Spencer Gibb + */ +@Value +public class TraceCallable extends TraceDelegate> implements Callable { + + public TraceCallable(Trace trace, Callable delagate) { + super(trace, delagate); + } + + public TraceCallable(Trace trace, Callable delagate, Span parent) { + super(trace, delagate, parent); + } + + public TraceCallable(Trace trace, Callable delagate, Span parent, String name) { + super(trace, delagate, parent, name); + } + + @Override + public V call() throws Exception { + if (this.parent != null) { + TraceScope scope = startSpan(); + + try { + return this.delagate.call(); + } + finally { + scope.close(); + } + + } + else { + return this.delagate.call(); + } + } + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceDelegate.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceDelegate.java new file mode 100644 index 000000000..458de89d4 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceDelegate.java @@ -0,0 +1,40 @@ +package org.springframework.cloud.sleuth.instrument; + +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceContextHolder; +import org.springframework.cloud.sleuth.TraceScope; + +/** + * @author Spencer Gibb + */ +public abstract class TraceDelegate { + + protected final Trace trace; + protected final T delagate; + protected final Span parent; + protected final String name; + + public TraceDelegate(Trace trace, T delagate) { + this(trace, delagate, TraceContextHolder.getCurrentSpan(), null); + } + + public TraceDelegate(Trace trace, T delagate, Span parent) { + this(trace, delagate, parent, null); + } + + public TraceDelegate(Trace trace, T delagate, Span parent, String name) { + this.trace = trace; + this.delagate = delagate; + this.parent = parent; + this.name = name; + } + + protected TraceScope startSpan() { + return this.trace.startSpan(getSpanName(), this.parent); + } + + protected String getSpanName() { + return this.name == null ? Thread.currentThread().getName() : name; + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java new file mode 100644 index 000000000..259360f6f --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java @@ -0,0 +1,43 @@ +package org.springframework.cloud.sleuth.instrument; + +import lombok.Value; + +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceScope; + +/** + * @author Spencer Gibb + */ +@Value +public class TraceRunnable extends TraceDelegate implements Runnable { + + public TraceRunnable(Trace trace, Runnable delagate) { + super(trace, delagate); + } + + public TraceRunnable(Trace trace, Runnable delagate, Span parent) { + super(trace, delagate, parent); + } + + public TraceRunnable(Trace trace, Runnable delagate, Span parent, String name) { + super(trace, delagate, parent, name); + } + + @Override + public void run() { + if (this.parent != null) { + TraceScope scope = startSpan(); + + try { + this.delagate.run(); + } + finally { + scope.close(); + } + } + else { + this.delagate.run(); + } + } +} From 0de00870a693a2af75ee64d5a70acd31eb3b813b Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 16:01:50 -0600 Subject: [PATCH 31/34] add TraceWebAspect to wrap Callable's returned in Controllers. --- .../sleuth/instrument/web/TraceWebAspect.java | 82 +++++++++++++++++++ .../web/TraceWebAutoConfiguration.java | 6 ++ .../sleuth/sample/SampleApplication.java | 68 ++------------- .../cloud/sleuth/sample/SampleController.java | 82 +++++++++++++++++++ 4 files changed, 178 insertions(+), 60 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java create mode 100644 spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java new file mode 100644 index 000000000..7ffe04d2b --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java @@ -0,0 +1,82 @@ +package org.springframework.cloud.sleuth.instrument.web; + +import java.util.concurrent.Callable; + +import lombok.extern.apachecommons.CommonsLog; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceContextHolder; +import org.springframework.cloud.sleuth.instrument.TraceCallable; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestOperations; + +/** + * Aspect that adds correlation id to + *

    + *

      + *
    • {@link RestController} annotated classes with public {@link Callable} methods
    • + *
    • {@link Controller} annotated classes with public {@link Callable} methods
    • + *
    + *

    + * For controllers an around aspect is created that wraps the {@link Callable#call()} + * method execution in {@link TraceCallable} + *

    + * + * @see RestController + * @see Controller + * @see RestOperations + * @see TraceCallable + * @see Trace + * + * @author Tomasz Nurkewicz, 4financeIT + * @author Marcin Grzejszczak, 4financeIT + * @author Michal Chmielarz, 4financeIT + * @author Spencer Gibb + */ +@Aspect +@CommonsLog +public class TraceWebAspect { + + private final Trace trace; + + public TraceWebAspect(Trace trace) { + this.trace = trace; + } + + @Pointcut("@target(org.springframework.web.bind.annotation.RestController)") + private void anyRestControllerAnnotated() { + } + + @Pointcut("@target(org.springframework.stereotype.Controller)") + private void anyControllerAnnotated() { + } + + @Pointcut("execution(public java.util.concurrent.Callable *(..))") + private void anyPublicMethodReturningCallable() { + } + + @Pointcut("(anyRestControllerAnnotated() || anyControllerAnnotated()) && anyPublicMethodReturningCallable()") + private void anyControllerOrRestControllerWithPublicAsyncMethod() { + } + + @Around("anyControllerOrRestControllerWithPublicAsyncMethod()") + @SuppressWarnings("unchecked") + public Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable { + Callable callable = (Callable) pjp.proceed(); + if (TraceContextHolder.isTracing()) { + log.debug("Wrapping callable with span [" + + TraceContextHolder.getCurrentSpan() + "]"); + + return new TraceCallable(this.trace, callable); + } + else { + return callable; + } + } + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 00aebe585..5e4d8045b 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -52,6 +52,12 @@ public class TraceWebAutoConfiguration { @Autowired private Trace trace; + @Bean + @ConditionalOnMissingBean + public TraceWebAspect traceWebAspect() { + return new TraceWebAspect(trace); + } + @Bean @ConditionalOnMissingBean public TraceHandlerInterceptor traceHandlerInterceptor() { diff --git a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java index 90b1f9d88..8897123cf 100644 --- a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java +++ b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java @@ -1,90 +1,38 @@ package org.springframework.cloud.sleuth.sample; -import java.util.Random; - -import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.cloud.sleuth.Sampler; -import org.springframework.cloud.sleuth.Trace; -import org.springframework.cloud.sleuth.TraceScope; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; -import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.RestTemplate; +import org.springframework.scheduling.annotation.EnableAsync; /** * @author Spencer Gibb */ @Configuration @EnableAutoConfiguration -@EnableAspectJAutoProxy +@EnableAspectJAutoProxy(proxyTargetClass = true) +@EnableAsync @Slf4j public class SampleApplication { public static final String CLIENT_NAME = "testApp"; - @RestController - protected static class SampleController implements - ApplicationListener { - @Autowired - private RestTemplate restTemplate; - @Autowired - private Trace trace; - private int port; - - @SneakyThrows - @RequestMapping("/") - public String hi() { - final Random random = new Random(); - Thread.sleep(random.nextInt(1000)); - - String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", - String.class); - return "hi/" + s; - } - - @SneakyThrows - @RequestMapping("/hi2") - public String hi2() { - final Random random = new Random(); - Thread.sleep(random.nextInt(1000)); - return "hi2"; - } - - @SneakyThrows - @RequestMapping("/traced") - public String traced() { - TraceScope scope = trace.startSpan("customTraceEndpoint", new AlwaysSampler()); - final Random random = new Random(); - int millis = random.nextInt(1000); - log.info("Sleeping for {} millis", millis); - Thread.sleep(millis); - - String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", String.class); - scope.close(); - return "hi/" + s; - } - - @Override - public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { - port = event.getEmbeddedServletContainer().getPort(); - } - } - @Bean public Sampler defaultSampler() { return new AlwaysSampler(); } + @Bean + public SampleController sampleController() { + return new SampleController(); + } + public static void main(String[] args) { SpringApplication.run(SampleApplication.class, args); } diff --git a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java new file mode 100644 index 000000000..242ce39e0 --- /dev/null +++ b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java @@ -0,0 +1,82 @@ +package org.springframework.cloud.sleuth.sample; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; +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.sampler.AlwaysSampler; +import org.springframework.context.ApplicationListener; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +import java.util.Random; +import java.util.concurrent.Callable; + +/** + * @author Spencer Gibb + */ +@Slf4j +@RestController +class SampleController implements + ApplicationListener { + @Autowired + private RestTemplate restTemplate; + @Autowired + private Trace trace; + private int port; + + @SneakyThrows + @RequestMapping("/") + public String hi() { + final Random random = new Random(); + Thread.sleep(random.nextInt(1000)); + + String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", + String.class); + return "hi/" + s; + } + + @RequestMapping("/call") + public Callable call() { + return new Callable() { + @Override + public String call() throws Exception { + Span currentSpan = TraceContextHolder.getCurrentSpan(); + return "async hi: "+currentSpan; + } + }; + } + + + @SneakyThrows + @RequestMapping("/hi2") + public String hi2() { + final Random random = new Random(); + Thread.sleep(random.nextInt(1000)); + return "hi2"; + } + + @SneakyThrows + @RequestMapping("/traced") + public String traced() { + TraceScope scope = trace.startSpan("customTraceEndpoint", new AlwaysSampler()); + final Random random = new Random(); + int millis = random.nextInt(1000); + log.info("Sleeping for {} millis", millis); + Thread.sleep(millis); + + String s = restTemplate.getForObject("http://localhost:" + port + "/hi2", String.class); + scope.close(); + return "hi/" + s; + } + + @Override + public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { + port = event.getEmbeddedServletContainer().getPort(); + } +} From 2877d6b870952761c5d5ce7b788cfd927d6eb13c Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 26 Jun 2015 16:11:25 -0600 Subject: [PATCH 32/34] comment out TraceHandlerInterceptor bean, fix error overflow. --- .../springframework/cloud/sleuth/Utils.java | 2 +- .../web/TraceHandlerInterceptor.java | 2 +- .../web/TraceWebAutoConfiguration.java | 20 ++++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Utils.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Utils.java index 6c8feaf18..09c4dbac5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Utils.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Utils.java @@ -8,7 +8,7 @@ import lombok.extern.apachecommons.CommonsLog; @CommonsLog public abstract class Utils { public static void error(String msg) { - error(msg); + log.error(msg); throw new RuntimeException(msg); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java index 8d8b8a4f1..51c46efd8 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java @@ -25,7 +25,7 @@ public class TraceHandlerInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //TODO: get trace data from request? //TODO: what is the description? - TraceScope scope = trace.startSpan(""); + TraceScope scope = trace.startSpan("traceHandlerInterceptor"); request.setAttribute(ATTR_NAME, scope); return true; } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 5e4d8045b..321c75dd2 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -58,7 +58,8 @@ public class TraceWebAutoConfiguration { return new TraceWebAspect(trace); } - @Bean + //TODO: I don't think TraceHandlerInterceptor is needed with TraceFilter + /*@Bean @ConditionalOnMissingBean public TraceHandlerInterceptor traceHandlerInterceptor() { return new TraceHandlerInterceptor(trace); @@ -70,14 +71,6 @@ public class TraceWebAutoConfiguration { return new TraceWebConfigurer(handlerInterceptor); } - @Bean - @ConditionalOnMissingBean - public FilterRegistrationBean traceFilter() { - Pattern pattern = StringUtils.hasText(skipPattern) ? Pattern.compile(skipPattern) - : TraceFilter.DEFAULT_SKIP_PATTERN; - return new FilterRegistrationBean(new TraceFilter(trace, pattern)); - } - protected static class TraceWebConfigurer extends WebMvcConfigurerAdapter { private TraceHandlerInterceptor interceptor; @@ -89,5 +82,14 @@ public class TraceWebAutoConfiguration { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(interceptor).addPathPatterns("/**"); } + }*/ + + @Bean + @ConditionalOnMissingBean + public FilterRegistrationBean traceFilter() { + Pattern pattern = StringUtils.hasText(skipPattern) ? Pattern.compile(skipPattern) + : TraceFilter.DEFAULT_SKIP_PATTERN; + return new FilterRegistrationBean(new TraceFilter(trace, pattern)); } + } From 74c077816dabb61793da7b3b1a07579a705de493 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Sat, 4 Jul 2015 00:47:49 -0600 Subject: [PATCH 33/34] fix lombok builder syntax --- .../cloud/sleuth/DefaultTrace.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java index 847bd8c46..7a7c10a7c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultTrace.java @@ -41,8 +41,7 @@ public class DefaultTrace implements Trace { .name(name) .traceId(tinfo.getTraceId()) .spanId(idGenerator.create()) - .parents(Collections.singletonList(tinfo.getSpanId())) - //TODO: when lombok plugin supports @Singular parent(tinfo.getSpanId()). + .parent(tinfo.getSpanId()) .build(); return doStart(span); } @@ -91,15 +90,14 @@ public class DefaultTrace implements Trace { } protected Span createChild(Span parent, String childname) { - return MilliSpan.builder(). - begin(System.currentTimeMillis()). - name(childname). - traceId(parent.getTraceId()). - parents(Collections.singletonList(parent.getSpanId())). - //TODO: when lombok plugin supports @Singular parent(parent.getSpanId()). - spanId(idGenerator.create()). - processId(parent.getProcessId()). - build(); + return MilliSpan.builder() + .begin(System.currentTimeMillis()) + .name(childname) + .traceId(parent.getTraceId()) + .parent(parent.getSpanId()) + .spanId(idGenerator.create()) + .processId(parent.getProcessId()) + .build(); } protected TraceScope doStart(Span span) { From cf41d8ece6b6354937cb1993861ef4c61f4d268b Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Sat, 4 Jul 2015 00:49:44 -0600 Subject: [PATCH 34/34] polish --- .../java/org/springframework/cloud/sleuth/MilliSpan.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java index 450068fcc..858060afb 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java @@ -30,19 +30,22 @@ public class MilliSpan implements Span { @Override public synchronized void stop() { if (end == 0) { - if (begin == 0) + if (begin == 0) { throw new IllegalStateException("Span for " + name + " has not been started"); + } end = System.currentTimeMillis(); } } @Override public synchronized long getAccumulatedMillis() { - if (begin == 0) + if (begin == 0) { return 0; - if (end > 0) + } + if (end > 0) { return end - begin; + } return System.currentTimeMillis() - begin; }