-
Notifications
You must be signed in to change notification settings - Fork 714
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP TraceContext propagation handler
- Loading branch information
Adrian Cole
committed
Mar 12, 2020
1 parent
0dc3752
commit 1bf1465
Showing
12 changed files
with
697 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
Copyright 2013-2020 The OpenZipkin 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. | ||
--> | ||
<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> | ||
|
||
<parent> | ||
<groupId>io.zipkin.brave</groupId> | ||
<artifactId>brave-parent</artifactId> | ||
<version>5.10.2-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>brave-propagation-parent</artifactId> | ||
<name>Brave: Trace Propagation Formats</name> | ||
<packaging>pom</packaging> | ||
|
||
<properties> | ||
<main.basedir>${project.basedir}/..</main.basedir> | ||
</properties> | ||
|
||
<modules> | ||
<module>w3c</module> | ||
</modules> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>${project.groupId}</groupId> | ||
<artifactId>brave</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>${project.groupId}</groupId> | ||
<artifactId>brave-tests</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# brave-propagation-w3c | ||
|
||
This project includes propagation handlers for W3C defined headers. | ||
|
||
## Trace Context | ||
The [Trace Context][https://w3c.github.io/trace-context/] specification defines two headers: | ||
|
||
* `traceparent` - almost the same as our [B3-single format](https://github.com/openzipkin/b3-propagation#single-header) | ||
* `tracestate` - vendor-specific (or format-specific): may impact how to interpret `traceparent` | ||
|
||
This implementation can survive mixed systems who follow the specification and forward the | ||
`tracestate` header. When writing the `traceparent` header, this also overwrites the `tracestate` | ||
entry named 'b3' (in B3 single format). When reading headers, this entry is favored over the | ||
`traceparent`, allowing the the next span to re-attach to the last known 'b3' header. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
Copyright 2013-2020 The OpenZipkin 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. | ||
--> | ||
<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"> | ||
<parent> | ||
<groupId>io.zipkin.brave</groupId> | ||
<artifactId>brave-propagation-parent</artifactId> | ||
<version>5.10.2-SNAPSHOT</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>brave-propagation-w3c</artifactId> | ||
<name>Brave Propagation: W3C Tracing headers (traceparent, tracestate, etc.)</name> | ||
|
||
<properties> | ||
<main.basedir>${project.basedir}/../..</main.basedir> | ||
<main.java.version>1.6</main.java.version> | ||
<main.signature.artifact>java16</main.signature.artifact> | ||
</properties> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<configuration> | ||
<archive> | ||
<manifestEntries> | ||
<Automatic-Module-Name>brave.propagation.w3c</Automatic-Module-Name> | ||
</manifestEntries> | ||
</archive> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
85 changes: 85 additions & 0 deletions
85
propagation/w3c/src/main/java/brave/propagation/w3c/TraceContextExtractor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* Copyright 2013-2020 The OpenZipkin 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 brave.propagation.w3c; | ||
|
||
import brave.propagation.Propagation.Getter; | ||
import brave.propagation.SamplingFlags; | ||
import brave.propagation.TraceContext; | ||
import brave.propagation.TraceContext.Extractor; | ||
import brave.propagation.TraceContextOrSamplingFlags; | ||
import brave.propagation.w3c.TraceContextPropagation.Extra; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import static brave.propagation.w3c.TraceparentFormat.FORMAT_LENGTH; | ||
import static brave.propagation.w3c.TraceparentFormat.maybeExtractParent; | ||
import static brave.propagation.w3c.TraceparentFormat.validateFormat; | ||
|
||
final class TraceContextExtractor<C, K> implements Extractor<C> { | ||
final Getter<C, K> getter; | ||
final K tracestateKey; | ||
final TracestateFormat tracestateFormat; | ||
|
||
TraceContextExtractor(TraceContextPropagation<K> propagation, Getter<C, K> getter) { | ||
this.getter = getter; | ||
this.tracestateKey = propagation.tracestateKey; | ||
this.tracestateFormat = new TracestateFormat(propagation.stateName); | ||
} | ||
|
||
@Override public TraceContextOrSamplingFlags extract(C carrier) { | ||
if (carrier == null) throw new NullPointerException("carrier == null"); | ||
String tracestateString = getter.get(carrier, tracestateKey); | ||
if (tracestateString == null) return EMPTY; | ||
|
||
TraceparentFormatHandler handler = new TraceparentFormatHandler(); | ||
CharSequence otherState = tracestateFormat.parseAndReturnOtherState(tracestateString, handler); | ||
|
||
List<Object> extra; | ||
if (otherState == null) { | ||
extra = DEFAULT_EXTRA; | ||
} else { | ||
Extra e = new Extra(); | ||
e.otherState = otherState; | ||
extra = Collections.singletonList(e); | ||
} | ||
|
||
if (handler.context == null) { | ||
if (extra == DEFAULT_EXTRA) return EMPTY; | ||
return TraceContextOrSamplingFlags.newBuilder() | ||
.extra(extra) | ||
.samplingFlags(SamplingFlags.EMPTY) | ||
.build(); | ||
} | ||
return TraceContextOrSamplingFlags.newBuilder().context(handler.context).extra(extra).build(); | ||
} | ||
|
||
static final class TraceparentFormatHandler implements TracestateFormat.Handler { | ||
TraceContext context; | ||
|
||
@Override public boolean onThisState(CharSequence tracestateString, int pos) { | ||
if (validateFormat(tracestateString, pos) < FORMAT_LENGTH) { | ||
return false; | ||
} | ||
context = maybeExtractParent(tracestateString, pos); | ||
return true; | ||
} | ||
} | ||
|
||
/** When present, this context was created with TracestatePropagation */ | ||
static final Extra MARKER = new Extra(); | ||
|
||
static final List<Object> DEFAULT_EXTRA = Collections.singletonList(MARKER); | ||
static final TraceContextOrSamplingFlags EMPTY = | ||
TraceContextOrSamplingFlags.EMPTY.toBuilder().extra(DEFAULT_EXTRA).build(); | ||
} |
51 changes: 51 additions & 0 deletions
51
propagation/w3c/src/main/java/brave/propagation/w3c/TraceContextInjector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright 2013-2020 The OpenZipkin 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 brave.propagation.w3c; | ||
|
||
import brave.propagation.Propagation.Setter; | ||
import brave.propagation.TraceContext; | ||
import brave.propagation.TraceContext.Injector; | ||
import brave.propagation.w3c.TraceContextPropagation.Extra; | ||
|
||
import static brave.propagation.w3c.TraceparentFormat.writeTraceparentFormat; | ||
|
||
final class TraceContextInjector<C, K> implements Injector<C> { | ||
final TracestateFormat tracestateFormat; | ||
final Setter<C, K> setter; | ||
final K traceparentKey, tracestateKey; | ||
|
||
TraceContextInjector(TraceContextPropagation<K> propagation, Setter<C, K> setter) { | ||
this.tracestateFormat = new TracestateFormat(propagation.stateName); | ||
this.traceparentKey = propagation.traceparentKey; | ||
this.tracestateKey = propagation.tracestateKey; | ||
this.setter = setter; | ||
} | ||
|
||
@Override public void inject(TraceContext traceContext, C carrier) { | ||
String thisState = writeTraceparentFormat(traceContext); | ||
setter.put(carrier, traceparentKey, thisState); | ||
|
||
CharSequence otherState = null; | ||
for (int i = 0, length = traceContext.extra().size(); i < length; i++) { | ||
Object next = traceContext.extra().get(i); | ||
if (next instanceof Extra) { | ||
otherState = ((Extra) next).otherState; | ||
break; | ||
} | ||
} | ||
|
||
String tracestate = tracestateFormat.write(thisState, otherState); | ||
setter.put(carrier, tracestateKey, tracestate); | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
propagation/w3c/src/main/java/brave/propagation/w3c/TraceContextPropagation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright 2013-2020 The OpenZipkin 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 brave.propagation.w3c; | ||
|
||
import brave.propagation.Propagation; | ||
import brave.propagation.TraceContext; | ||
import brave.propagation.TraceContext.Extractor; | ||
import brave.propagation.TraceContext.Injector; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public final class TraceContextPropagation<K> implements Propagation<K> { | ||
// TODO: not sure if we will want a constant here, or something like a builder. For example, we | ||
// probably will need a primary state handler (ex b3) to catch data no longer in the traceparent | ||
// format. At any rate, we will need to know what state is primarily ours, so that probably means | ||
// not having a constant, unless that constant uses b3 single impl for the tracestate entry. | ||
public static final Propagation.Factory FACTORY = | ||
new Propagation.Factory() { | ||
@Override public <K> Propagation<K> create(KeyFactory<K> keyFactory) { | ||
return new TraceContextPropagation<>(keyFactory); | ||
} | ||
|
||
/** | ||
* Traceparent doesn't support sharing the same span ID, though it may be possible to support | ||
* this by extending it with a b3 state entry. | ||
*/ | ||
@Override public boolean supportsJoin() { | ||
return false; | ||
} | ||
|
||
@Override public TraceContext decorate(TraceContext context) { | ||
// TODO: almost certain we will need to decorate as not all contexts will start with an | ||
// incoming request (ex schedule or client-originated traces) | ||
return super.decorate(context); | ||
} | ||
|
||
@Override public boolean requires128BitTraceId() { | ||
return true; | ||
} | ||
|
||
@Override public String toString() { | ||
return "TracestatePropagationFactory"; | ||
} | ||
}; | ||
|
||
final String stateName; | ||
final K traceparentKey, tracestateKey; | ||
final List<K> fields; | ||
|
||
TraceContextPropagation(KeyFactory<K> keyFactory) { | ||
this.stateName = "b3"; | ||
this.traceparentKey = keyFactory.create("traceparent"); | ||
this.tracestateKey = keyFactory.create("tracestate"); | ||
this.fields = Arrays.asList(traceparentKey, tracestateKey); | ||
} | ||
|
||
@Override public List<K> keys() { | ||
return fields; | ||
} | ||
|
||
@Override public <C> Injector<C> injector(Setter<C, K> setter) { | ||
if (setter == null) throw new NullPointerException("setter == null"); | ||
return new TraceContextInjector<>(this, setter); | ||
} | ||
|
||
@Override public <C> Extractor<C> extractor(Getter<C, K> getter) { | ||
if (getter == null) throw new NullPointerException("getter == null"); | ||
return new TraceContextExtractor<>(this, getter); | ||
} | ||
|
||
// TODO: this probably needs to carry more state than the upstream at some point, eventhough we | ||
// can start with pass-through integration. | ||
static final class Extra { // hidden intentionally | ||
CharSequence otherState; | ||
|
||
@Override public String toString() { | ||
return "TracestatePropagation{" | ||
+ (otherState != null ? ("fields=" + otherState.toString()) : "") | ||
+ "}"; | ||
} | ||
} | ||
} |
Oops, something went wrong.