Commit 65fde953 authored by Jonathan Mace's avatar Jonathan Mace

Fold transitlayer into the baggagecontext package

parent 8302259f
.classpath
.settings
.project
bin
target
xtrace-data
application.conf
\ No newline at end of file
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer-api</artifactId>
<packaging>jar</packaging>
<name>Transit Layer - API</name>
<parent>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>baggagecontext-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>
package brown.tracingplane;
import java.nio.ByteBuffer;
/**
* <p>
* A {@link TransitLayer} implementation is responsible for maintaining {@link BaggageContext} instances while
* executions run. The TransitLayer has the notion of an "active" context which represents the {@link BaggageContext}
* for the current execution. Implicitly, if the current execution has no {@link BaggageContext}, it is the same as
* having an empty context.
* </p>
*
* <p>
* A {@link TransitLayer} implementation typically maintains the active {@link BaggageContext} using thread-local
* storage. The purpose of this interface is to enable other implementations to plug in to existing instrumentation.
* </p>
*
* <p>
* {@link TransitLayer} also provides methods that mirror those of {@link BaggageProvider}, such as {@link #branch()}
* which corresponds to {@link BaggageProvider#branch(BaggageContext)}. These methods simply proxy the
* {@link BaggageProvider} method, passing the currently active {@link BaggageContext}.
* </p>
*
* <p>
* All {@link TransitLayer} implementations must have a one-argument constructor that receives the
* {@link BaggageProvider} to use.
* </p>
*/
public interface TransitLayer {
/**
* Discard the currently active {@link BaggageContext}.
*/
public void discard();
/**
* Create and return a branched copy of the currently active baggage context. Typically, this will just duplicate
* the active context or increment a reference count. Sometimes it will create a new instance, or even modify the
* contents of the branched context.
*
* @return a baggage instance branched from the currently active context, possibly null
*/
public BaggageContext branch();
/**
* Create and return a branched, serialized copy of the currently active baggage context. Typically, this will just
* duplicate the active context or increment a reference count. Sometimes it will create a new instance, or even
* modify the contents of the branched context.
*
* @return a baggage instance branched from the currently active context and serialized, possibly null
*/
public byte[] branchBytes();
/**
* Merges the contents of <code>otherContext</code> into the currently active context. <code>otherContext</code>
* should not be reused after calling this method, and should be treated as discarded.
*
* @param otherContext another baggage context, possibly null
*/
public void join(BaggageContext otherContext);
/**
* Deserializes the provided context and merges it into the currently active context.
*
* @param serializedContext a serialized baggage context, possibly null
*/
public void join(ByteBuffer serializedContext);
/**
* Deserializes the provided context and merges it into the currently active context.
*
* @param serializedContext a serialized baggage context, possibly null
*/
public void join(byte[] serialized, int offset, int length);
/**
* Discards the currently active {@link BaggageContext}, then activates the provided <code>baggage</code>. If
* <code>baggage</code> is just a modified version of the currently active BaggageContext, then it is better to use
* the {@link #update(BaggageContext)} method instead.
*
* @param baggage The new baggage context to activate.
*/
public void set(BaggageContext baggage);
/**
* Deserializes the provided context, discards any currently active context, and replaces it with the deserialized
* context.
*
* @param serializedContext a serialized baggage context, possibly null
*/
public void set(ByteBuffer serializedContext);
/**
* Deserializes the provided context and merges it into the currently active context.
*
* @param serialized a serialized baggage context, possibly null
* @param offset offset into the byte array
* @param length length of serialized bytes
*/
public void set(byte[] serialized, int offset, int length);
/**
* Gets and removes the currently active {@link BaggageContext}. After calling this method, there will be no active
* {@link BaggageContext}.
*
* @return the current {@link BaggageContext}.
*/
public BaggageContext take();
/**
* Gets, removes, and serializes the currently active {@link BaggageContext}. After calling this method, there will
* be no active {@link BaggageContext}.
*
* @return the current {@link BaggageContext}.
*/
public byte[] takeBytes();
/**
* Gets the currently active {@link BaggageContext}. The {@link BaggageContext} instance remains active after
* calling this method. Use {@link #take()} to if you wish to get and remove the currently active context.
*
* @return the active {@link BaggageContext}
*/
public BaggageContext peek();
/**
* Sets the currently active {@link BaggageContext}. A call to this method implies that the provided
* <code>context</code> argument is an updated version of the active context. Conversely, if you intend to replace
* the currently active context (e.g., because a different execution is beginning), use the
* {@link #set(BaggageContext)} method.
*
* @param context an updated version of the currently active baggage context.
*/
public void update(BaggageContext baggage);
}
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer</artifactId>
<packaging>pom</packaging>
<name>Transit Layer</name>
<modules>
<module>api</module>
<module>staticapi</module>
<module>tls-impl</module>
</modules>
<parent>
<groupId>brown.tracingplane</groupId>
<artifactId>tracingplane-project</artifactId>
<version>1.0</version>
</parent>
</project>
.classpath
.settings
.project
bin
target
xtrace-data
application.conf
\ No newline at end of file
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer-staticapi</artifactId>
<packaging>jar</packaging>
<name>Transit Layer - Static API</name>
<parent>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>baggagecontext-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer-impl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>baggagecontext-staticapi</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>
package brown.tracingplane;
import java.nio.ByteBuffer;
/**
* <p>
* {@link ActiveBaggage} provides static methods that mirror the methods implemented by {@link BaggageProvider} and
* {@link TransitLayer}. Unlike the {@link brown.tracingplane.Baggage} interface, {@link ActiveBaggage} implicitly
* accesses the currently-active {@link BaggageContext} that is being managed by the {@link TransitLayer}. Unless it has
* been configured otherwise, this entails looking up the {@link BaggageContext} in thread-local storage.
* </p>
*
* <p>
* This class also provides static methods to get and set the currently active baggage. These methods proxy to the
* configured {@link TransitLayer}, which is responsible for maintaining active baggage (e.g., in thread-local storage).
* </p>
*
* <p>
* If you wish to manipulate {@link BaggageContext} instances without affecting the currently active baggage context,
* use the static methods on the {@link brown.tracingplane.Baggage} class.
* </p>
*
* <p>
* Using this class requires that a {@link BaggageProvider} has been registered (e.g., using the
* <code>baggage.provider</code> property). By default, the {@link TransitLayer} used will be
* {@link ThreadLocalTransitLayer}; this can be overridden using <code>baggage.transit</code>.
* </p>
*
*/
public class ActiveBaggage {
private static final TransitLayer transit = DefaultTransitLayer.get();
/** Not instantiable */
private ActiveBaggage() {}
/**
* Discard the currently active {@link BaggageContext}.
*/
public static void discard() {
transit.discard();
}
/**
* Create and return a branched copy of the currently active baggage context. Typically, this will just duplicate
* the active context or increment a reference count. Sometimes it will create a new instance, or even modify the
* contents of the branched context.
*
* @return a baggage instance branched from the currently active context, possibly null
*/
public static BaggageContext branch() {
return transit.branch();
}
/**
* Create and return a branched, serialized copy of the currently active baggage context. Typically, this will just
* duplicate the active context or increment a reference count. Sometimes it will create a new instance, or even
* modify the contents of the branched context.
*
* @return a baggage instance branched from the currently active context and serialized, possibly null
*/
public static byte[] branchBytes() {
return transit.branchBytes();
}
/**
* Merges the contents of <code>otherContext</code> into the currently active context. <code>otherContext</code>
* should not be reused after calling this method, and should be treated as discarded.
*
* @param otherContext another baggage context, possibly null
*/
public static void join(BaggageContext otherContext) {
transit.join(otherContext);
}
/**
* Deserializes the provided context and merges it into the currently active context.
*
* @param serializedContext a serialized baggage context, possibly null
*/
public static void join(ByteBuffer serializedContext) {
transit.join(serializedContext);
}
/**
* Deserializes the provided context and merges it into the currently active context.
*
* @param serializedContext a serialized baggage context, possibly null
*/
public static void join(byte[] serialized, int offset, int length) {
transit.join(serialized, offset, length);
}
/**
* Discards the currently active {@link BaggageContext}, then activates the provided <code>baggage</code>. If
* <code>baggage</code> is just a modified version of the currently active BaggageContext, then it is better to use
* the {@link #update(BaggageContext)} method instead.
*
* @param baggage The new baggage context to activate.
*/
public static void set(BaggageContext baggage) {
transit.set(baggage);
}
/**
* Deserializes the provided context, discards any currently active context, and replaces it with the deserialized
* context.
*
* @param serializedContext a serialized baggage context, possibly null
*/
public static void set(ByteBuffer serializedContext) {
transit.set(serializedContext);
}
/**
* Deserializes the provided context and merges it into the currently active context.
*
* @param serialized a serialized baggage context, possibly null
* @param offset offset into the byte array
* @param length length of serialized bytes
*/
public static void set(byte[] serialized, int offset, int length) {
transit.set(serialized, offset, length);
}
/**
* Gets and removes the currently active {@link BaggageContext}. After calling this method, there will be no active
* {@link BaggageContext}.
*
* @return the current {@link BaggageContext}.
*/
public static BaggageContext take() {
return transit.take();
}
/**
* Gets, removes, and serializes the currently active {@link BaggageContext}. After calling this method, there will
* be no active {@link BaggageContext}.
*
* @return the current {@link BaggageContext}.
*/
public static byte[] takeBytes() {
return transit.takeBytes();
}
/**
* Gets the currently active {@link BaggageContext}. The {@link BaggageContext} instance remains active after
* calling this method. Use {@link #take()} to if you wish to get and remove the currently active context.
*
* @return the active {@link BaggageContext}
*/
public static BaggageContext peek() {
return transit.peek();
}
/**
* Sets the currently active {@link BaggageContext}. A call to this method implies that the provided
* <code>context</code> argument is an updated version of the active context. Conversely, if you intend to replace
* the currently active context (e.g., because a different execution is beginning), use the
* {@link #set(BaggageContext)} method.
*
* @param context an updated version of the currently active baggage context.
*/
public static void update(BaggageContext baggage) {
transit.update(baggage);
}
}
package brown.tracingplane;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.typesafe.config.ConfigException;
import com.typesafe.config.ConfigFactory;
/**
* <p>
* Loads the default configured {@link TransitLayer} using reflection. Checks the <code>baggage.transit</code> property.
* If <code>baggage.transit</code> is not set, then the default transit layer will be {@link ThreadLocalTransitLayer}.
* </p>
*/
public class DefaultTransitLayer {
private static final Logger log = LoggerFactory.getLogger(DefaultTransitLayer.class);
/** Not instantiable */
private DefaultTransitLayer() {}
private static boolean initialized = false;
private static TransitLayer instance = null;
private static synchronized void initialize() {
if (initialized) {
return;
}
BaggageProvider<BaggageContext> provider = DefaultBaggageProvider.getWrapped();
try {
String providerClass = ConfigFactory.load().getString("baggage.transit");
try {
Constructor<?> constructor = Class.forName(providerClass).getDeclaredConstructor(BaggageProvider.class);
instance = (TransitLayer) constructor.newInstance(provider);
} catch (NoSuchMethodException | SecurityException | ClassNotFoundException | InstantiationException
| IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
log.error("Unable to instantiate baggage.transit " + providerClass, e);
}
} catch (ConfigException.Missing e) {
log.error("No baggage.transit has been configured");
} catch (ConfigException.WrongType e) {
log.error("Invalid value (expected a string) for baggage.transit " +
ConfigFactory.load().getAnyRef("baggage.transit"));
} finally {
initialized = true;
if (instance == null) {
instance = new ThreadLocalTransitLayer(provider);
}
log.info("Transit Layer initialied to " + instance.getClass().getName());
}
}
/**
* @return the configured {@link TransitLayer} instance. The default transit layer can be set using
* -Dbaggage.transit. If no instance has been configured, this method will return a
* {@link ThreadLocalTransitLayer} that uses simple thread-local storage to store baggage contexts.
*/
public static TransitLayer get() {
if (!initialized) {
initialize();
}
return instance;
}
}
.classpath
.settings
.project
bin
target
xtrace-data
application.conf
\ No newline at end of file
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer-impl</artifactId>
<packaging>jar</packaging>
<name>Transit Layer - Thread-Local Impl</name>
<parent>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>transitlayer-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>
package brown.tracingplane;
import java.nio.ByteBuffer;
/**
* <p>
* A straightforward {@link TransitLayer} implementation based on thread-local storage.
* </p>
*/
public class ThreadLocalTransitLayer implements TransitLayer {
private final BaggageProvider<BaggageContext> provider;
private final ThreadLocal<BaggageContext> current = new ThreadLocal<BaggageContext>();
/**
* @param provider the implementation of {@link BaggageProvider} in use by this transit layer
*/
public ThreadLocalTransitLayer(BaggageProvider<BaggageContext> provider) {
this.provider = provider;
}
@Override
public void discard() {
current.remove();
}
@Override
public BaggageContext branch() {
return provider.branch(current.get());
}
@Override
public byte[] branchBytes() {
return provider.serialize(provider.branch(current.get()));
}
@Override
public void join(BaggageContext otherContext) {
current.set(provider.join(current.get(), otherContext));
}
@Override
public void join(ByteBuffer serializedContext) {
current.set(provider.join(current.get(), provider.deserialize(serializedContext)));
}
@Override
public void join(byte[] serialized, int offset, int length) {
current.set(provider.join(current.get(), provider.deserialize(serialized, offset, length)));
}
@Override
public void set(BaggageContext baggage) {
current.set(baggage);
}
@Override
public void set(ByteBuffer serializedContext) {
current.set(provider.deserialize(serializedContext));
}
@Override
public void set(byte[] serialized, int offset, int length) {
current.set(provider.deserialize(serialized, offset, length));
}
@Override
public BaggageContext take() {
try {
return current.get();
} finally {
current.remove();
}
}
@Override
public byte[] takeBytes() {
try {
return provider.serialize(current.get());
} finally {
current.remove();
}
}
@Override
public BaggageContext peek() {
return current.get();
}
@Override
public void update(BaggageContext baggage) {
current.set(baggage);
}
}
Markdown is supported
0% or