Merge pull request #120 from spring-cloud/issues_#98_match_opentracing_span

[Match OpenTracing] Matching Tracer
This commit is contained in:
Marcin Grzejszczak
2016-01-20 11:09:32 +01:00
76 changed files with 1147 additions and 1025 deletions

12
build-tools/pom.xml Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>build-tools</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<name>build-tools</name>
<packaging>jar</packaging>
<description>Spring Cloud Sleuth Build Tools</description>
</project>

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<!-- this. in front of fields -->
<module name="RequireThis">
<property name="checkMethods" value="false"/>
</module>
<module name="TreeWalker">
<!-- tabs instead of spaces -->
<module name="RegexpSinglelineJava">
<property name="format" value="^\t* "/>
<property name="message" value="Indent must use tab characters"/>
<property name="ignoreComments" value="true"/>
</module>
</module>
</module>

43
pom.xml
View File

@@ -26,6 +26,7 @@
</scm>
<modules>
<module>build-tools</module>
<module>spring-cloud-sleuth-dependencies</module>
<module>spring-cloud-sleuth-core</module>
<module>spring-cloud-sleuth-zipkin</module>
@@ -91,8 +92,49 @@
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>build-tools</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>verify-style</id>
<phase>process-classes</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<logViolationsToConsole>true</logViolationsToConsole>
<failOnViolation>false</failOnViolation>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<headerLocation>LICENSE.txt</headerLocation>
</configuration>
</plugin>
</plugins>
</reporting>
<dependencyManagement>
<dependencies>
<dependency>
@@ -164,6 +206,7 @@
<maven.compiler.testTarget>1.8</maven.compiler.testTarget>
<maven.compiler.testSource>1.8</maven.compiler.testSource>
<surefire.plugin.version>2.19.1</surefire.plugin.version>
<checkstyle.version>2.17</checkstyle.version>
</properties>
<profiles>

View File

@@ -1,123 +0,0 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.sleuth;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import lombok.Builder;
import lombok.Data;
import lombok.Singular;
/**
* @author Spencer Gibb
*/
@Data
@Builder(toBuilder=true)
public class MilliSpan implements Span {
private final long begin;
private long end = 0;
private final String name;
private final long traceId;
@Singular
private List<Long> parents = new ArrayList<>();
private final long spanId;
private boolean remote = false;
private boolean exportable = true;
private final Map<String, String> tags = new LinkedHashMap<>();
private final String processId;
@Singular
private final List<Log> logs = new ArrayList<>();
public static MilliSpan.MilliSpanBuilder builder() {
return new MilliSpan().toBuilder();
}
public MilliSpan(long begin, long end, String name, long traceId, List<Long> parents, long spanId, boolean remote, boolean exportable, String processId) {
this.begin = begin<=0 ? System.currentTimeMillis() : begin;
this.end = end;
this.name = name;
this.traceId = traceId;
this.parents = parents;
this.spanId = spanId;
this.remote = remote;
this.exportable = exportable;
this.processId = processId;
}
//for serialization
private MilliSpan() {
this.begin = 0;
this.name = null;
this.traceId = 0;
this.spanId = 0;
this.processId = null;
this.parents = new ArrayList<>();
}
@Override
public synchronized void stop() {
if (this.end == 0) {
if (this.begin == 0) {
throw new IllegalStateException("Span for " + this.name
+ " has not been started");
}
this.end = System.currentTimeMillis();
}
}
@Override
public synchronized long getAccumulatedMillis() {
if (this.begin == 0) {
return 0;
}
if (this.end > 0) {
return this.end - this.begin;
}
return System.currentTimeMillis() - this.begin;
}
@Override
public synchronized boolean isRunning() {
return this.begin != 0 && this.end == 0;
}
@Override
public void tag(String key, String value) {
this.tags.put(key, value);
}
@Override
public void log(String msg) {
this.logs.add(new Log(System.currentTimeMillis(),
msg));
}
@Override
public Map<String, String> tags() {
return Collections.unmodifiableMap(this.tags);
}
@Override
public List<Log> logs() {
return Collections.unmodifiableList(this.logs);
}
}

View File

@@ -18,32 +18,7 @@ package org.springframework.cloud.sleuth;
/**
* Extremely simple callback to determine the frequency that an action should be
* performed.
* <p/>
* '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<Call>. 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.
* <p/>
* For the example above, the next(T info) function may look like this
* <p/>
* <pre>
* <code>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;
* }
* }
* </code>
* </pre>
* This would trace 50% of all gets, 75% of all puts and would not trace any other requests.
*/
public interface Sampler<T> {
public interface Sampler {
boolean next();
}

View File

@@ -16,104 +16,161 @@
package org.springframework.cloud.sleuth;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import lombok.ToString;
import org.springframework.util.Assert;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Interface for gathering and reporting statistics about a block of execution.
* Class for gathering and reporting statistics about a block of execution.
* <p/>
* 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.
* <p/>
*
* @author Spencer Gibb
* @author Marcin Grzejszczak
*/
public interface Span {
@Builder(toBuilder = true)
@ToString
@EqualsAndHashCode
@Getter
public class Span {
/**
* A human-readable name assigned to this span instance.
* <p/>
*/
String getName();
public static final String NOT_SAMPLED_NAME = "X-Not-Sampled";
public static final String PROCESS_ID_NAME = "X-Process-Id";
public static final String PARENT_ID_NAME = "X-Parent-Id";
public static final String TRACE_ID_NAME = "X-Trace-Id";
public static final String SPAN_NAME_NAME = "X-Span-Name";
public static final String SPAN_ID_NAME = "X-Span-Id";
public static final List<String> HEADERS = Arrays
.asList(SPAN_ID_NAME, TRACE_ID_NAME, SPAN_NAME_NAME, PARENT_ID_NAME,
PROCESS_ID_NAME, NOT_SAMPLED_NAME);
public static final String SPAN_EXPORT_NAME = "X-Span-Export";
/**
* A pseudo-unique (random) number assigned to this span instance.
* <p/>
* <p/>
* The spanId is immutable and cannot be changed. It is safe to access this from
* multiple threads.
*/
long getSpanId();
private final long begin;
private long end = 0;
private final String name;
private final long traceId;
@Singular
private List<Long> parents = new ArrayList<>();
private final long spanId;
private boolean remote = false;
private boolean exportable = true;
private final Map<String, String> tags = new LinkedHashMap<>();
private final String processId;
@Singular
private final List<Log> logs = new ArrayList<>();
private final Span savedSpan;
/**
* A pseudo-unique (random) number assigned to the trace associated with this span
*/
long getTraceId();
public static Span.SpanBuilder builder() {
return new Span().toBuilder();
}
/**
* Return a unique id for the process from which this Span originated.
* <p/>
* <p/>
* // TODO: Check when this is going to be null (cause it may be null)
*/
String getProcessId();
public Span(Span current, Span savedSpan) {
this.begin = current.getBegin();
this.end = current.getEnd();
this.name = current.getName();
this.traceId = current.getTraceId();
this.parents = current.getParents();
this.spanId = current.getSpanId();
this.remote = current.isRemote();
this.exportable = current.isExportable();
this.processId = current.getProcessId();
this.tags.putAll(current.tags());
this.logs.addAll(current.logs());
this.savedSpan = savedSpan;
}
/**
* Returns the parent IDs of the span.
* <p/>
* <p/>
* The collection will be empty if there are no parents.
*/
List<Long> getParents();
public Span(long begin, long end, String name, long traceId, List<Long> parents,
long spanId, boolean remote, boolean exportable, String processId) {
this(begin, end, name, traceId, parents, spanId, remote, exportable, processId, null);
}
/**
* Flag that tells us whether the span was started in another process. Useful in RPC
* tracing when the receiver actually has to add annotations to the senders span.
*/
boolean isRemote();
public Span(long begin, long end, String name, long traceId, List<Long> parents,
long spanId, boolean remote, boolean exportable, String processId,
Span savedSpan) {
this.begin = begin<=0 ? System.currentTimeMillis() : begin;
this.end = end;
this.name = name;
this.traceId = traceId;
this.parents = parents;
this.spanId = spanId;
this.remote = remote;
this.exportable = exportable;
this.processId = processId;
this.savedSpan = savedSpan;
}
//for serialization
private Span() {
this.begin = 0;
this.name = null;
this.traceId = 0;
this.spanId = 0;
this.processId = null;
this.parents = new ArrayList<>();
this.savedSpan = null;
}
/**
* The block has completed, stop the clock
*/
void stop();
/**
* Get the start time, in milliseconds
*/
long getBegin();
/**
* Get the stop time, in milliseconds
*/
long getEnd();
public synchronized void stop() {
if (this.end == 0) {
if (this.begin == 0) {
throw new IllegalStateException("Span for " + this.name
+ " has not been started");
}
this.end = System.currentTimeMillis();
}
}
/**
* Return the total amount of time elapsed since start was called, if running, or
* difference between stop and start
*/
long getAccumulatedMillis();
public synchronized long getAccumulatedMillis() {
if (this.begin == 0) {
return 0;
}
if (this.end > 0) {
return this.end - this.begin;
}
return System.currentTimeMillis() - this.begin;
}
/**
* Has the span been started and not yet stopped?
*/
boolean isRunning();
/**
* Is the span eligible for export? If not then we may not need accumulate annotations
* (for instance).
*/
boolean isExportable();
public synchronized boolean isRunning() {
return this.begin != 0 && this.end == 0;
}
/**
* Add a tag or data annotation associated with this span
*/
void tag(String key, String value);
public void tag(String key, String value) {
this.tags.put(key, value);
}
/**
* Add a log or timeline annotation associated with this span
*/
void log(String msg);
public void log(String msg) {
this.logs.add(new Log(System.currentTimeMillis(),
msg));
}
/**
* Get tag data associated with this span (read only)
@@ -121,7 +178,9 @@ public interface Span {
* <p/>
* Will never be null.
*/
Map<String, String> tags();
public Map<String, String> tags() {
return Collections.unmodifiableMap(this.tags);
}
/**
* Get any logs or annotations (read only)
@@ -129,27 +188,111 @@ public interface Span {
* <p/>
* Will never be null.
*/
List<Log> logs();
public List<Log> logs() {
return Collections.unmodifiableList(this.logs);
}
/**
* Class used for conversions of long ids to their String representation
* Returns the saved span. The one that was "current" before this Span.
* <p>
* Might be null
*/
class IdConverter {
public Span getSavedSpan() {
return this.savedSpan;
}
/**
* Represents given long id as hex string
*/
public static String toHex(long id) {
return Long.toHexString(id);
}
public boolean hasSavedSpan() {
return this.savedSpan != null;
}
/**
* Represents hex string as long
*/
public static long fromHex(String hexString) {
Assert.hasText(hexString, "Can't convert empty hex string to long");
return new BigInteger(hexString, 16).longValue();
}
/**
* A human-readable name assigned to this span instance.
* <p>
*/
public String getName() {
return this.name;
}
/**
* A pseudo-unique (random) number assigned to this span instance.
* <p>
* <p>
* The spanId is immutable and cannot be changed. It is safe to access this from
* multiple threads.
*/
public long getSpanId() {
return this.spanId;
}
/**
* A pseudo-unique (random) number assigned to the trace associated with this span
*/
public long getTraceId() {
return this.traceId;
}
/**
* Return a unique id for the process from which this Span originated.
* <p>
* <p>
* // TODO: Check when this is going to be null (cause it may be null)
*/
public String getProcessId() {
return this.processId;
}
/**
* Returns the parent IDs of the span.
* <p>
* <p>
* The collection will be empty if there are no parents.
*/
public List<Long> getParents() {
return this.parents;
}
/**
* Flag that tells us whether the span was started in another process. Useful in RPC
* tracing when the receiver actually has to add annotations to the senders span.
*/
public boolean isRemote() {
return this.remote;
}
/**
* Get the start time, in milliseconds
*/
public long getBegin() {
return this.begin;
}
/**
* Get the stop time, in milliseconds
*/
public long getEnd() {
return this.end;
}
/**
* Is the span eligible for export? If not then we may not need accumulate annotations
* (for instance).
*/
public boolean isExportable() {
return this.exportable;
}
/**
* Represents given long id as hex string
*/
public static String toHex(long id) {
return Long.toHexString(id);
}
/**
* Represents hex string as long
*/
public static long fromHex(String hexString) {
Assert.hasText(hexString, "Can't convert empty hex string to long");
return new BigInteger(hexString, 16).longValue();
}
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.sleuth;
import java.util.Arrays;
import java.util.List;
import lombok.Value;
import lombok.experimental.NonFinal;
/**
* A wrapper around the current span with context for a possible hierarchy or stack of
* spans being monitored.
*
* @author Spencer Gibb
*/
@Value
@NonFinal
public class Trace {
public static final String NOT_SAMPLED_NAME = "X-Not-Sampled";
public static final String PROCESS_ID_NAME = "X-Process-Id";
public static final String PARENT_ID_NAME = "X-Parent-Id";
public static final String TRACE_ID_NAME = "X-Trace-Id";
public static final String SPAN_NAME_NAME = "X-Span-Name";
public static final String SPAN_ID_NAME = "X-Span-Id";
public static final String SPAN_EXPORT_NAME = "X-Span-Export";
public static final List<String> HEADERS = Arrays.asList(SPAN_ID_NAME, TRACE_ID_NAME,
SPAN_NAME_NAME, PARENT_ID_NAME, PROCESS_ID_NAME, NOT_SAMPLED_NAME);
/**
* the span for this trace
*/
private final Span span;
/**
* the trace that was "current" before this trace was entered
*/
private final Trace saved;
public Trace(Trace saved, Span span) {
this.saved = saved;
this.span = span;
}
public Trace(Span span) {
this(null, span);
}
}

View File

@@ -31,14 +31,8 @@ import java.util.concurrent.Callable;
* 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 'startTrace' method in this class starts a new span.
*
* The 'startTrace' methods in this class do a few things:
* <ul>
* <li>Set currentSpan to the new Span.</li>
* <li>Create a TraceSpan object to manage the new Span.</li>
* </ul>
*
@@ -53,18 +47,18 @@ import java.util.concurrent.Callable;
public interface Tracer extends TraceAccessor {
/**
* Creates a trace wrapping a new span.
* Creates a new Span.
* <p/>
* If this thread has a currently active span, it will be the parent of the span we
* create here, and the trace scope will contain the new span and the parent. If there
* is no currently active trace span, the trace scope we create will be empty.
* create here. If there is no currently active trace span, the trace scope we
* create will be empty.
*
* @param name The name field for the new span to create.
*/
Trace startTrace(String name);
Span startTrace(String name);
/**
* Creates a new trace scope with a specific parent. The parent might be in another
* Creates a new Span with a specific parent. The parent might be in another
* process or thread.
* <p/>
* If this thread has a currently active trace span, it must be the 'parent' span that
@@ -73,7 +67,7 @@ public interface Tracer extends TraceAccessor {
*
* @param name The name field for the new span to create.
*/
Trace joinTrace(String name, Span parent);
Span joinTrace(String name, Span parent);
/**
* Start a new span if the sampler allows it or if we are already tracing in this
@@ -81,12 +75,12 @@ public interface Tracer extends TraceAccessor {
* @param name the name of the span
* @param sampler a sampler to decide whether to create the span or not
*/
<T> Trace startTrace(String name, Sampler<T> sampler);
Span startTrace(String name, Sampler sampler);
/**
* Pick up an existing span from another thread.
*/
Trace continueSpan(Span s);
Span continueSpan(Span span);
/**
* Adds a tag to the current span if tracing is currently on.
@@ -96,19 +90,19 @@ public interface Tracer extends TraceAccessor {
/**
* Remove this span from 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().
* use with Span.continueTrace().
*
* @return the saved trace if there was one before the trace started (null otherwise)
*/
Trace detach(Trace trace);
Span detach(Span span);
/**
* Remove this span from the current thread, stop it and send it for collection.
*
* @param trace the trace to close
* @return the saved trace if there was one before the trace started (null otherwise)
* @param span the span to close
* @return the saved span if there was one before the trace started (null otherwise)
*/
Trace close(Trace trace);
Span close(Span span);
<V> Callable<V> wrap(Callable<V> callable);

View File

@@ -41,13 +41,13 @@ public class TraceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Sampler<Void> defaultTraceSampler() {
public Sampler defaultTraceSampler() {
return new IsTracingSampler();
}
@Bean
@ConditionalOnMissingBean
public DefaultTracer traceManager(Sampler<Void> sampler,
public DefaultTracer traceManager(Sampler sampler,
ApplicationEventPublisher publisher) {
return new DefaultTracer(sampler, random(), publisher);
}

View File

@@ -21,7 +21,7 @@ import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
@@ -35,9 +35,9 @@ import org.springframework.util.ClassUtils;
public class TraceBootstrapEnvironmentPostProcessor implements EnvironmentPostProcessor {
private static final String PROPERTY_SOURCE_NAME = "defaultProperties";
private static String[] headers = new String[] { Trace.SPAN_ID_NAME,
Trace.TRACE_ID_NAME, Trace.PARENT_ID_NAME, Trace.PROCESS_ID_NAME,
Trace.NOT_SAMPLED_NAME, Trace.SPAN_NAME_NAME };
private static String[] headers = new String[] { Span.SPAN_ID_NAME,
Span.TRACE_ID_NAME, Span.PARENT_ID_NAME, Span.PROCESS_ID_NAME,
Span.NOT_SAMPLED_NAME, Span.SPAN_NAME_NAME };
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,

View File

@@ -18,7 +18,7 @@ package org.springframework.cloud.sleuth.instrument;
import java.util.concurrent.Callable;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import lombok.EqualsAndHashCode;
@@ -43,12 +43,12 @@ public class TraceCallable<V> extends TraceDelegate<Callable<V>> implements Call
@Override
public V call() throws Exception {
ensureThatThreadIsNotPollutedByPreviousTraces();
Trace trace = startSpan();
Span span = startSpan();
try {
return this.getDelegate().call();
}
finally {
closeAll(trace);
closeAll(span);
}
}

View File

@@ -16,12 +16,10 @@
package org.springframework.cloud.sleuth.instrument;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import lombok.Getter;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
/**
* @author Spencer Gibb
@@ -45,18 +43,18 @@ public abstract class TraceDelegate<T> {
this.parent = tracer.getCurrentSpan();
}
protected void close(Trace trace) {
this.tracer.close(trace);
protected void close(Span span) {
this.tracer.close(span);
}
protected void closeAll(Trace trace) {
trace = this.tracer.close(trace);
while (trace != null) {
trace = this.tracer.detach(trace);
protected void closeAll(Span span) {
span = this.tracer.close(span);
while (span != null) {
span = this.tracer.detach(span);
}
}
protected Trace startSpan() {
protected Span startSpan() {
return this.tracer.joinTrace(getSpanName(), this.parent);
}
@@ -65,6 +63,6 @@ public abstract class TraceDelegate<T> {
}
protected void ensureThatThreadIsNotPollutedByPreviousTraces() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
}

View File

@@ -16,7 +16,7 @@
package org.springframework.cloud.sleuth.instrument;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import lombok.EqualsAndHashCode;
@@ -40,12 +40,12 @@ public class TraceRunnable extends TraceDelegate<Runnable> implements Runnable {
@Override
public void run() {
ensureThatThreadIsNotPollutedByPreviousTraces();
Trace trace = startSpan();
Span span = startSpan();
try {
this.getDelegate().run();
}
finally {
closeAll(trace);
closeAll(span);
}
}
}

View File

@@ -20,9 +20,8 @@ import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixThreadPoolKey;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
/**
* Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting
@@ -72,17 +71,17 @@ public abstract class TraceCommand<R> extends HystrixCommand<R> {
@Override
protected R run() throws Exception {
enforceThatHystrixThreadIsNotPollutedByPreviousTraces();
Trace trace = this.tracer.joinTrace(getCommandKey().name(), parentSpan);
Span span = this.tracer.joinTrace(getCommandKey().name(), parentSpan);
try {
return doRun();
} finally {
this.tracer.close(trace);
this.tracer.close(span);
}
}
// TODO: Do more analysis why this is not removed properly
private void enforceThatHystrixThreadIsNotPollutedByPreviousTraces() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
public abstract R doRun() throws Exception;

View File

@@ -1,10 +1,6 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Random;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.integration.channel.AbstractMessageChannel;
@@ -13,6 +9,8 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
import java.util.Random;
/**
* Abstraction over classes related to channel intercepting
*
@@ -45,19 +43,19 @@ abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter
* trace id passed initially.
*/
Span buildSpan(Message<?> message) {
if (!hasHeader(message, Trace.TRACE_ID_NAME) || !hasHeader(message, Trace.SPAN_ID_NAME)) {
if (!hasHeader(message, Span.TRACE_ID_NAME) || !hasHeader(message, Span.SPAN_ID_NAME)) {
return null; // cannot build a span without ids
}
long spanId = hasHeader(message, Trace.SPAN_ID_NAME) ?
getHeader(message, Trace.SPAN_ID_NAME, Long.class) : this.random.nextLong();
long traceId = getHeader(message, Trace.TRACE_ID_NAME, Long.class);
MilliSpan.MilliSpanBuilder span = MilliSpan.builder().traceId(traceId).spanId(spanId);
Long parentId = getHeader(message, Trace.PARENT_ID_NAME, Long.class);
if (message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
long spanId = hasHeader(message, Span.SPAN_ID_NAME) ?
getHeader(message, Span.SPAN_ID_NAME, Long.class) : this.random.nextLong();
long traceId = getHeader(message, Span.TRACE_ID_NAME, Long.class);
Span.SpanBuilder span = Span.builder().traceId(traceId).spanId(spanId);
Long parentId = getHeader(message, Span.PARENT_ID_NAME, Long.class);
if (message.getHeaders().containsKey(Span.NOT_SAMPLED_NAME)) {
span.exportable(false);
}
String processId = getHeader(message, Trace.PROCESS_ID_NAME);
String spanName = getHeader(message, Trace.SPAN_NAME_NAME);
String processId = getHeader(message, Span.PROCESS_ID_NAME);
String spanName = getHeader(message, Span.SPAN_NAME_NAME);
if (spanName != null) {
span.name(spanName);
}

View File

@@ -16,17 +16,16 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Utility for manipulating message headers related to span data.
*
@@ -38,25 +37,25 @@ public class SpanMessageHeaders {
public static Message<?> addSpanHeaders(TraceKeys traceKeys, Message<?> message,
Span span) {
if (span == null) {
if (!message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
if (!message.getHeaders().containsKey(Span.NOT_SAMPLED_NAME)) {
return MessageBuilder.fromMessage(message)
.setHeader(Trace.NOT_SAMPLED_NAME, "").build();
.setHeader(Span.NOT_SAMPLED_NAME, "").build();
}
return message;
}
Map<String, String> headers = new HashMap<>();
addHeader(headers, Trace.TRACE_ID_NAME, span.getTraceId());
addHeader(headers, Trace.SPAN_ID_NAME, span.getSpanId());
addHeader(headers, Span.TRACE_ID_NAME, span.getTraceId());
addHeader(headers, Span.SPAN_ID_NAME, span.getSpanId());
if (span.isExportable()) {
addAnnotations(traceKeys, message, span);
addHeader(headers, Trace.PARENT_ID_NAME, getFirst(span.getParents()));
addHeader(headers, Trace.SPAN_NAME_NAME, span.getName());
addHeader(headers, Trace.PROCESS_ID_NAME, span.getProcessId());
addHeader(headers, Span.PARENT_ID_NAME, getFirst(span.getParents()));
addHeader(headers, Span.SPAN_NAME_NAME, span.getName());
addHeader(headers, Span.PROCESS_ID_NAME, span.getProcessId());
}
else {
addHeader(headers, Trace.NOT_SAMPLED_NAME, "");
addHeader(headers, Span.NOT_SAMPLED_NAME, "");
}
return MessageBuilder.fromMessage(message).copyHeaders(headers).build();
}
@@ -100,7 +99,7 @@ public class SpanMessageHeaders {
private static void addHeader(Map<String, String> headers, String name, Long value) {
if (value != null) {
addHeader(headers, name, Span.IdConverter.toHex(value));
addHeader(headers, name, Span.toHex(value));
}
}

View File

@@ -16,18 +16,17 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.messaging.Message;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* Builder class to create STOMP message
*
@@ -62,16 +61,16 @@ public class StompMessageBuilder {
public StompMessageBuilder setHeadersFromSpan(final Span span) {
if (span != null) {
setHeaderIfAbsent(Trace.SPAN_ID_NAME, span.getSpanId());
setHeaderIfAbsent(Trace.TRACE_ID_NAME, span.getTraceId());
setHeaderIfAbsent(Trace.SPAN_NAME_NAME, span.getName());
Long parentId = getParentId(TraceContextHolder.getCurrentSpan());
setHeaderIfAbsent(Span.SPAN_ID_NAME, span.getSpanId());
setHeaderIfAbsent(Span.TRACE_ID_NAME, span.getTraceId());
setHeaderIfAbsent(Span.SPAN_NAME_NAME, span.getName());
Long parentId = getParentId(SpanContextHolder.getCurrentSpan());
if (parentId != null)
setHeaderIfAbsent(Trace.PARENT_ID_NAME, parentId);
setHeaderIfAbsent(Span.PARENT_ID_NAME, parentId);
String processId = span.getProcessId();
if (StringUtils.hasText(processId))
setHeaderIfAbsent(Trace.PROCESS_ID_NAME, processId);
setHeaderIfAbsent(Span.PROCESS_ID_NAME, processId);
}
return this;
}
@@ -101,12 +100,12 @@ public class StompMessageBuilder {
case SimpMessageHeaderAccessor.HEART_BEAT_HEADER:
case SimpMessageHeaderAccessor.ORIGINAL_DESTINATION:
case SimpMessageHeaderAccessor.IGNORE_ERROR:
case Trace.NOT_SAMPLED_NAME:
case Trace.PARENT_ID_NAME:
case Trace.PROCESS_ID_NAME:
case Trace.SPAN_ID_NAME:
case Trace.SPAN_NAME_NAME:
case Trace.TRACE_ID_NAME:
case Span.NOT_SAMPLED_NAME:
case Span.PARENT_ID_NAME:
case Span.PROCESS_ID_NAME:
case Span.SPAN_ID_NAME:
case Span.SPAN_NAME_NAME:
case Span.TRACE_ID_NAME:
accessor.setHeader(key, value);
break;
default:

View File

@@ -16,23 +16,22 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Random;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.cloud.sleuth.sampler.IsTracingSampler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import java.util.Random;
/**
* @author Dave Syer
*
*/
public class TraceChannelInterceptor extends AbstractTraceChannelInterceptor {
private ThreadLocal<Trace> traceHolder = new ThreadLocal<>();
private ThreadLocal<Span> traceHolder = new ThreadLocal<>();
public TraceChannelInterceptor(Tracer tracer, TraceKeys traceKeys, Random random) {
super(tracer, traceKeys, random);
@@ -40,7 +39,7 @@ public class TraceChannelInterceptor extends AbstractTraceChannelInterceptor {
@Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
Trace trace = this.traceHolder.get();
Span trace = this.traceHolder.get();
// Double close to clean up the parent (remote span as well)
getTracer().close(getTracer().close(trace));
this.traceHolder.remove();
@@ -53,16 +52,16 @@ public class TraceChannelInterceptor extends AbstractTraceChannelInterceptor {
getTracer().getCurrentSpan());
}
String name = getMessageChannelName(channel);
Trace trace = startSpan(buildSpan(message), name, message);
this.traceHolder.set(trace);
return SpanMessageHeaders.addSpanHeaders(getTraceKeys(), message, trace.getSpan());
Span span = startSpan(buildSpan(message), name, message);
this.traceHolder.set(span);
return SpanMessageHeaders.addSpanHeaders(getTraceKeys(), message, span);
}
private Trace startSpan(Span span, String name, Message<?> message) {
private Span startSpan(Span span, String name, Message<?> message) {
if (span != null) {
return getTracer().joinTrace(name, span);
}
if (message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
if (message.getHeaders().containsKey(Span.NOT_SAMPLED_NAME)) {
return getTracer().startTrace(name, IsTracingSampler.INSTANCE);
}
return getTracer().startTrace(name);

View File

@@ -18,7 +18,6 @@ package org.springframework.cloud.sleuth.instrument.integration;
import org.springframework.aop.support.AopUtils;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.messaging.Message;
@@ -50,7 +49,7 @@ public class TraceContextPropagationChannelInterceptor extends ChannelIntercepto
private final Tracer tracer;
private final static ThreadLocal<Trace> ORIGINAL_CONTEXT = new ThreadLocal<>();
private final static ThreadLocal<Span> ORIGINAL_CONTEXT = new ThreadLocal<>();
public TraceContextPropagationChannelInterceptor(Tracer tracer) {
this.tracer = tracer;
@@ -101,12 +100,12 @@ public class TraceContextPropagationChannelInterceptor extends ChannelIntercepto
protected void populatePropagatedContext(Span span, Message<?> message,
MessageChannel channel) {
if (span != null) {
ORIGINAL_CONTEXT.set(this.tracer.continueSpan(span).getSaved());
ORIGINAL_CONTEXT.set(this.tracer.continueSpan(span).getSavedSpan());
}
}
protected void resetPropagatedContext() {
Trace originalContext = ORIGINAL_CONTEXT.get();
Span originalContext = ORIGINAL_CONTEXT.get();
this.tracer.detach(originalContext);
ORIGINAL_CONTEXT.remove();
}
@@ -128,16 +127,16 @@ public class TraceContextPropagationChannelInterceptor extends ChannelIntercepto
Map<String, Object> headers = new HashMap<>();
headers.putAll(message.getHeaders());
setHeader(headers, Trace.SPAN_ID_NAME, this.span.getSpanId());
setHeader(headers, Trace.TRACE_ID_NAME, this.span.getTraceId());
setHeader(headers, Trace.SPAN_NAME_NAME, this.span.getName());
setHeader(headers, Span.SPAN_ID_NAME, this.span.getSpanId());
setHeader(headers, Span.TRACE_ID_NAME, this.span.getTraceId());
setHeader(headers, Span.SPAN_NAME_NAME, this.span.getName());
Long parentId = getParentId(span);
if (parentId != null) {
setHeader(headers, Trace.PARENT_ID_NAME, parentId);
setHeader(headers, Span.PARENT_ID_NAME, parentId);
}
String processId = span.getProcessId();
if (StringUtils.hasText(processId)) {
setHeader(headers, Trace.PROCESS_ID_NAME, processId);
setHeader(headers, Span.PROCESS_ID_NAME, processId);
}
this.messageHeaders = new MessageHeaders(headers);
}
@@ -148,7 +147,7 @@ public class TraceContextPropagationChannelInterceptor extends ChannelIntercepto
}
}
public void setHeader(Map<String, Object> headers, String name, long value) {
setHeader(headers, name, Span.IdConverter.toHex(value));
setHeader(headers, name, Span.toHex(value));
}
@Override

View File

@@ -15,16 +15,15 @@
*/
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Random;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.ChannelInterceptor;
import java.util.Random;
/**
* Interceptor for Stomp Messages sent over websocket
*
@@ -33,7 +32,7 @@ import org.springframework.messaging.support.ChannelInterceptor;
*
*/
public class TraceStompMessageChannelInterceptor extends AbstractTraceChannelInterceptor implements ChannelInterceptor {
private ThreadLocal<Trace> traceScopeHolder = new ThreadLocal<Trace>();
private ThreadLocal<Span> traceScopeHolder = new ThreadLocal<>();
public TraceStompMessageChannelInterceptor(Tracer tracer, TraceKeys traceKeys, Random random) {
super(tracer, traceKeys, random);
@@ -41,16 +40,16 @@ public class TraceStompMessageChannelInterceptor extends AbstractTraceChannelInt
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
if (getTracer().isTracing() || message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
if (getTracer().isTracing() || message.getHeaders().containsKey(Span.NOT_SAMPLED_NAME)) {
return StompMessageBuilder.fromMessage(message).setHeadersFromSpan(getTracer().getCurrentSpan()).build();
}
String name = getMessageChannelName(channel);
Trace trace = startSpan(buildSpan(message), name);
this.traceScopeHolder.set(trace);
return StompMessageBuilder.fromMessage(message).setHeadersFromSpan(trace.getSpan()).build();
Span span = startSpan(buildSpan(message), name);
this.traceScopeHolder.set(span);
return StompMessageBuilder.fromMessage(message).setHeadersFromSpan(span).build();
}
private Trace startSpan(Span span, String name) {
private Span startSpan(Span span, String name) {
if (span != null) {
return getTracer().joinTrace(name, span);
}
@@ -59,8 +58,8 @@ public class TraceStompMessageChannelInterceptor extends AbstractTraceChannelInt
@Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
final ThreadLocal<Trace> traceScopeHolder = this.traceScopeHolder;
Trace traceInScope = traceScopeHolder.get();
final ThreadLocal<Span> traceScopeHolder = this.traceScopeHolder;
Span traceInScope = traceScopeHolder.get();
getTracer().close(traceInScope);
traceScopeHolder.remove();
}

View File

@@ -18,7 +18,6 @@ package org.springframework.cloud.sleuth.instrument.integration;
import org.springframework.aop.support.AopUtils;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.integration.channel.DirectChannel;
@@ -40,7 +39,7 @@ public class TraceStompMessageContextPropagationChannelInterceptor extends Chann
implements ExecutorChannelInterceptor {
private final Tracer tracer;
private final static ThreadLocal<Trace> ORIGINAL_CONTEXT = new ThreadLocal<>();
private final static ThreadLocal<Span> ORIGINAL_CONTEXT = new ThreadLocal<>();
private TraceKeys traceKeys;
public TraceStompMessageContextPropagationChannelInterceptor(Tracer tracer, TraceKeys traceKeys) {
@@ -94,12 +93,12 @@ public class TraceStompMessageContextPropagationChannelInterceptor extends Chann
protected void populatePropagatedContext(Span span) {
if (span != null) {
ORIGINAL_CONTEXT.set(this.tracer.continueSpan(span).getSaved());
ORIGINAL_CONTEXT.set(this.tracer.continueSpan(span).getSavedSpan());
}
}
protected void resetPropagatedContext() {
Trace originalContext = ORIGINAL_CONTEXT.get();
Span originalContext = ORIGINAL_CONTEXT.get();
this.tracer.detach(originalContext);
ORIGINAL_CONTEXT.remove();
}

View File

@@ -19,7 +19,7 @@ package org.springframework.cloud.sleuth.instrument.scheduling;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.scheduling.annotation.Scheduled;
@@ -46,12 +46,12 @@ public class TraceSchedulingAspect {
@Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))")
public Object traceBackgroundThread(final ProceedingJoinPoint pjp) throws Throwable {
Trace trace = this.tracer.startTrace(pjp.toShortString());
Span span = this.tracer.startTrace(pjp.toShortString());
try {
return pjp.proceed();
}
finally {
this.tracer.close(trace);
this.tracer.close(span);
}
}

View File

@@ -15,30 +15,14 @@
*/
package org.springframework.cloud.sleuth.instrument.web;
import static org.springframework.util.StringUtils.hasText;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Random;
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.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.MilliSpan.MilliSpanBuilder;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span.SpanBuilder;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
import org.springframework.cloud.sleuth.event.ServerSentEvent;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.cloud.sleuth.sampler.IsTracingSampler;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
@@ -48,16 +32,29 @@ import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.UrlPathHelper;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Random;
import java.util.regex.Pattern;
import static org.springframework.util.StringUtils.hasText;
/**
* 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
* Filter that takes the value of the {@link Span#SPAN_ID_NAME} and
* {@link Span#TRACE_ID_NAME} header from either request or response and uses them to
* create a new span.
*
* <p>In order to keep the size of spans manageable, this only add tags defined in {@link TraceKeys}.
* If you need to add additional tags, such as headers subtype this and override
* {@link #addRequestTags} or {@link #addResponseTags}.
*
* @see TraceManager
* @see Tracer
* @see TraceKeys
* @see TraceWebAutoConfiguration#traceWebFilter(TraceFilter)
*
@@ -106,32 +103,33 @@ public class TraceFilter extends OncePerRequestFilter
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
String uri = this.urlPathHelper.getPathWithinApplication(request);
boolean skip = this.skipPattern.matcher(uri).matches()
|| getHeader(request, response, Trace.NOT_SAMPLED_NAME) != null;
|| getHeader(request, response, Span.NOT_SAMPLED_NAME) != null;
Trace trace = (Trace) request.getAttribute(TRACE_REQUEST_ATTR);
if (trace != null) {
this.tracer.continueSpan(trace.getSpan());
Span spanFromRequest = (Span) request.getAttribute(TRACE_REQUEST_ATTR);
if (spanFromRequest != null) {
this.tracer.continueSpan(spanFromRequest);
}
else if (skip) {
addToResponseIfNotPresent(response, Trace.NOT_SAMPLED_NAME, "");
addToResponseIfNotPresent(response, Span.NOT_SAMPLED_NAME, "");
}
String name = "http" + uri;
if (hasHeader(request, response, Trace.TRACE_ID_NAME)) {
long traceId = Span.IdConverter.fromHex(getHeader(request, response, Trace.TRACE_ID_NAME));
long spanId = hasHeader(request, response, Trace.SPAN_ID_NAME) ?
Span.IdConverter.fromHex(getHeader(request, response, Trace.SPAN_ID_NAME)) : this.random.nextLong();
if (hasHeader(request, response, Span.TRACE_ID_NAME)) {
long traceId = Span.fromHex(getHeader(request, response, Span.TRACE_ID_NAME));
long spanId = hasHeader(request, response, Span.SPAN_ID_NAME) ?
Span.fromHex(getHeader(request, response, Span.SPAN_ID_NAME)) :
this.random.nextLong();
MilliSpanBuilder span = MilliSpan.builder().traceId(traceId).spanId(spanId);
SpanBuilder span = Span.builder().traceId(traceId).spanId(spanId);
if (skip) {
span.exportable(false);
}
String processId = getHeader(request, response, Trace.PROCESS_ID_NAME);
String parentName = getHeader(request, response, Trace.SPAN_NAME_NAME);
String processId = getHeader(request, response, Span.PROCESS_ID_NAME);
String parentName = getHeader(request, response, Span.SPAN_NAME_NAME);
if (StringUtils.hasText(parentName)) {
span.name(parentName);
} else {
@@ -140,26 +138,27 @@ public class TraceFilter extends OncePerRequestFilter
if (StringUtils.hasText(processId)) {
span.processId(processId);
}
if (hasHeader(request, response, Trace.PARENT_ID_NAME)) {
span.parent(Span.IdConverter.fromHex(getHeader(request, response, Trace.PARENT_ID_NAME)));
if (hasHeader(request, response, Span.PARENT_ID_NAME)) {
span.parent(
Span.fromHex(getHeader(request, response, Span.PARENT_ID_NAME)));
}
span.remote(true);
Span parent = span.build();
trace = this.tracer.joinTrace(name, parent);
publish(new ServerReceivedEvent(this, parent, trace.getSpan()));
request.setAttribute(TRACE_REQUEST_ATTR, trace);
spanFromRequest = this.tracer.joinTrace(name, parent);
publish(new ServerReceivedEvent(this, parent, spanFromRequest));
request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest);
}
else {
if (skip) {
trace = this.tracer.startTrace(name, IsTracingSampler.INSTANCE
spanFromRequest = this.tracer.startTrace(name, IsTracingSampler.INSTANCE
);
}
else {
trace = this.tracer.startTrace(name);
spanFromRequest = this.tracer.startTrace(name);
}
request.setAttribute(TRACE_REQUEST_ATTR, trace);
request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest);
}
Throwable exception = null;
@@ -179,25 +178,25 @@ public class TraceFilter extends OncePerRequestFilter
return;
}
if (skip) {
addToResponseIfNotPresent(response, Trace.NOT_SAMPLED_NAME, "");
addToResponseIfNotPresent(response, Span.NOT_SAMPLED_NAME, "");
}
if (trace != null) {
if (spanFromRequest != null) {
addResponseTags(response, exception);
addResponseHeaders(response, trace.getSpan());
if (trace.getSaved() != null) {
publish(new ServerSentEvent(this, trace.getSaved().getSpan(),
trace.getSpan()));
addResponseHeaders(response, spanFromRequest);
if (spanFromRequest.hasSavedSpan()) {
publish(new ServerSentEvent(this, spanFromRequest.getSavedSpan(),
spanFromRequest));
}
// Double close to clean up the parent (remote span as well)
this.tracer.close(this.tracer.close(trace));
this.tracer.close(this.tracer.close(spanFromRequest));
}
}
}
private void addResponseHeaders(HttpServletResponse response, Span span) {
if (span != null) {
response.addHeader(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(span.getSpanId()));
response.addHeader(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId()));
response.addHeader(Span.SPAN_ID_NAME, Span.toHex(span.getSpanId()));
response.addHeader(Span.TRACE_ID_NAME, Span.toHex(span.getTraceId()));
}
}

View File

@@ -16,14 +16,14 @@
package org.springframework.cloud.sleuth.instrument.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
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
*/
@@ -42,8 +42,8 @@ public class TraceHandlerInterceptor implements HandlerInterceptor {
Object handler) throws Exception {
// TODO: get trace data from request?
// TODO: what is the description?
Trace trace = this.tracer.startTrace("traceHandlerInterceptor");
request.setAttribute(ATTR_NAME, trace);
Span span = this.tracer.startTrace("traceHandlerInterceptor");
request.setAttribute(ATTR_NAME, span);
return true;
}
@@ -56,7 +56,7 @@ public class TraceHandlerInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
Trace trace = Trace.class.cast(request.getAttribute(ATTR_NAME));
this.tracer.close(trace);
Span span = Span.class.cast(request.getAttribute(ATTR_NAME));
this.tracer.close(span);
}
}

View File

@@ -36,7 +36,6 @@ import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
import org.springframework.cloud.netflix.feign.support.SpringDecoder;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.TraceAccessor;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
@@ -123,14 +122,14 @@ public class TraceFeignClientAutoConfiguration {
public void apply(RequestTemplate template) {
Span span = getCurrentSpan();
if (span == null) {
setHeader(template, Trace.NOT_SAMPLED_NAME, "");
setHeader(template, Span.NOT_SAMPLED_NAME, "");
return;
}
template.header(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId()));
setHeader(template, Trace.SPAN_NAME_NAME, span.getName());
setHeader(template, Trace.SPAN_ID_NAME, span.getSpanId());
setHeader(template, Trace.PARENT_ID_NAME, getParentId(span));
setHeader(template, Trace.PROCESS_ID_NAME, span.getProcessId());
template.header(Span.TRACE_ID_NAME, Span.toHex(span.getTraceId()));
setHeader(template, Span.SPAN_NAME_NAME, span.getName());
setHeader(template, Span.SPAN_ID_NAME, span.getSpanId());
setHeader(template, Span.PARENT_ID_NAME, getParentId(span));
setHeader(template, Span.PROCESS_ID_NAME, span.getProcessId());
publish(new ClientSentEvent(this, span));
}
};
@@ -156,7 +155,7 @@ public class TraceFeignClientAutoConfiguration {
public void setHeader(RequestTemplate request, String name, Long value) {
if (value != null) {
setHeader(request, name, Span.IdConverter.toHex(value));
setHeader(request, name, Span.toHex(value));
}
}
@@ -166,12 +165,12 @@ public class TraceFeignClientAutoConfiguration {
newHeaders.putAll(headers);
Span span = getCurrentSpan();
if (span == null) {
setHeader(newHeaders, Trace.NOT_SAMPLED_NAME, "");
setHeader(newHeaders, Span.NOT_SAMPLED_NAME, "");
return newHeaders;
}
setHeader(newHeaders, Trace.TRACE_ID_NAME, span.getTraceId());
setHeader(newHeaders, Trace.SPAN_ID_NAME, span.getSpanId());
setHeader(newHeaders, Trace.PARENT_ID_NAME, getParentId(span));
setHeader(newHeaders, Span.TRACE_ID_NAME, span.getTraceId());
setHeader(newHeaders, Span.SPAN_ID_NAME, span.getSpanId());
setHeader(newHeaders, Span.PARENT_ID_NAME, getParentId(span));
return newHeaders;
}
@@ -184,7 +183,7 @@ public class TraceFeignClientAutoConfiguration {
public void setHeader(Map<String, Collection<String>> headers, String name,
Long value) {
if (value != null ){
setHeader(headers, name, Span.IdConverter.toHex(value));
setHeader(headers, name, Span.toHex(value));
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.TraceAccessor;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
@@ -62,14 +61,14 @@ ApplicationEventPublisherAware {
ClientHttpRequestExecution execution) throws IOException {
Span span = getCurrentSpan();
if (span == null) {
setHeader(request, Trace.NOT_SAMPLED_NAME, "");
setHeader(request, Span.NOT_SAMPLED_NAME, "");
return execution.execute(request, body);
}
setHeader(request, Trace.TRACE_ID_NAME, span.getTraceId());
setHeader(request, Trace.SPAN_ID_NAME, span.getSpanId());
setHeader(request, Trace.SPAN_NAME_NAME, span.getName());
setHeader(request, Trace.PARENT_ID_NAME, getParentId(span));
setHeader(request, Trace.PROCESS_ID_NAME, span.getProcessId());
setHeader(request, Span.TRACE_ID_NAME, span.getTraceId());
setHeader(request, Span.SPAN_ID_NAME, span.getSpanId());
setHeader(request, Span.SPAN_NAME_NAME, span.getName());
setHeader(request, Span.PARENT_ID_NAME, getParentId(span));
setHeader(request, Span.PROCESS_ID_NAME, span.getProcessId());
publish(new ClientSentEvent(this, span));
return new TraceHttpResponse(this, execution.execute(request, body));
}
@@ -100,7 +99,7 @@ ApplicationEventPublisherAware {
public void setHeader(HttpRequest request, String name, Long value) {
if (value != null) {
setHeader(request, name, Span.IdConverter.toHex(value));
setHeader(request, name, Span.toHex(value));
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.cloud.sleuth.instrument.zuul;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.TraceAccessor;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.context.ApplicationEvent;
@@ -61,15 +60,15 @@ ApplicationEventPublisherAware {
// N.B. this will only work with the simple host filter (not ribbon) unless you set hystrix.execution.isolation.strategy=SEMAPHORE
Span span = getCurrentSpan();
if (span == null) {
setHeader(response, Trace.NOT_SAMPLED_NAME, "");
setHeader(response, Span.NOT_SAMPLED_NAME, "");
return null;
}
try {
setHeader(response, Trace.SPAN_ID_NAME, span.getSpanId());
setHeader(response, Trace.TRACE_ID_NAME, span.getTraceId());
setHeader(response, Trace.SPAN_NAME_NAME, span.getName());
setHeader(response, Trace.PARENT_ID_NAME, getParentId(span));
setHeader(response, Trace.PROCESS_ID_NAME, span.getProcessId());
setHeader(response, Span.SPAN_ID_NAME, span.getSpanId());
setHeader(response, Span.TRACE_ID_NAME, span.getTraceId());
setHeader(response, Span.SPAN_NAME_NAME, span.getName());
setHeader(response, Span.PARENT_ID_NAME, getParentId(span));
setHeader(response, Span.PROCESS_ID_NAME, span.getProcessId());
// TODO: the client sent event should come from the client not the filter!
publish(new ClientSentEvent(this, span));
}
@@ -94,7 +93,7 @@ ApplicationEventPublisherAware {
}
}
public void setHeader(Map<String, String> request, String name, Long value) {
setHeader(request, name, Span.IdConverter.toHex(value));
setHeader(request, name, Span.toHex(value));
}
@Override

View File

@@ -24,7 +24,6 @@ import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonComm
import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory;
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.TraceAccessor;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.context.ApplicationEvent;
@@ -91,15 +90,15 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
protected void customizeRequest(HttpRequest.Builder requestBuilder) {
Span span = getCurrentSpan();
if (span == null) {
setHeader(requestBuilder, Trace.NOT_SAMPLED_NAME, "");
setHeader(requestBuilder, Span.NOT_SAMPLED_NAME, "");
return;
}
setHeader(requestBuilder, Trace.TRACE_ID_NAME, span.getTraceId());
setHeader(requestBuilder, Trace.SPAN_ID_NAME, span.getSpanId());
setHeader(requestBuilder, Trace.SPAN_NAME_NAME, span.getName());
setHeader(requestBuilder, Trace.PARENT_ID_NAME,
setHeader(requestBuilder, Span.TRACE_ID_NAME, span.getTraceId());
setHeader(requestBuilder, Span.SPAN_ID_NAME, span.getSpanId());
setHeader(requestBuilder, Span.SPAN_NAME_NAME, span.getName());
setHeader(requestBuilder, Span.PARENT_ID_NAME,
getParentId(span));
setHeader(requestBuilder, Trace.PROCESS_ID_NAME,
setHeader(requestBuilder, Span.PROCESS_ID_NAME,
span.getProcessId());
publish(new ClientSentEvent(this, span));
}
@@ -122,7 +121,7 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
}
public void setHeader(HttpRequest.Builder builder, String name, Long value) {
setHeader(builder, name, Span.IdConverter.toHex(value));
setHeader(builder, name, Span.toHex(value));
}
private Span getCurrentSpan() {

View File

@@ -16,9 +16,9 @@
package org.springframework.cloud.sleuth.log;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanContinuedEvent;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
@@ -26,8 +26,6 @@ import org.springframework.context.event.EventListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import lombok.extern.slf4j.Slf4j;
/**
* @author Spencer Gibb
*/
@@ -38,9 +36,9 @@ public class Slf4jSpanListener {
@Order(Ordered.LOWEST_PRECEDENCE)
public void start(SpanAcquiredEvent event) {
Span span = event.getSpan();
MDC.put(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(span.getSpanId()));
MDC.put(Trace.SPAN_EXPORT_NAME, String.valueOf(span.isExportable()));
MDC.put(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId()));
MDC.put(Span.SPAN_ID_NAME, Span.toHex(span.getSpanId()));
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(span.isExportable()));
MDC.put(Span.TRACE_ID_NAME, Span.toHex(span.getTraceId()));
log.trace("Starting span: {}", span);
if (event.getParent() != null) {
log.trace("With parent: {}", event.getParent());
@@ -51,9 +49,9 @@ public class Slf4jSpanListener {
@Order(Ordered.LOWEST_PRECEDENCE)
public void continued(SpanContinuedEvent event) {
Span span = event.getSpan();
MDC.put(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(span.getSpanId()));
MDC.put(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId()));
MDC.put(Trace.SPAN_EXPORT_NAME, String.valueOf(span.isExportable()));
MDC.put(Span.SPAN_ID_NAME, Span.toHex(span.getSpanId()));
MDC.put(Span.TRACE_ID_NAME, Span.toHex(span.getTraceId()));
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(span.isExportable()));
log.trace("Continued span: {}", event.getSpan());
}
@@ -63,13 +61,13 @@ public class Slf4jSpanListener {
log.trace("Stopped span: {}", event.getSpan());
if (event.getParent() != null) {
log.trace("With parent: {}", event.getParent());
MDC.put(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(event.getParent().getSpanId()));
MDC.put(Trace.SPAN_EXPORT_NAME, String.valueOf(event.getParent().isExportable()));
MDC.put(Span.SPAN_ID_NAME, Span.toHex(event.getParent().getSpanId()));
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(event.getParent().isExportable()));
}
else {
MDC.remove(Trace.SPAN_ID_NAME);
MDC.remove(Trace.SPAN_EXPORT_NAME);
MDC.remove(Trace.TRACE_ID_NAME);
MDC.remove(Span.SPAN_ID_NAME);
MDC.remove(Span.SPAN_EXPORT_NAME);
MDC.remove(Span.TRACE_ID_NAME);
}
}

View File

@@ -21,7 +21,7 @@ import org.springframework.cloud.sleuth.Sampler;
/**
* @author Spencer Gibb
*/
public class AlwaysSampler implements Sampler<Void> {
public class AlwaysSampler implements Sampler {
@Override
public boolean next() {
return true;

View File

@@ -17,17 +17,17 @@
package org.springframework.cloud.sleuth.sampler;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
/**
* @author Spencer Gibb
*/
public class IsTracingSampler implements Sampler<Void> {
public class IsTracingSampler implements Sampler {
public static IsTracingSampler INSTANCE = new IsTracingSampler();
@Override
public boolean next() {
return TraceContextHolder.isTracing();
return SpanContextHolder.isTracing();
}
}

View File

@@ -20,7 +20,7 @@ import org.springframework.cloud.sleuth.TraceAccessor;
* @author Marcin Grzejszczak
* @author Adrian Cole
*/
public class PercentageBasedSampler implements Sampler<Void> {
public class PercentageBasedSampler implements Sampler {
private final SamplerConfiguration configuration;
private final TraceAccessor traceAccessor;

View File

@@ -16,8 +16,8 @@
package org.springframework.cloud.sleuth.template;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
public interface TraceCallback<T> {
T doInTrace(Trace trace);
T doInTrace(Span span);
}

View File

@@ -16,7 +16,7 @@
package org.springframework.cloud.sleuth.template;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceDelegate;
@@ -35,11 +35,11 @@ public class TraceTemplate implements TraceOperations {
public <T> T trace(final TraceCallback<T> callback) {
if (this.tracer.isTracing()) {
DelegateCallback<T> delegate = new DelegateCallback<>(this.tracer);
Trace trace = delegate.startSpan();
Span span = delegate.startSpan();
try {
return callback.doInTrace(trace);
return callback.doInTrace(span);
} finally {
this.tracer.close(trace);
this.tracer.close(span);
}
} else {
return callback.doInTrace(null);
@@ -53,7 +53,7 @@ public class TraceTemplate implements TraceOperations {
}
@Override
protected Trace startSpan() {
protected Span startSpan() {
return super.startSpan();
}

View File

@@ -16,15 +16,8 @@
package org.springframework.cloud.sleuth.trace;
import static org.springframework.cloud.sleuth.util.ExceptionUtils.warn;
import java.util.Random;
import java.util.concurrent.Callable;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanContinuedEvent;
@@ -34,18 +27,23 @@ import org.springframework.cloud.sleuth.instrument.TraceRunnable;
import org.springframework.cloud.sleuth.util.ExceptionUtils;
import org.springframework.context.ApplicationEventPublisher;
import java.util.Random;
import java.util.concurrent.Callable;
import static org.springframework.cloud.sleuth.util.ExceptionUtils.warn;
/**
* @author Spencer Gibb
*/
public class DefaultTracer implements Tracer {
private final Sampler<Void> defaultSampler;
private final Sampler defaultSampler;
private final ApplicationEventPublisher publisher;
private final Random random;
public DefaultTracer(Sampler<Void> defaultSampler,
public DefaultTracer(Sampler defaultSampler,
Random random, ApplicationEventPublisher publisher) {
this.defaultSampler = defaultSampler;
this.random = random;
@@ -53,13 +51,13 @@ public class DefaultTracer implements Tracer {
}
@Override
public Trace joinTrace(String name, Span parent) {
public Span joinTrace(String name, Span parent) {
if (parent == null) {
return startTrace(name);
}
Span currentSpan = getCurrentSpan();
if (currentSpan != null && !parent.equals(currentSpan)) {
warn("Trace client warn: thread " + Thread.currentThread().getName()
warn("Warn during joining trace: thread " + Thread.currentThread().getName()
+ " tried to start a new Span " + "with parent " + parent.toString()
+ ", but there is already a " + "currentSpan " + currentSpan);
}
@@ -67,20 +65,20 @@ public class DefaultTracer implements Tracer {
}
@Override
public Trace startTrace(String name) {
public Span startTrace(String name) {
return this.startTrace(name, this.defaultSampler);
}
@Override
public <T> Trace startTrace(String name, Sampler<T> s) {
Span span = null;
public Span startTrace(String name, Sampler s) {
Span span;
if (isTracing() || s.next()) {
span = createChild(getCurrentSpan(), name);
}
else {
// Non-exportable so we keep the trace but not other data
long id = createId();
span = MilliSpan.builder().begin(System.currentTimeMillis()).name(name)
span = Span.builder().begin(System.currentTimeMillis()).name(name)
.traceId(id).spanId(id).exportable(false).build();
this.publisher.publishEvent(new SpanAcquiredEvent(this, span));
}
@@ -88,12 +86,11 @@ public class DefaultTracer implements Tracer {
}
@Override
public Trace detach(Trace trace) {
if (trace == null) {
public Span detach(Span span) {
if (span == null) {
return null;
}
Span cur = TraceContextHolder.getCurrentSpan();
Span span = trace.getSpan();
Span cur = SpanContextHolder.getCurrentSpan();
if (cur != span) {
ExceptionUtils.warn("Tried to detach trace span but "
+ "it is not the current span for the '"
@@ -101,24 +98,23 @@ public class DefaultTracer implements Tracer {
+ ". You have " + "probably forgotten to close or detach " + cur);
}
else {
if (trace.getSaved() != null) {
TraceContextHolder.setCurrentTrace(trace.getSaved());
if (span.hasSavedSpan()) {
SpanContextHolder.setCurrentSpan(span.getSavedSpan());
}
else {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
}
return trace.getSaved();
return span.getSavedSpan();
}
@Override
public Trace close(Trace trace) {
if (trace == null) {
public Span close(Span span) {
if (span == null) {
return null;
}
Span cur = TraceContextHolder.getCurrentSpan();
Span span = trace.getSpan();
Trace savedTrace = trace.getSaved();
Span cur = SpanContextHolder.getCurrentSpan();
Span savedSpan = span.getSavedSpan();
if (cur != span) {
ExceptionUtils.warn("Tried to close trace span but "
+ "it is not the current span for the '"
@@ -126,42 +122,35 @@ public class DefaultTracer implements Tracer {
+ ". You have " + "probably forgotten to close or detach " + cur);
}
else {
if (span != null) {
span.stop();
if (savedTrace != null
&& span.getParents().contains(savedTrace.getSpan().getSpanId())) {
this.publisher.publishEvent(
new SpanReleasedEvent(this, savedTrace.getSpan(), span));
TraceContextHolder.setCurrentTrace(savedTrace);
}
else {
if (!span.isRemote()) {
this.publisher.publishEvent(new SpanReleasedEvent(this, span));
}
TraceContextHolder.removeCurrentTrace();
}
span.stop();
if (savedSpan != null && span.getParents().contains(savedSpan.getSpanId())) {
this.publisher.publishEvent(new SpanReleasedEvent(this, savedSpan, span));
SpanContextHolder.setCurrentSpan(savedSpan);
}
else {
TraceContextHolder.removeCurrentTrace();
if (!span.isRemote()) {
this.publisher.publishEvent(new SpanReleasedEvent(this, span));
}
SpanContextHolder.removeCurrentSpan();
}
}
return savedTrace;
return savedSpan;
}
protected Span createChild(Span parent, String name) {
long id = createId();
if (parent == null) {
MilliSpan span = MilliSpan.builder().begin(System.currentTimeMillis())
Span span = Span.builder().begin(System.currentTimeMillis())
.name(name).traceId(id).spanId(id).build();
this.publisher.publishEvent(new SpanAcquiredEvent(this, span));
return span;
}
else {
if (TraceContextHolder.getCurrentTrace() == null) {
Trace trace = createTrace(null, parent);
TraceContextHolder.setCurrentTrace(trace);
if (SpanContextHolder.getCurrentSpan() == null) {
Span span = createSpan(null, parent);
SpanContextHolder.setCurrentSpan(span);
}
MilliSpan span = MilliSpan.builder().begin(System.currentTimeMillis())
Span span = Span.builder().begin(System.currentTimeMillis())
.name(name).traceId(parent.getTraceId()).parent(parent.getSpanId())
.spanId(id).processId(parent.getProcessId()).build();
this.publisher.publishEvent(new SpanAcquiredEvent(this, parent, span));
@@ -174,27 +163,27 @@ public class DefaultTracer implements Tracer {
}
@Override
public Trace continueSpan(Span span) {
public Span continueSpan(Span span) {
if (span != null) {
this.publisher.publishEvent(new SpanContinuedEvent(this, span));
}
Trace trace = createTrace(TraceContextHolder.getCurrentTrace(), span);
TraceContextHolder.setCurrentTrace(trace);
return trace;
Span newSpan = createSpan(SpanContextHolder.getCurrentSpan(), span);
SpanContextHolder.setCurrentSpan(newSpan);
return newSpan;
}
protected Trace createTrace(Trace trace, Span span) {
return new Trace(trace, span);
protected Span createSpan(Span saved, Span span) {
return new Span(span, saved);
}
@Override
public Span getCurrentSpan() {
return TraceContextHolder.getCurrentSpan();
return SpanContextHolder.getCurrentSpan();
}
@Override
public boolean isTracing() {
return TraceContextHolder.isTracing();
return SpanContextHolder.isTracing();
}
@Override

View File

@@ -16,45 +16,39 @@
package org.springframework.cloud.sleuth.trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.core.NamedThreadLocal;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.cloud.sleuth.Span;
import org.springframework.core.NamedThreadLocal;
/**
* @author Spencer Gibb
*/
@CommonsLog
public class TraceContextHolder {
public class SpanContextHolder {
private static final ThreadLocal<Trace> currentTrace = new NamedThreadLocal<>("Trace Context");
public static Trace getCurrentTrace() {
return currentTrace.get();
}
private static final ThreadLocal<Span> CURRENT_SPAN = new NamedThreadLocal<>("Trace Context");
public static Span getCurrentSpan() {
return isTracing() ? currentTrace.get().getSpan() : null;
return isTracing() ? CURRENT_SPAN.get() : null;
}
public static void setCurrentTrace(Trace trace) {
public static void setCurrentSpan(Span span) {
// backwards compatibility
if (trace == null) {
currentTrace.remove();
if (span == null) {
CURRENT_SPAN.remove();
return;
}
if (log.isTraceEnabled()) {
log.trace("Setting current trace " + trace);
log.trace("Setting current span " + span);
}
currentTrace.set(trace);
CURRENT_SPAN.set(span);
}
public static void removeCurrentTrace() {
currentTrace.remove();
public static void removeCurrentSpan() {
CURRENT_SPAN.remove();
}
public static boolean isTracing() {
return currentTrace.get() != null;
return CURRENT_SPAN.get() != null;
}
}

View File

@@ -25,7 +25,7 @@ import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.sampler.IsTracingSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
@@ -53,12 +53,12 @@ public class DefaultTraceManagerTests {
@Before
public void setup() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@After
public void clean() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
@@ -67,12 +67,12 @@ public class DefaultTraceManagerTests {
DefaultTracer traceManager = new DefaultTracer(new IsTracingSampler(), new Random(), publisher);
Trace trace = traceManager.startTrace(CREATE_SIMPLE_TRACE, new AlwaysSampler());
Span span = traceManager.startTrace(CREATE_SIMPLE_TRACE, new AlwaysSampler());
try {
importantWork1(traceManager);
}
finally {
traceManager.close(trace);
traceManager.close(span);
}
verify(publisher, times(NUM_SPANS)).publishEvent(isA(SpanAcquiredEvent.class));
@@ -122,7 +122,7 @@ public class DefaultTraceManagerTests {
}
private void importantWork1(Tracer tracer) {
Trace cur = tracer.startTrace(IMPORTANT_WORK_1);
Span cur = tracer.startTrace(IMPORTANT_WORK_1);
try {
Thread.sleep((long) (50 * Math.random()));
importantWork2(tracer);
@@ -136,7 +136,7 @@ public class DefaultTraceManagerTests {
}
private void importantWork2(Tracer tracer) {
Trace cur = tracer.startTrace(IMPORTANT_WORK_2);
Span cur = tracer.startTrace(IMPORTANT_WORK_2);
try {
Thread.sleep((long) (50 * Math.random()));
}

View File

@@ -1,43 +0,0 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.sleuth;
import org.junit.Test;
import java.util.Collections;
/**
* @author Rob Winch
* @author Spencer Gibb
*/
public class MilliSpanTests {
@Test(expected = UnsupportedOperationException.class)
public void getAnnotationsReadOnly() {
MilliSpan span = new MilliSpan(1, 2, "name", 1L, Collections.<Long>emptyList(), 2L, true, true, "process");
span.tags().put("a", "b");
}
@Test(expected = UnsupportedOperationException.class)
public void getTimelineAnnotationsReadOnly() {
MilliSpan span = new MilliSpan(1, 2, "name", 1L, Collections.<Long>emptyList(), 2L, true, true, "process");
span.logs().add(new Log(1, "1"));
}
}

View File

@@ -2,10 +2,14 @@ package org.springframework.cloud.sleuth;
import org.junit.Test;
import java.util.Collections;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
* @author Rob Winch
* @author Spencer Gibb
*/
public class SpanTest {
@@ -13,7 +17,7 @@ public class SpanTest {
public void should_convert_long_to_hex_string() throws Exception {
long someLong = 123123L;
String hexString = Span.IdConverter.toHex(someLong);
String hexString = Span.toHex(someLong);
then(hexString).isEqualTo("1e0f3");
}
@@ -22,13 +26,27 @@ public class SpanTest {
public void should_convert_hex_string_to_long() throws Exception {
String hexString = "1e0f3";
long someLong = Span.IdConverter.fromHex(hexString);
long someLong = Span.fromHex(hexString);
then(someLong).isEqualTo(123123L);
}
@Test(expected = IllegalArgumentException.class)
public void should_throw_exception_when_null_string_is_to_be_converted_to_long() throws Exception {
Span.IdConverter.fromHex(null);
Span.fromHex(null);
}
@Test(expected = UnsupportedOperationException.class) public void getAnnotationsReadOnly() {
Span span = new Span(1, 2, "name", 1L, Collections.<Long>emptyList(), 2L, true,
true, "process");
span.tags().put("a", "b");
}
@Test(expected = UnsupportedOperationException.class) public void getTimelineAnnotationsReadOnly() {
Span span = new Span(1, 2, "name", 1L, Collections.<Long>emptyList(), 2L, true,
true, "process");
span.logs().add(new Log(1, "1"));
}
}

View File

@@ -5,11 +5,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import java.util.Random;
@@ -28,21 +28,21 @@ public class TraceCallableTests {
@After
public void clean() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
public void should_not_see_same_trace_id_in_successive_tasks()
throws Exception {
Trace firstTrace = givenCallableGetsSubmitted(
Span firstSpan = givenCallableGetsSubmitted(
thatRetrievesTraceFromThreadLocal());
Trace secondTrace = whenCallableGetsSubmitted(
Span secondSpan = whenCallableGetsSubmitted(
thatRetrievesTraceFromThreadLocal());
then(secondTrace.getSpan().getTraceId())
.isNotEqualTo(firstTrace.getSpan().getTraceId());
then(secondTrace.getSaved()).isNull();
then(secondSpan.getTraceId())
.isNotEqualTo(firstSpan.getTraceId());
then(secondSpan.getSavedSpan()).isNull();
}
@Test
@@ -50,51 +50,51 @@ public class TraceCallableTests {
throws Exception {
givenCallableGetsSubmitted(thatRetrievesTraceFromThreadLocal());
Trace secondTrace = whenNonTraceableCallableGetsSubmitted(
Span secondSpan = whenNonTraceableCallableGetsSubmitted(
thatRetrievesTraceFromThreadLocal());
then(secondTrace).isNull();
then(secondSpan).isNull();
}
@Test
public void should_remove_parent_span_from_thread_local_after_finishing_work()
throws Exception {
Trace parent = givenSpanIsAlreadyActive();
Trace child = givenCallableGetsSubmitted(thatRetrievesTraceFromThreadLocal());
Span parent = givenSpanIsAlreadyActive();
Span child = givenCallableGetsSubmitted(thatRetrievesTraceFromThreadLocal());
then(parent).as("parent").isNotNull();
then(child.getSaved()).isEqualTo(parent);
then(child.getSavedSpan()).isEqualTo(parent);
Trace secondTrace = whenNonTraceableCallableGetsSubmitted(
Span secondSpan = whenNonTraceableCallableGetsSubmitted(
thatRetrievesTraceFromThreadLocal());
then(secondTrace).isNull();
then(secondSpan).isNull();
}
private Trace givenSpanIsAlreadyActive() {
private Span givenSpanIsAlreadyActive() {
return this.tracer.startTrace("parent");
}
private Callable<Trace> thatRetrievesTraceFromThreadLocal() {
return new Callable<Trace>() {
private Callable<Span> thatRetrievesTraceFromThreadLocal() {
return new Callable<Span>() {
@Override
public Trace call() throws Exception {
return TraceContextHolder.getCurrentTrace();
public Span call() throws Exception {
return SpanContextHolder.getCurrentSpan();
}
};
}
private Trace givenCallableGetsSubmitted(Callable<Trace> callable)
private Span givenCallableGetsSubmitted(Callable<Span> callable)
throws InterruptedException, java.util.concurrent.ExecutionException {
return whenCallableGetsSubmitted(callable);
}
private Trace whenCallableGetsSubmitted(Callable<Trace> callable)
private Span whenCallableGetsSubmitted(Callable<Span> callable)
throws InterruptedException, java.util.concurrent.ExecutionException {
return this.executor.submit(new TraceCallable<>(this.tracer, callable))
.get();
}
private Trace whenNonTraceableCallableGetsSubmitted(Callable<Trace> callable)
private Span whenNonTraceableCallableGetsSubmitted(Callable<Span> callable)
throws InterruptedException, java.util.concurrent.ExecutionException {
return this.executor.submit(callable).get();
}

View File

@@ -1,23 +1,23 @@
package org.springframework.cloud.sleuth.instrument;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
@RunWith(MockitoJUnitRunner.class)
public class TraceRunnableTests {
@@ -27,7 +27,7 @@ public class TraceRunnableTests {
@After
public void cleanup() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
@@ -36,19 +36,19 @@ public class TraceRunnableTests {
// given
TraceKeepingRunnable traceKeepingRunnable = runnableThatRetrievesTraceFromThreadLocal();
givenRunnableGetsSubmitted(traceKeepingRunnable);
Trace firstTrace = traceKeepingRunnable.trace;
then(firstTrace).as("first trace").isNotNull();
Span firstSpan = traceKeepingRunnable.span;
then(firstSpan).as("first span").isNotNull();
// when
whenRunnableGetsSubmitted(traceKeepingRunnable);
// then
Trace secondTrace = traceKeepingRunnable.trace;
then(secondTrace.getSpan().getTraceId()).as("second trace id")
.isNotEqualTo(firstTrace.getSpan().getTraceId()).as("first trace id");
Span secondSpan = traceKeepingRunnable.span;
then(secondSpan.getTraceId()).as("second span id")
.isNotEqualTo(firstSpan.getTraceId()).as("first span id");
// and
then(secondTrace.getSaved()).as("saved trace as remnant of first trace")
then(secondSpan.getSavedSpan()).as("saved span as remnant of first span")
.isNull();
}
@@ -58,15 +58,15 @@ public class TraceRunnableTests {
// given
TraceKeepingRunnable traceKeepingRunnable = runnableThatRetrievesTraceFromThreadLocal();
givenRunnableGetsSubmitted(traceKeepingRunnable);
Trace firstTrace = traceKeepingRunnable.trace;
then(firstTrace).as("expected trace").isNotNull();
Span firstSpan = traceKeepingRunnable.span;
then(firstSpan).as("expected span").isNotNull();
// when
whenNonTraceableRunnableGetsSubmitted(traceKeepingRunnable);
// then
Trace secondTrace = traceKeepingRunnable.trace;
then(secondTrace).as("unexpected trace").isNull();
Span secondSpan = traceKeepingRunnable.span;
then(secondSpan).as("unexpected span").isNull();
}
private TraceKeepingRunnable runnableThatRetrievesTraceFromThreadLocal() {
@@ -87,11 +87,11 @@ public class TraceRunnableTests {
}
static class TraceKeepingRunnable implements Runnable {
public Trace trace;
public Span span;
@Override
public void run() {
this.trace = TraceContextHolder.getCurrentTrace();
this.span = SpanContextHolder.getCurrentSpan();
}
}

View File

@@ -1,7 +1,18 @@
package org.springframework.cloud.sleuth.instrument.executor;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.BDDAssertions.then;
import lombok.SneakyThrows;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import java.util.ArrayList;
import java.util.List;
@@ -12,21 +23,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import lombok.SneakyThrows;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(MockitoJUnitRunner.class)
public class TraceableExecutorServiceTests {
@@ -42,7 +40,7 @@ public class TraceableExecutorServiceTests {
public void setup() {
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher);
this.traceManagerableExecutorService = new TraceableExecutorService(this.executorService, this.tracer);
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@After
@@ -50,17 +48,17 @@ public class TraceableExecutorServiceTests {
this.tracer = null;
this.traceManagerableExecutorService.shutdown();
this.executorService.shutdown();
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
@SneakyThrows
public void should_propagate_trace_id_and_set_new_span_when_traceable_executor_service_is_executed() {
Trace trace = this.tracer.startTrace("PARENT");
Span span = this.tracer.startTrace("PARENT");
CompletableFuture.allOf(runnablesExecutedViaTraceManagerableExecutorService()).get();
this.tracer.close(trace);
this.tracer.close(span);
then(this.spanVerifyingRunnable.traceIds.stream().distinct().collect(toList())).containsOnly(trace.getSpan().getTraceId());
then(this.spanVerifyingRunnable.traceIds.stream().distinct().collect(toList())).containsOnly(span.getTraceId());
then(this.spanVerifyingRunnable.spanIds.stream().distinct().collect(toList())).hasSize(TOTAL_THREADS);
}
@@ -79,7 +77,7 @@ public class TraceableExecutorServiceTests {
@Override
public void run() {
Span span = TraceContextHolder.getCurrentSpan();
Span span = SpanContextHolder.getCurrentSpan();
this.traceIds.add(span.getTraceId());
this.spanIds.add(span.getSpanId());
}

View File

@@ -11,7 +11,7 @@ import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -39,7 +39,7 @@ public class SpanPassingForHystrixViaAnnotationsIntegrationTests {
}
private Span givenASpanInCurrentThread() {
Span span = tracer.startTrace("existing").getSpan();
Span span = tracer.startTrace("existing");
tracer.continueSpan(span);
return span;
}
@@ -61,7 +61,7 @@ public class SpanPassingForHystrixViaAnnotationsIntegrationTests {
@After
public void cleanTrace() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@DefaultTestAutoConfiguration
@@ -81,7 +81,7 @@ public class SpanPassingForHystrixViaAnnotationsIntegrationTests {
@HystrixCommand
public void invokeLogicWrappedInHystrixCommand() {
spanCaughtFromHystrixThread = new AtomicReference<>(TraceContextHolder.getCurrentSpan());
spanCaughtFromHystrixThread = new AtomicReference<>(SpanContextHolder.getCurrentSpan());
}
public Long getTraceId() {

View File

@@ -6,12 +6,11 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import java.util.Random;
@@ -28,64 +27,65 @@ public class TraceCommandTests {
@Before
public void setup() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@After
public void cleanup() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
public void should_remove_span_from_thread_local_after_finishing_work()
throws Exception {
TraceContextHolder.removeCurrentTrace();
Trace firstTraceFromHystrix = givenACommandWasExecuted(traceReturningCommand());
SpanContextHolder.removeCurrentSpan();
Span firstSpanFromHystrix = givenACommandWasExecuted(traceReturningCommand());
Trace secondTraceFromHystrix = whenCommandIsExecuted(traceReturningCommand());
Span secondSpanFromHystrix = whenCommandIsExecuted(traceReturningCommand());
then(secondTraceFromHystrix.getSpan().getTraceId()).as("second trace id")
.isNotEqualTo(firstTraceFromHystrix.getSpan().getTraceId()).as("first trace id");
then(secondTraceFromHystrix.getSaved()).as("saved trace as remnant of first trace")
then(secondSpanFromHystrix.getTraceId()).as("second span id")
.isNotEqualTo(firstSpanFromHystrix.getTraceId()).as("first span id");
then(secondSpanFromHystrix.getSavedSpan()).as("saved span as remnant of first span")
.isNull();
}
@Test
public void should_run_Hystrix_command_with_span_passed_from_parent_thread() {
givenATraceIsPresentInTheCurrentThread();
TraceCommand<Trace> command = traceReturningCommand();
TraceCommand<Span> command = traceReturningCommand();
Trace traceFromCommand = whenCommandIsExecuted(command);
Span spanFromCommand = whenCommandIsExecuted(command);
then(traceFromCommand).as("Trace from the Hystrix Thread").isNotNull();
then(traceFromCommand.getSpan().getTraceId()).isEqualTo(EXPECTED_TRACE_ID);
then(spanFromCommand).as("Span from the Hystrix Thread").isNotNull();
then(spanFromCommand.getTraceId()).isEqualTo(EXPECTED_TRACE_ID);
}
@After
public void cleanUpTrace() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
private Trace givenATraceIsPresentInTheCurrentThread() {
return this.tracer.joinTrace("test", MilliSpan.builder().traceId(EXPECTED_TRACE_ID).build());
private Span givenATraceIsPresentInTheCurrentThread() {
return this.tracer
.joinTrace("test", Span.builder().traceId(EXPECTED_TRACE_ID).build());
}
private TraceCommand<Trace> traceReturningCommand() {
return new TraceCommand<Trace>(this.tracer, withGroupKey(asKey(""))
private TraceCommand<Span> traceReturningCommand() {
return new TraceCommand<Span>(this.tracer, withGroupKey(asKey(""))
.andCommandKey(HystrixCommandKey.Factory.asKey("")).andThreadPoolPropertiesDefaults(
HystrixThreadPoolProperties.Setter().withMaxQueueSize(1).withCoreSize(1))) {
@Override
public Trace doRun() throws Exception {
return TraceContextHolder.getCurrentTrace();
public Span doRun() throws Exception {
return SpanContextHolder.getCurrentSpan();
}
};
}
private Trace whenCommandIsExecuted(TraceCommand<Trace> command) {
private Span whenCommandIsExecuted(TraceCommand<Span> command) {
return command.execute();
}
private Trace givenACommandWasExecuted(TraceCommand<Trace> command) {
private Span givenACommandWasExecuted(TraceCommand<Span> command) {
return whenCommandIsExecuted(command);
}
}

View File

@@ -1,21 +1,21 @@
package org.springframework.cloud.sleuth.instrument.integration;
import static org.assertj.core.api.BDDAssertions.then;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.ExecutorSubscribableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringJUnit4ClassRunner.class)
public abstract class AbstractTraceStompIntegrationTests {
@@ -34,11 +34,11 @@ public abstract class AbstractTraceStompIntegrationTests {
@After
public void close() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
this.channel.unsubscribe(this.stompMessageHandler);
}
Trace givenALocallyStartedSpan() {
Span givenALocallyStartedSpan() {
return this.tracer.startTrace("testSendMessage", this.sampler);
}
@@ -52,13 +52,13 @@ public abstract class AbstractTraceStompIntegrationTests {
}
Long thenSpanIdFromHeadersIsNotEmpty() {
Long header = getValueFromHeaders(Trace.SPAN_ID_NAME, Long.class);
Long header = getValueFromHeaders(Span.SPAN_ID_NAME, Long.class);
then(header).as("Span id should not be empty").isNotNull();
return header;
}
Long thenTraceIdFromHeadersIsNotEmpty() {
Long header = getValueFromHeaders(Trace.TRACE_ID_NAME, Long.class);
Long header = getValueFromHeaders(Span.TRACE_ID_NAME, Long.class);
then(header).as("Trace id should not be empty").isNotNull();
return header;
}

View File

@@ -26,12 +26,11 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.cloud.sleuth.instrument.integration.TraceChannelInterceptorTests.App;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
@@ -48,7 +47,10 @@ import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* @author Dave Syer
@@ -79,7 +81,7 @@ public class TraceChannelInterceptorTests implements MessageHandler {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
this.message = message;
this.span = TraceContextHolder.getCurrentSpan();
this.span = SpanContextHolder.getCurrentSpan();
}
@Before
@@ -89,35 +91,36 @@ public class TraceChannelInterceptorTests implements MessageHandler {
@After
public void close() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
this.channel.unsubscribe(this);
}
@Test
public void nonExportableSpanCreation() {
this.channel.send(MessageBuilder.withPayload("hi").setHeader(Trace.NOT_SAMPLED_NAME, "")
this.channel.send(MessageBuilder.withPayload("hi").setHeader(Span.NOT_SAMPLED_NAME, "")
.build());
assertNotNull("message was null", this.message);
String spanId = this.message.getHeaders().get(Trace.SPAN_ID_NAME, String.class);
String spanId = this.message.getHeaders().get(Span.SPAN_ID_NAME, String.class);
assertNotNull("spanId was null", spanId);
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
assertFalse(this.span.isExportable());
}
@Test
public void parentSpanIncluded() {
this.channel.send(MessageBuilder.withPayload("hi").setHeader(Trace.TRACE_ID_NAME, 10L)
.setHeader(Trace.SPAN_ID_NAME, 20L)
this.channel.send(MessageBuilder.withPayload("hi").setHeader(Span.TRACE_ID_NAME, 10L)
.setHeader(Span.SPAN_ID_NAME, 20L)
.build());
assertNotNull("message was null", this.message);
String spanId = this.message.getHeaders().get(Trace.SPAN_ID_NAME, String.class);
String spanId = this.message.getHeaders().get(Span.SPAN_ID_NAME, String.class);
assertNotNull("spanId was null", spanId);
long traceId = Span.IdConverter.fromHex(this.message.getHeaders().get(Trace.TRACE_ID_NAME, String.class));
long traceId = Span
.fromHex(this.message.getHeaders().get(Span.TRACE_ID_NAME, String.class));
then(traceId).isEqualTo(10L);
then(spanId).isNotEqualTo(20L);
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
assertEquals(1, this.app.events.size());
}
@@ -126,45 +129,45 @@ public class TraceChannelInterceptorTests implements MessageHandler {
this.channel.send(MessageBuilder.withPayload("hi").build());
assertNotNull("message was null", this.message);
String spanId = this.message.getHeaders().get(Trace.SPAN_ID_NAME, String.class);
String spanId = this.message.getHeaders().get(Span.SPAN_ID_NAME, String.class);
assertNotNull("spanId was null", spanId);
String traceId = this.message.getHeaders().get(Trace.TRACE_ID_NAME, String.class);
String traceId = this.message.getHeaders().get(Span.TRACE_ID_NAME, String.class);
assertNotNull("traceId was null", traceId);
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
public void headerCreation() {
Trace trace = this.tracer.startTrace("testSendMessage",
Span span = this.tracer.startTrace("testSendMessage",
new AlwaysSampler());
this.channel.send(MessageBuilder.withPayload("hi").build());
this.tracer.close(trace);
this.tracer.close(span);
assertNotNull("message was null", this.message);
String spanId = this.message.getHeaders().get(Trace.SPAN_ID_NAME, String.class);
String spanId = this.message.getHeaders().get(Span.SPAN_ID_NAME, String.class);
assertNotNull("spanId was null", spanId);
String traceId = this.message.getHeaders().get(Trace.TRACE_ID_NAME, String.class);
String traceId = this.message.getHeaders().get(Span.TRACE_ID_NAME, String.class);
assertNotNull("traceId was null", traceId);
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
// TODO: Refactor to parametrized test together with sending messages via channel
@Test
public void headerCreationViaMessagingTemplate() {
Trace trace = this.tracer.startTrace("testSendMessage",
Span span = this.tracer.startTrace("testSendMessage",
new AlwaysSampler());
this.messagingTemplate.send(MessageBuilder.withPayload("hi").build());
this.tracer.close(trace);
this.tracer.close(span);
assertNotNull("message was null", this.message);
String spanId = this.message.getHeaders().get(Trace.SPAN_ID_NAME, String.class);
String spanId = this.message.getHeaders().get(Span.SPAN_ID_NAME, String.class);
assertNotNull("spanId was null", spanId);
String traceId = this.message.getHeaders().get(Trace.TRACE_ID_NAME, String.class);
String traceId = this.message.getHeaders().get(Span.TRACE_ID_NAME, String.class);
assertNotNull("traceId was null", traceId);
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Configuration

View File

@@ -25,11 +25,10 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.integration.TraceContextPropagationChannelInterceptorTests.App;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.channel.QueueChannel;
@@ -60,25 +59,27 @@ public class TraceContextPropagationChannelInterceptorTests {
@After
public void close() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
public void testSpanPropagation() {
Trace trace = this.tracer.startTrace("testSendMessage", new AlwaysSampler());
Span span = this.tracer.startTrace("testSendMessage", new AlwaysSampler());
this.channel.send(MessageBuilder.withPayload("hi").build());
Long expectedSpanId = trace.getSpan().getSpanId();
this.tracer.close(trace);
Long expectedSpanId = span.getSpanId();
this.tracer.close(span);
Message<?> message = this.channel.receive(0);
assertNotNull("message was null", message);
Long spanId = Span.IdConverter.fromHex(message.getHeaders().get(Trace.SPAN_ID_NAME, String.class));
Long spanId = Span
.fromHex(message.getHeaders().get(Span.SPAN_ID_NAME, String.class));
assertEquals("spanId was wrong", expectedSpanId, spanId);
long traceId = Span.IdConverter.fromHex(message.getHeaders().get(Trace.TRACE_ID_NAME, String.class));
long traceId = Span
.fromHex(message.getHeaders().get(Span.TRACE_ID_NAME, String.class));
assertNotNull("traceId was null", traceId);
}

View File

@@ -6,10 +6,10 @@ import org.junit.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.instrument.integration.TraceStompMessageChannelInterceptorTests.TestApplication;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
@@ -44,30 +44,30 @@ public class TraceStompMessageChannelInterceptorTests extends AbstractTraceStomp
thenSpanIdFromHeadersIsNotEmpty();
thenTraceIdFromHeadersIsNotEmpty();
then(TraceContextHolder.getCurrentTrace()).isNull();
then(SpanContextHolder.getCurrentSpan()).isNull();
}
@Test
public void should_propagate_headers_when_message_was_sent_during_local_span_starting() {
Trace trace = givenALocallyStartedSpan();
Span span = givenALocallyStartedSpan();
Message<?> message = givenMessageToBeSampled();
whenTheMessageWasSent(message);
this.tracer.close(trace);
this.tracer.close(span);
Long spanId = thenSpanIdFromHeadersIsNotEmpty();
long traceId = thenTraceIdFromHeadersIsNotEmpty();
then(traceId).isEqualTo(trace.getSpan().getTraceId());
then(spanId).isEqualTo(trace.getSpan().getSpanId());
then(TraceContextHolder.getCurrentTrace()).isNull();
then(traceId).isEqualTo(span.getTraceId());
then(spanId).isEqualTo(span.getSpanId());
then(SpanContextHolder.getCurrentSpan()).isNull();
}
private Message<?> givenMessageNotToBeSampled() {
return StompMessageBuilder.fromMessage(new GenericMessage<>("Message2")).setHeader(Trace.NOT_SAMPLED_NAME, "").build();
return StompMessageBuilder.fromMessage(new GenericMessage<>("Message2")).setHeader(Span.NOT_SAMPLED_NAME, "").build();
}
private String thenSpanIdFromHeadersIsEmpty() {
String header = getValueFromHeaders(Trace.SPAN_ID_NAME, String.class);
String header = getValueFromHeaders(Span.SPAN_ID_NAME, String.class);
then(header).as("Span id should be empty").isNullOrEmpty();
return header;
}

View File

@@ -7,7 +7,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.instrument.integration.TraceStompMessageContextPropagationChannelInterceptorTests.TestApplication;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.context.annotation.Bean;
@@ -28,12 +28,12 @@ public class TraceStompMessageContextPropagationChannelInterceptorTests extends
@Test
public void should_propagate_span_information() {
Trace trace = givenALocallyStartedSpan();
Span span = givenALocallyStartedSpan();
Message<?> m = givenMessageToBeSampled();
whenTheMessageWasSent(m);
Long expectedTraceId = trace.getSpan().getTraceId();
this.tracer.close(trace);
Long expectedTraceId = span.getTraceId();
this.tracer.close(span);
thenReceivedMessageIsNotNull();
long traceId = thenTraceIdFromHeadersIsNotEmpty();

View File

@@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
@@ -70,7 +70,7 @@ class TestBeanWithScheduledMethod {
@Scheduled(fixedDelay = 1L)
public void scheduledMethod() {
this.span = TraceContextHolder.getCurrentSpan();
this.span = SpanContextHolder.getCurrentSpan();
}
public Span getSpan() {

View File

@@ -9,7 +9,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.web.common.HttpMockServer;
import org.springframework.cloud.sleuth.instrument.web.common.AbstractMvcWiremockIntegrationTest;
@@ -71,7 +71,7 @@ public class RestTemplateTraceAspectIntegrationTests extends AbstractMvcWiremock
}
private void thenTraceIdHasBeenSetOnARequestHeader() {
this.wireMock.verifyThat(getRequestedFor(urlMatching(".*")).withHeader(Trace.TRACE_ID_NAME, matching("^(?!\\s*$).+")));
this.wireMock.verifyThat(getRequestedFor(urlMatching(".*")).withHeader(Span.TRACE_ID_NAME, matching("^(?!\\s*$).+")));
}
private void whenARequestIsSentToAnAsyncEndpoint(String url) throws Exception {

View File

@@ -10,7 +10,7 @@ import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
@@ -40,7 +40,7 @@ public class TraceAsyncIntegrationTests {
}
private Span givenASpanInCurrentThread() {
Span span = tracer.startTrace("existing").getSpan();
Span span = tracer.startTrace("existing");
tracer.continueSpan(span);
return span;
}
@@ -62,7 +62,7 @@ public class TraceAsyncIntegrationTests {
@After
public void cleanTrace() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@DefaultTestAutoConfiguration
@@ -83,7 +83,7 @@ public class TraceAsyncIntegrationTests {
@Async
public void invokeAsynchronousLogic() {
span.set(TraceContextHolder.getCurrentSpan());
span.set(SpanContextHolder.getCurrentSpan());
}
public Long getTraceId() {

View File

@@ -1,15 +1,10 @@
package org.springframework.cloud.sleuth.instrument.web;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
@@ -20,6 +15,10 @@ import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(TraceFilterIntegrationTests.class)
@DefaultTestAutoConfiguration
@@ -60,19 +59,19 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest {
private MvcResult whenSentPingWithTraceId(Long passedTraceId)
throws Exception {
return sendPingWithTraceId(Trace.TRACE_ID_NAME, passedTraceId);
return sendPingWithTraceId(Span.TRACE_ID_NAME, passedTraceId);
}
private MvcResult sendPingWithTraceId(String headerName, Long passedCorrelationId)
throws Exception {
return this.mockMvc
.perform(MockMvcRequestBuilders.get("/ping").accept(MediaType.TEXT_PLAIN)
.header(headerName, Span.IdConverter.toHex(passedCorrelationId))
.header(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(new Random().nextLong())))
.header(headerName, Span.toHex(passedCorrelationId))
.header(Span.SPAN_ID_NAME, Span.toHex(new Random().nextLong())))
.andReturn();
}
private Long tracingHeaderFrom(MvcResult mvcResult) {
return Span.IdConverter.fromHex(mvcResult.getResponse().getHeader(Trace.TRACE_ID_NAME));
return Span.fromHex(mvcResult.getResponse().getHeader(Span.TRACE_ID_NAME));
}
}

View File

@@ -16,19 +16,15 @@
package org.springframework.cloud.sleuth.instrument.web;
import static org.junit.Assert.assertNull;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import java.util.Random;
import lombok.SneakyThrows;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockFilterChain;
@@ -37,7 +33,10 @@ import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import lombok.SneakyThrows;
import java.util.Random;
import static org.junit.Assert.assertNull;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
/**
* @author Spencer Gibb
@@ -58,7 +57,7 @@ public class TraceFilterMockChainIntegrationTests {
@Before
@SneakyThrows
public void init() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
this.context.refresh();
this.request = builder().buildRequest(new MockServletContext());
this.response = new MockHttpServletResponse();
@@ -75,17 +74,17 @@ public class TraceFilterMockChainIntegrationTests {
public void startsNewTrace() throws Exception {
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
filter.doFilter(this.request, this.response, this.filterChain);
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
public void continuesSpanFromHeaders() throws Exception {
Random generator = new Random();
this.request = builder().header(Trace.SPAN_ID_NAME, generator.nextLong())
.header(Trace.TRACE_ID_NAME, generator.nextLong()).buildRequest(new MockServletContext());
this.request = builder().header(Span.SPAN_ID_NAME, generator.nextLong())
.header(Span.TRACE_ID_NAME, generator.nextLong()).buildRequest(new MockServletContext());
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
filter.doFilter(this.request, this.response, this.filterChain);
assertNull(TraceContextHolder.getCurrentSpan());
assertNull(SpanContextHolder.getCurrentSpan());
}
}

View File

@@ -16,28 +16,18 @@
package org.springframework.cloud.sleuth.instrument.web;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import java.util.Random;
import lombok.SneakyThrows;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.sampler.IsTracingSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -47,7 +37,15 @@ import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import lombok.SneakyThrows;
import java.util.Random;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
/**
* @author Spencer Gibb
@@ -65,7 +63,7 @@ public class TraceFilterTests {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MockFilterChain filterChain;
private Sampler<Void> sampler = new AlwaysSampler();
private Sampler sampler = new AlwaysSampler();
@Before
@SneakyThrows
@@ -74,9 +72,9 @@ public class TraceFilterTests {
this.tracer = new DefaultTracer(new DelegateSampler(), new Random(),
this.publisher) {
@Override
protected Trace createTrace(Trace trace, Span span) {
TraceFilterTests.this.span = span;
return super.createTrace(trace, span);
protected Span createSpan(Span saved, Span span) {
TraceFilterTests.this.span = super.createSpan(saved, span);
return TraceFilterTests.this.span;
}
};
this.request = builder().buildRequest(new MockServletContext());
@@ -101,7 +99,7 @@ public class TraceFilterTests {
filter.doFilter(this.request, this.response, this.filterChain);
assertFalse(this.span.isExportable());
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
@@ -109,40 +107,40 @@ public class TraceFilterTests {
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
filter.doFilter(this.request, this.response, this.filterChain);
verifyHttpTags();
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
public void continuesSpanInRequestAttr() throws Exception {
Trace trace = this.tracer.startTrace("foo");
this.request.setAttribute(TraceFilter.TRACE_REQUEST_ATTR, trace);
Span span = this.tracer.startTrace("foo");
this.request.setAttribute(TraceFilter.TRACE_REQUEST_ATTR, span);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
filter.doFilter(this.request, this.response, this.filterChain);
verifyHttpTags();
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
public void continuesSpanFromHeaders() throws Exception {
this.request = builder().header(Trace.SPAN_ID_NAME, 10L)
.header(Trace.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
this.request = builder().header(Span.SPAN_ID_NAME, 10L)
.header(Span.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
filter.doFilter(this.request, this.response, this.filterChain);
verifyHttpTags();
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
public void addsAdditionalHeaders() throws Exception {
this.request = builder().header(Trace.SPAN_ID_NAME, 10L)
.header(Trace.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
this.request = builder().header(Span.SPAN_ID_NAME, 10L)
.header(Span.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
this.traceKeys.getHttp().getHeaders().add("x-foo");
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
@@ -151,13 +149,13 @@ public class TraceFilterTests {
assertThat(this.span.tags()).contains(entry("http/x-foo", "bar"));
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
public void additionalMultiValuedHeader() throws Exception {
this.request = builder().header(Trace.SPAN_ID_NAME, 10L)
.header(Trace.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
this.request = builder().header(Span.SPAN_ID_NAME, 10L)
.header(Span.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
this.traceKeys.getHttp().getHeaders().add("x-foo");
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
@@ -167,7 +165,7 @@ public class TraceFilterTests {
assertThat(this.span.tags()).contains(entry("http/x-foo", "'bar','spam'"));
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
@Test
@@ -189,7 +187,7 @@ public class TraceFilterTests {
}
verifyHttpTags(HttpStatus.INTERNAL_SERVER_ERROR);
assertNull(TraceContextHolder.getCurrentTrace());
assertNull(SpanContextHolder.getCurrentSpan());
}
public void verifyHttpTags() {
@@ -216,7 +214,7 @@ public class TraceFilterTests {
}
}
private class DelegateSampler implements Sampler<Void> {
private class DelegateSampler implements Sampler {
@Override
public boolean next() {
return TraceFilterTests.this.sampler.next();

View File

@@ -1,12 +1,8 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -18,13 +14,11 @@ import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -38,9 +32,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { FeignTraceTests.TestConfiguration.class })
@@ -59,7 +56,7 @@ public class FeignTraceTests {
@After
public void close() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
this.listener.getEvents().clear();
}
@@ -69,7 +66,7 @@ public class FeignTraceTests {
ResponseEntity<String> response = this.testFeignInterface.getNoTrace();
// then
then(getHeader(response, Trace.TRACE_ID_NAME)).isNotNull();
then(getHeader(response, Span.TRACE_ID_NAME)).isNotNull();
then(this.listener.getEvents()).isNotEmpty();
}
@@ -78,14 +75,14 @@ public class FeignTraceTests {
// given
Long currentTraceId = 1L;
Long currentParentId = 2L;
this.tracer.continueSpan(MilliSpan.builder().traceId(currentTraceId)
this.tracer.continueSpan(Span.builder().traceId(currentTraceId)
.spanId(generatedId()).parent(currentParentId).build());
// when
ResponseEntity<String> response = this.testFeignInterface.getTraceId();
// then
then(Span.IdConverter.fromHex(getHeader(response, Trace.TRACE_ID_NAME))).isEqualTo(currentTraceId);
then(Span.fromHex(getHeader(response, Span.TRACE_ID_NAME))).isEqualTo(currentTraceId);
then(this.listener.getEvents().size()).isEqualTo(2);
}
@@ -148,15 +145,15 @@ public class FeignTraceTests {
@RequestMapping(value = "/notrace", method = RequestMethod.GET)
public String notrace(
@RequestHeader(name = Trace.TRACE_ID_NAME, required = false) String traceId) {
@RequestHeader(name = Span.TRACE_ID_NAME, required = false) String traceId) {
then(traceId).isNotNull();
return "OK";
}
@RequestMapping(value = "/traceid", method = RequestMethod.GET)
public String traceId(@RequestHeader(Trace.TRACE_ID_NAME) String traceId,
@RequestHeader(Trace.SPAN_ID_NAME) String spanId,
@RequestHeader(Trace.PARENT_ID_NAME) String parentId) {
public String traceId(@RequestHeader(Span.TRACE_ID_NAME) String traceId,
@RequestHeader(Span.SPAN_ID_NAME) String spanId,
@RequestHeader(Span.PARENT_ID_NAME) String parentId) {
then(traceId).isNotEmpty();
then(parentId).isNotEmpty();
then(spanId).isNotEmpty();

View File

@@ -16,22 +16,13 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertFalse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.ClientHttpRequestInterceptor;
@@ -43,6 +34,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertFalse;
/**
* @author Dave Syer
*
@@ -65,22 +64,22 @@ public class TraceRestTemplateInterceptorTests {
this.traces = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher);
this.template.setInterceptors(Arrays.<ClientHttpRequestInterceptor>asList(
new TraceRestTemplateInterceptor(this.traces)));
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@After
public void clean() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
public void headersAddedWhenTracing() {
this.traces.continueSpan(MilliSpan.builder().traceId(1L).spanId(2L).build());
this.traces.continueSpan(Span.builder().traceId(1L).spanId(2L).build());
@SuppressWarnings("unchecked")
Map<String, String> headers = this.template.getForEntity("/", Map.class)
.getBody();
then(Long.valueOf(headers.get(Trace.TRACE_ID_NAME))).isEqualTo(1L);
then(Long.valueOf(headers.get(Trace.SPAN_ID_NAME))).isEqualTo(2L);
then(Long.valueOf(headers.get(Span.TRACE_ID_NAME))).isEqualTo(1L);
then(Long.valueOf(headers.get(Span.SPAN_ID_NAME))).isEqualTo(2L);
}
@Test
@@ -88,7 +87,7 @@ public class TraceRestTemplateInterceptorTests {
@SuppressWarnings("unchecked")
Map<String, String> headers = this.template.getForEntity("/", Map.class)
.getBody();
assertFalse("Wrong headers: " + headers, headers.containsKey(Trace.SPAN_ID_NAME));
assertFalse("Wrong headers: " + headers, headers.containsKey(Span.SPAN_ID_NAME));
}
@RestController
@@ -96,8 +95,8 @@ public class TraceRestTemplateInterceptorTests {
@RequestMapping("/")
public Map<String, String> home(@RequestHeader HttpHeaders headers) {
Map<String, String> map = new HashMap<String, String>();
addHeaders(map, headers, Trace.SPAN_ID_NAME, Trace.TRACE_ID_NAME,
Trace.PARENT_ID_NAME);
addHeaders(map, headers, Span.SPAN_ID_NAME, Span.TRACE_ID_NAME,
Span.PARENT_ID_NAME);
return map;
}

View File

@@ -16,18 +16,19 @@
package org.springframework.cloud.sleuth.log;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.OutputCapture;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.util.StringUtils;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Spencer Gibb
*/
@@ -38,7 +39,7 @@ public class JsonLogSpanListenerTests {
@Test
public void jsonSpanIsOnOneLine() throws IOException {
JsonLogSpanListener listener = new JsonLogSpanListener();
Span span = MilliSpan.builder()
Span span = Span.builder()
.name("testSpan")
.spanId(1L)
.parent(2L)
@@ -61,7 +62,7 @@ public class JsonLogSpanListenerTests {
assertFalse("json contains linefeed", output.contains("\n"));
assertFalse("json contains carriage return", output.contains("\r"));
MilliSpan read = listener.getObjectMapper().readValue(json, MilliSpan.class);
Span read = listener.getObjectMapper().readValue(json, Span.class);
assertEquals("span not equals", read, span);
}
}

View File

@@ -1,15 +1,14 @@
package org.springframework.cloud.sleuth.sampler;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.data.Percentage.withPercentage;
import org.junit.Test;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TraceAccessor;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.data.Percentage.withPercentage;
public class PercentageBasedSamplerTests {
SamplerConfiguration samplerConfiguration = new SamplerConfiguration();
@@ -59,7 +58,7 @@ public class PercentageBasedSamplerTests {
return new TraceAccessor() {
@Override
public Span getCurrentSpan() {
return MilliSpan.builder().traceId(RANDOM.nextLong()).build();
return Span.builder().traceId(RANDOM.nextLong()).build();
}
@Override

View File

@@ -1,19 +1,19 @@
package org.springframework.cloud.sleuth.template;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.Random;
import org.junit.After;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
public class TraceTemplateTests {
Tracer tracer = new DefaultTracer(new AlwaysSampler(),
@@ -21,25 +21,25 @@ public class TraceTemplateTests {
@After
public void close() {
TraceContextHolder.removeCurrentTrace();
SpanContextHolder.removeCurrentSpan();
}
@Test
public void should_pass_trace_to_the_callback_if_tracing_is_active() {
Trace initialTrace = this.tracer.startTrace("test");
Span initialSpan = this.tracer.startTrace("test");
TraceTemplate traceTemplate = new TraceTemplate(this.tracer);
Trace traceFromCallback = whenTraceCallbackReturningCurrentTraceIsExecuted(traceTemplate);
Span spanFromCallback = whenTraceCallbackReturningCurrentTraceIsExecuted(traceTemplate);
then(traceFromCallback).isNotNull();
then(traceFromCallback.getSpan().getTraceId()).isEqualTo(initialTrace.getSpan().getTraceId());
then(spanFromCallback).isNotNull();
then(spanFromCallback.getTraceId()).isEqualTo(initialSpan.getTraceId());
}
private Trace whenTraceCallbackReturningCurrentTraceIsExecuted(TraceTemplate traceTemplate) {
return traceTemplate.trace(new TraceCallback<Trace>() {
private Span whenTraceCallbackReturningCurrentTraceIsExecuted(TraceTemplate traceTemplate) {
return traceTemplate.trace(new TraceCallback<Span>() {
@Override
public Trace doInTrace(Trace trace) {
return TraceContextHolder.getCurrentTrace();
public Span doInTrace(Span span) {
return SpanContextHolder.getCurrentSpan();
}
});
}

View File

@@ -49,7 +49,7 @@ public class SampleMessagingApplication {
private SampleRequestResponse transformer;
@Bean
public Sampler<?> defaultSampler() {
public Sampler defaultSampler() {
return new AlwaysSampler();
}

View File

@@ -39,7 +39,7 @@ import com.github.kristofa.brave.SpanCollector;
public class SampleRibbonApplication {
@Bean
public Sampler<?> defaultSampler() {
public Sampler defaultSampler() {
return new AlwaysSampler();
}

View File

@@ -21,7 +21,6 @@ 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.TraceAccessor;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
@@ -94,7 +93,7 @@ ApplicationListener<EmbeddedServletContainerInitializedEvent> {
@SneakyThrows
@RequestMapping("/traced")
public String traced() {
Trace trace = this.tracer.startTrace("customTraceEndpoint",
Span span = this.tracer.startTrace("customTraceEndpoint",
new AlwaysSampler());
int millis = random.nextInt(1000);
log.info("Sleeping for {} millis", millis);
@@ -103,7 +102,7 @@ ApplicationListener<EmbeddedServletContainerInitializedEvent> {
String s = this.restTemplate.getForObject("http://localhost:" + this.port
+ "/call", String.class);
this.tracer.close(trace);
this.tracer.close(span);
return "traced/" + s;
}

View File

@@ -35,7 +35,7 @@ public class SampleSleuthApplication {
public static final String CLIENT_NAME = "testApp";
@Bean
public Sampler<?> defaultSampler() {
public Sampler defaultSampler() {
return new AlwaysSampler();
}

View File

@@ -17,8 +17,11 @@ package tools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.http.*;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
@@ -53,7 +56,7 @@ public class RequestSendingRunnable implements Runnable {
private RequestEntity requestWithTraceId(long traceId) {
HttpHeaders headers = new HttpHeaders();
headers.add(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(traceId));
headers.add(Span.TRACE_ID_NAME, Span.toHex(traceId));
URI uri = URI.create(url);
RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, uri);
log.info("Request [" + requestEntity + "] is ready");

View File

@@ -24,7 +24,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.stream.Host;
import org.springframework.cloud.sleuth.stream.SleuthSink;
@@ -60,7 +59,7 @@ public class ZipkinStreamTests extends AbstractIntegrationTest {
await().until(zipkinServerIsUp());
long traceId = new Random().nextLong();
Span span = MilliSpan.builder().traceId(traceId).spanId(traceId).name("test")
Span span = Span.builder().traceId(traceId).spanId(traceId).name("test")
.build();
span.tag(getRequiredBinaryAnnotationName(), "10131");

View File

@@ -21,7 +21,6 @@ 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.TraceAccessor;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
@@ -94,7 +93,7 @@ ApplicationListener<EmbeddedServletContainerInitializedEvent> {
@SneakyThrows
@RequestMapping("/traced")
public String traced() {
Trace trace = this.tracer.startTrace("customTraceEndpoint",
Span span = this.tracer.startTrace("customTraceEndpoint",
new AlwaysSampler());
int millis = random.nextInt(1000);
log.info("Sleeping for {} millis", millis);
@@ -103,7 +102,7 @@ ApplicationListener<EmbeddedServletContainerInitializedEvent> {
String s = this.restTemplate.getForObject("http://localhost:" + this.port
+ "/call", String.class);
this.tracer.close(trace);
this.tracer.close(span);
return "traced/" + s;
}

View File

@@ -39,7 +39,7 @@ public class SampleZipkinApplication {
public static final String CLIENT_NAME = "testApp";
@Bean
public Sampler<?> defaultSampler() {
public Sampler defaultSampler() {
return new AlwaysSampler();
}

View File

@@ -21,7 +21,6 @@ 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.TraceAccessor;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
@@ -94,7 +93,7 @@ ApplicationListener<EmbeddedServletContainerInitializedEvent> {
@SneakyThrows
@RequestMapping("/traced")
public String traced() {
Trace trace = this.tracer.startTrace("customTraceEndpoint",
Span span = this.tracer.startTrace("customTraceEndpoint",
new AlwaysSampler());
int millis = random.nextInt(1000);
log.info("Sleeping for {} millis", millis);
@@ -103,7 +102,7 @@ ApplicationListener<EmbeddedServletContainerInitializedEvent> {
String s = this.restTemplate.getForObject("http://localhost:" + this.port
+ "/call", String.class);
this.tracer.close(trace);
this.tracer.close(span);
return "traced/" + s;
}

View File

@@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.config.ChannelBindingAutoConfiguration;
import org.springframework.context.annotation.Bean;
@@ -61,7 +61,7 @@ public class SleuthStreamAutoConfiguration {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
return MessageBuilder.fromMessage(message)
.setHeader(Trace.NOT_SAMPLED_NAME, "").build();
.setHeader(Span.NOT_SAMPLED_NAME, "").build();
}
};
}

View File

@@ -18,7 +18,7 @@ package org.springframework.cloud.sleuth.stream;
import org.junit.Test;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -27,7 +27,8 @@ import java.util.Collections;
import static org.assertj.core.api.Assertions.assertThat;
public class ServerPropertiesHostLocatorTests {
MilliSpan span = new MilliSpan(1, 3, "name", 1L, Collections.<Long>emptyList(), 2L, true, true, "process");
Span span = new Span(1, 3, "name", 1L, Collections.<Long>emptyList(), 2L, true, true,
"process");
@Test
public void portDefaultsTo8080() {

View File

@@ -16,22 +16,13 @@
package org.springframework.cloud.sleuth.stream;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
@@ -51,6 +42,12 @@ import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -78,30 +75,30 @@ public class StreamSpanListenerTests {
@Test
public void acquireAndRelease() {
Trace context = this.tracer.startTrace("foo");
Span context = this.tracer.startTrace("foo");
this.tracer.close(context);
assertEquals(1, this.test.spans.size());
}
@Test
public void rpcAnnotations() {
Span parent = MilliSpan.builder().traceId(1L).name("parent").remote(true)
Span parent = Span.builder().traceId(1L).name("parent").remote(true)
.build();
Trace context = this.tracer.joinTrace("child", parent);
this.application.publishEvent(new ClientSentEvent(this, context.getSpan()));
Span context = this.tracer.joinTrace("child", parent);
this.application.publishEvent(new ClientSentEvent(this, context));
this.application
.publishEvent(new ServerReceivedEvent(this, parent, context.getSpan()));
.publishEvent(new ServerReceivedEvent(this, parent, context));
this.application
.publishEvent(new ServerSentEvent(this, parent, context.getSpan()));
this.application.publishEvent(new ClientReceivedEvent(this, context.getSpan()));
.publishEvent(new ServerSentEvent(this, parent, context));
this.application.publishEvent(new ClientReceivedEvent(this, context));
this.tracer.close(context);
assertEquals(2, this.test.spans.size());
}
@Test
public void nullSpanName() {
Trace context = this.tracer.startTrace(null, (Sampler) null);
this.application.publishEvent(new ClientSentEvent(this, context.getSpan()));
Span context = this.tracer.startTrace(null, null);
this.application.publishEvent(new ClientSentEvent(this, context));
this.tracer.close(context);
assertEquals(1, this.test.spans.size());
this.listener.poll();
@@ -129,7 +126,7 @@ public class StreamSpanListenerTests {
}
@Bean
public Sampler<?> defaultSampler() {
public Sampler defaultSampler() {
return new AlwaysSampler();
}

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.sleuth.zipkin.stream;
import org.junit.Test;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.stream.Host;
import org.springframework.cloud.sleuth.stream.Spans;
@@ -36,7 +35,7 @@ public class SamplingZipkinSpanIteratorTests {
@Test
public void skipsInputSpans() {
Spans spans = new Spans(host, Arrays.asList(span("message/sleuth")));
Spans spans = new Spans(host, Collections.singletonList(span("message/sleuth")));
Iterator<zipkin.Span> result = new SamplingZipkinSpanIterator(Sampler.create(1.0f), spans);
@@ -71,6 +70,7 @@ public class SamplingZipkinSpanIteratorTests {
Span span(String name) {
Long id = new Random().nextLong();
return new MilliSpan(1, 3, name, id, Collections.<Long>emptyList(), id, true, true, "process");
return new Span(1, 3, name, id, Collections.<Long>emptyList(), id, true, true,
"process");
}
}

View File

@@ -21,13 +21,14 @@ import zipkin.BinaryAnnotation;
import zipkin.Endpoint;
import org.junit.Test;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.stream.Host;
import static org.assertj.core.api.Assertions.assertThat;
public class ZipkinMessageListenerTests {
MilliSpan span = new MilliSpan(1, 3, "name", 1L, Collections.<Long>emptyList(), 2L, true, true, "process");
Span span = new Span(1, 3, "name", 1L, Collections.<Long>emptyList(), 2L, true, true,
"process");
Host host = new Host("myservice", "1.2.3.4", 8080);
Endpoint endpoint = Endpoint.create("myservice", 1 << 24 | 2 << 16 | 3 << 8 | 4, 8080);
@@ -79,7 +80,7 @@ public class ZipkinMessageListenerTests {
// TODO: "unknown" bc process id, documented as not nullable, is null in some tests.
@Test
public void nullProcessIdCoercesToUnknownServiceName() {
MilliSpan noProcessId = MilliSpan.builder().traceId(1L).name("parent").remote(true).build();
Span noProcessId = Span.builder().traceId(1L).name("parent").remote(true).build();
zipkin.Span result = ZipkinMessageListener.convert(noProcessId, host);

View File

@@ -16,23 +16,13 @@
package org.springframework.cloud.sleuth.zipkin;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
@@ -47,6 +37,13 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -72,7 +69,7 @@ public class ZipkinSpanListenerTests {
this.test.spans.clear();
}
Span parent = MilliSpan.builder().traceId(1L).name("parent").remote(true).build();
Span parent = Span.builder().traceId(1L).name("parent").remote(true).build();
/** Sleuth timestamps are millisecond granularity while zipkin is microsecond. */
@Test
@@ -119,7 +116,7 @@ public class ZipkinSpanListenerTests {
*/
@Test
public void spanWithoutAnnotationsLogsComponent() {
Trace context = this.tracer.startTrace("foo");
Span context = this.tracer.startTrace("foo");
this.tracer.close(context);
assertEquals(1, this.test.spans.size());
assertThat(this.test.spans.get(0).binaryAnnotations.get(0).endpoint.serviceName)
@@ -128,11 +125,11 @@ public class ZipkinSpanListenerTests {
@Test
public void rpcAnnotations() {
Trace context = this.tracer.joinTrace("child", parent);
this.application.publishEvent(new ClientSentEvent(this, context.getSpan()));
this.application.publishEvent(new ServerReceivedEvent(this, parent, context.getSpan()));
this.application.publishEvent(new ServerSentEvent(this, parent, context.getSpan()));
this.application.publishEvent(new ClientReceivedEvent(this, context.getSpan()));
Span context = this.tracer.joinTrace("child", parent);
this.application.publishEvent(new ClientSentEvent(this, context));
this.application.publishEvent(new ServerReceivedEvent(this, parent, context));
this.application.publishEvent(new ServerSentEvent(this, parent, context));
this.application.publishEvent(new ClientReceivedEvent(this, context));
this.tracer.close(context);
assertEquals(2, this.test.spans.size());
}
@@ -149,7 +146,7 @@ public class ZipkinSpanListenerTests {
private List<zipkin.Span> spans = new ArrayList<>();
@Bean
public Sampler<?> defaultSampler() {
public Sampler defaultSampler() {
return new AlwaysSampler();
}