Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright The OpenZipkin Authors
* SPDX-License-Identifier: Apache-2.0
*/
package zipkin2.internal;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.logging.Logger;
import zipkin2.Endpoint;
import zipkin2.Span;
import static java.lang.String.format;
import static java.util.logging.Level.FINE;
/**
* Convenience type representing a trace tree. Multiple Zipkin features require a trace tree. For
* example, looking at network boundaries to correct clock skew and aggregating requests paths imply
* visiting the tree.
*/
public final class SpanNode {
static final Comparator NODE_COMPARATOR = new Comparator() {
@Override public int compare(SpanNode left, SpanNode right) {
long x = left.span().timestampAsLong(), y = right.span().timestampAsLong();
return (x < y) ? -1 : ((x == y) ? 0 : 1); // Long.compareTo is JRE 7+
}
};
public static SpanNode.Builder newBuilder(Logger logger) {
return new SpanNode.Builder(logger);
}
/** Set via {@link #addChild(SpanNode)} */
@Nullable SpanNode parent;
/** Null when a synthetic root node */
@Nullable final Span span;
/** mutable to avoid allocating lists for childless nodes */
List children = Collections.emptyList();
SpanNode(@Nullable Span span) {
this.span = span;
}
/** Returns the parent, or null if root */
@Nullable public SpanNode parent() {
return parent;
}
/** Returns the span, or null if a synthetic root node */
@Nullable public Span span() {
return span;
}
/** Returns the children of this node. */
public List children() {
return children;
}
/** Traverses the tree, breadth-first. */
public Iterator traverse() {
return new BreadthFirstIterator(this);
}
static final class BreadthFirstIterator implements Iterator {
final ArrayDeque queue = new ArrayDeque<>();
BreadthFirstIterator(SpanNode root) {
// since the input data could be headless, we first push onto the queue the root-most spans
if (root.span == null) { // synthetic root
for (int i = 0, length = root.children.size(); i < length; i++) {
queue.add(root.children.get(i));
}
} else {
queue.add(root);
}
}
@Override public boolean hasNext() {
return !queue.isEmpty();
}
@Override public SpanNode next() {
if (!hasNext()) throw new NoSuchElementException();
SpanNode result = queue.remove();
for (int i = 0, length = result.children.size(); i < length; i++) {
queue.add(result.children.get(i));
}
return result;
}
@Override public void remove() {
throw new UnsupportedOperationException("remove");
}
}
/** Adds the child IFF it isn't already a child. */
SpanNode addChild(SpanNode child) {
if (child == null) throw new NullPointerException("child == null");
if (child == this) throw new IllegalArgumentException("circular dependency on " + this);
if (children.equals(Collections.emptyList())) children = new ArrayList<>();
children.add(child);
child.parent = this;
return this;
}
public static final class Builder {
final Logger logger;
Builder(Logger logger) {
this.logger = logger;
}
SpanNode rootSpan = null;
final Map