package rocks.inspectit.shared.all.tracing.data; import java.util.Collections; import java.util.HashMap; import java.util.Map; import rocks.inspectit.shared.all.cmr.cache.IObjectSizes; import rocks.inspectit.shared.all.communication.MethodSensorData; /** * Base span. This span holds all information that all other types of spans do. * <p> * The relationship in the span can be described in two ways: * <ul> * <li>1. The caller or called attribute. Reference span can either call another reference span or * be called. * <li>2. Relationship type describes what are time constraints between two spans. Can be Child-Of * (caller wait for callee) or Follow-From (caller does not wait for the callee). More info or the * relationships can be read in the class {@link ReferenceType}. * </ul> * <p> * We also capture the {@link PropagationType} that provides information if propagation was inter- * or cross-process and what technology was used (for example HTTP). * * @author Ivan Senic * */ public abstract class AbstractSpan extends MethodSensorData implements Span { /** * Generated UID. */ private static final long serialVersionUID = -8144017430549409409L; /** * Identifier of this span. */ private SpanIdent spanIdent; /** * Duration of this span in milliseconds. We keep same resolution here as for the duration of * our other monitoring data. */ private double duration; /** * Propagation type. * * @see PropagationType */ private PropagationType propagationType; /** * Reference type. */ private String referenceType; /** * Defined tags. */ private Map<String, String> tags; /** * {@inheritDoc} */ @Override public abstract boolean isCaller(); /** * Gets {@link #spanIdent}. * * @return {@link #spanIdent} */ @Override public SpanIdent getSpanIdent() { return this.spanIdent; } /** * Sets {@link #spanIdent}. * * @param spanIdent * New value for {@link #spanIdent} */ public void setSpanIdent(SpanIdent spanIdent) { this.spanIdent = spanIdent; } /** * Gets {@link #duration}. * * @return {@link #duration} */ @Override public double getDuration() { return this.duration; } /** * Sets {@link #duration}. * * @param duration * New value for {@link #duration} */ public void setDuration(double duration) { this.duration = duration; } /** * Gets {@link #propagationType}. * * @return {@link #propagationType} */ @Override public PropagationType getPropagationType() { return this.propagationType; } /** * Sets {@link #propagationType}. * * @param propagationType * New value for {@link #propagationType} */ public void setPropagationType(PropagationType propagationType) { this.propagationType = propagationType; } /** * {@inheritDoc} */ @Override public String getReferenceType() { return referenceType; } /** * Sets {@link #ReferenceType}. * * @param referenceType * New value for {@link #ReferenceType} */ public void setReferenceType(String referenceType) { this.referenceType = referenceType; } /** * Adds tag to this span. * * @param tag * {@link Tag}, must not be <code>null</code>. * @param value * String value, must not be <code>null</code>. * @return Old value associated with same tag. */ @Override public String addTag(String tag, String value) { if (null == tags) { tags = new HashMap<String, String>(1, 1f); } return tags.put(tag, value); } /** * Adds all tags from the given map to the tags of this span. * * @param otherTags * Map of tags to add. */ @Override public void addAllTags(Map<String, String> otherTags) { if (null == tags) { tags = new HashMap<String, String>(otherTags.size(), 1f); } tags.putAll(otherTags); } /** * {@inheritDoc} */ @Override public Map<String, String> getTags() { if (null == tags) { return Collections.emptyMap(); } else { return Collections.unmodifiableMap(tags); } } /** * {@inheritDoc} */ @Override public long getObjectSize(IObjectSizes objectSizes, boolean doAlign) { long size = super.getObjectSize(objectSizes, doAlign); size += objectSizes.getPrimitiveTypesSize(4, 0, 0, 0, 0, 1); size += objectSizes.getSizeOf(spanIdent); if (null != tags) { int tagsSize = tags.size(); size += objectSizes.getSizeOfHashMap(tagsSize); size += tagsSize + objectSizes.getSizeOfIntegerObject(); size += objectSizes.getSizeOf(tags.values().toArray(new String[tagsSize])); } if (doAlign) { return objectSizes.alignTo8Bytes(size); } else { return size; } } /** * {@inheritDoc} */ @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); long temp; temp = Double.doubleToLongBits(this.duration); result = (prime * result) + (int) (temp ^ (temp >>> 32)); result = (prime * result) + ((this.propagationType == null) ? 0 : this.propagationType.hashCode()); result = (prime * result) + ((this.referenceType == null) ? 0 : this.referenceType.hashCode()); result = (prime * result) + ((this.spanIdent == null) ? 0 : this.spanIdent.hashCode()); result = (prime * result) + ((this.tags == null) ? 0 : this.tags.hashCode()); return result; } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } AbstractSpan other = (AbstractSpan) obj; if (Double.doubleToLongBits(this.duration) != Double.doubleToLongBits(other.duration)) { return false; } if (this.propagationType != other.propagationType) { return false; } if (this.referenceType == null) { if (other.referenceType != null) { return false; } } else if (!this.referenceType.equals(other.referenceType)) { return false; } if (this.spanIdent == null) { if (other.spanIdent != null) { return false; } } else if (!this.spanIdent.equals(other.spanIdent)) { return false; } if (this.tags == null) { if (other.tags != null) { return false; } } else if (!this.tags.equals(other.tags)) { return false; } return true; } /** * {@inheritDoc} */ @Override public String toString() { return "AbstractSpan [getSpanIdent()=" + this.getSpanIdent() + ", getPropagationType()=" + this.getPropagationType() + ", getReferenceType()=" + this.getReferenceType() + ", isCaller()=" + this.isCaller() + ", getTags()=" + this.getTags() + ", getDuration()=" + this.getDuration() + "]"; } }