package rocks.inspectit.agent.java.sdk.opentracing.internal.impl; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import io.opentracing.SpanContext; import rocks.inspectit.agent.java.sdk.opentracing.internal.util.RandomUtils; /** * Implementation of the {@link io.opentracing.SpanContext}. Keeps information about span id, trace * id and span parent id. Sampling flag is not included in the moment as it's not explicitly defined * by the opentracing API. * * @author Ivan Senic * */ public class SpanContextImpl implements SpanContext { /** * Span id. */ private final long id; /** * Trace id. */ private final long traceId; /** * Parent span id. */ private final long parentId; /** * Reference type to the parent context. */ private final String referenceType; /** * Baggage. */ private final Map<String, String> baggage; /** * Constructor. Use build methods. * * @param id * Unique ID of the span. * @param traceId * ID of the trace that span belongs to. * @param parentId * ID of the span's parent. * @param referenceType * Reference to the parent. * @param baggage * Additional baggage */ public SpanContextImpl(long id, long traceId, long parentId, String referenceType, Map<String, String> baggage) { // ids this.id = id; this.traceId = traceId; this.parentId = parentId; this.referenceType = referenceType; // baggage handling if ((null != baggage) && !baggage.isEmpty()) { this.baggage = new HashMap<String, String>(baggage); } else { this.baggage = new HashMap<String, String>(0, 1f); } } /** * Builds new {@link SpanContextImpl} as a child of given parent context. If parent context is * <code>null</code> then {@link #build(Map)} will be used and new trace context will be * created. * <p> * Passed baggage will be the baggage of this span context. * * @param parent * Context that will be use to determine to which trace/parent new context belongs. * Can be <code>null</code> to denote that the new trace context should be created. * @param referenceType * Reference type to the parent context. * @param baggage * Context baggage. * @return {@link SpanContextImpl}. Never <code>null</code>. */ public static SpanContextImpl build(SpanContextImpl parent, String referenceType, Map<String, String> baggage) { if (null == parent) { return build(baggage); } else { long id = RandomUtils.randomLong(); SpanContextImpl spanContextImpl = new SpanContextImpl(id, parent.getTraceId(), parent.getId(), referenceType, baggage); return spanContextImpl; } } /** * Builds new {@link SpanContextImpl} with new trace context and given baggage. * * @param baggage * Context baggage. * @return {@link SpanContextImpl}. Never <code>null</code>. */ public static SpanContextImpl build(Map<String, String> baggage) { long id = RandomUtils.randomLong(); return new SpanContextImpl(id, id, id, null, baggage); } /** * Builds new {@link SpanContextImpl} with new trace context and no baggage. * * @return {@link SpanContextImpl}. Never <code>null</code>. */ public static SpanContextImpl build() { long id = RandomUtils.randomLong(); return new SpanContextImpl(id, id, id, null, null); } /** * This method is used when building context that is extracted from the propagation (like HTTP * headers). In this only calling span id and trace id are passed over the network with the * baggage. Returned context represents the context of the calling span. * * @param passedId * calling span id * @param passedTraceId * calling span trace id * @param passedBaggage * passage traveling along * @return Context representing the context of the calling span. */ public static SpanContextImpl buildExtractedContext(long passedId, long passedTraceId, Map<String, String> passedBaggage) { return new SpanContextImpl(passedId, passedTraceId, passedId, null, passedBaggage); } /** * {@inheritDoc} */ @Override public Iterable<Entry<String, String>> baggageItems() { return Collections.unmodifiableMap(baggage).entrySet(); } /** * Sets baggage item. * * @param key * key * @param value * value */ public void setBaggageItem(String key, String value) { baggage.put(key, value); } /** * Gets baggage item. * * @param key * key * @return Baggage item or <code>null</code> if the one does not exist. */ public String getBaggageItem(String key) { return baggage.get(key); } /** * Returns reference type to the parent if the one is set. * * @return Returns reference type to the parent if the one is set. */ public String getReferenceType() { return this.referenceType; } /** * Gets {@link #id}. * * @return {@link #id} */ public long getId() { return this.id; } /** * Gets {@link #traceId}. * * @return {@link #traceId} */ public long getTraceId() { return this.traceId; } /** * Gets {@link #parentId}. * * @return {@link #parentId} */ public long getParentId() { return this.parentId; } /** * {@inheritDoc} */ @Override public int hashCode() { final int prime = 31; int result = 1; result = (prime * result) + ((this.baggage == null) ? 0 : this.baggage.hashCode()); result = (prime * result) + (int) (this.id ^ (this.id >>> 32)); result = (prime * result) + (int) (this.parentId ^ (this.parentId >>> 32)); result = (prime * result) + ((this.referenceType == null) ? 0 : this.referenceType.hashCode()); result = (prime * result) + (int) (this.traceId ^ (this.traceId >>> 32)); return result; } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } SpanContextImpl other = (SpanContextImpl) obj; if (this.baggage == null) { if (other.baggage != null) { return false; } } else if (!this.baggage.equals(other.baggage)) { return false; } if (this.id != other.id) { return false; } if (this.parentId != other.parentId) { return false; } if (this.referenceType == null) { if (other.referenceType != null) { return false; } } else if (!this.referenceType.equals(other.referenceType)) { return false; } if (this.traceId != other.traceId) { return false; } return true; } /** * {@inheritDoc} */ @Override public String toString() { return "SpanContextImpl [id=" + this.id + ", traceId=" + this.traceId + ", parentId=" + this.parentId + ", referenceType=" + this.referenceType + ", baggage=" + this.baggage + "]"; } }