package zipkin.internal;
import com.github.kristofa.brave.IdConversion;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import zipkin.Span;
import static java.util.Arrays.asList;
/** In internal package to access zipkin internal code */
public class TraceUtil {
public static List<Span> washIds(List<Span> trace) {
// we want to return spans in their original order
Map<Span, Span> map = new LinkedHashMap<>();
for (Span span : trace) map.put(span, span);
long traceId = 1L, id = 1L;
// traverse the tree breadth-first, and replace the ids with incrementing ones
for (Iterator<Node<Span>> iter = Node.constructTree(trace).traverse(); iter.hasNext(); id++) {
Node<Span> next = iter.next();
if (next.parent() == null) {
Span root = next.value().toBuilder().traceId(traceId).id(id).build();
map.replace(next.value(), root);
next.value(root);
} else {
Span parent = next.parent().value();
Span child = next.value().toBuilder().traceId(traceId).parentId(parent.id).id(id).build();
map.replace(next.value(), child);
next.value(child);
}
}
return new ArrayList<>(map.values());
}
/** washes propagated trace identifiers in the request headers */
public static Map<String, List<String>> washIds(Map<String, List<String>> headers,
List<Span> unwashed) {
List<Span> washed = washIds(unwashed);
Map<String, String> idMapping = new LinkedHashMap<>();
for (int i = 0; i < unwashed.size(); i++) {
idMapping.put(
IdConversion.convertToString(unwashed.get(i).id),
IdConversion.convertToString(washed.get(i).id)
);
}
Map<String, List<String>> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
result.putAll(headers);
for (Map.Entry<String, List<String>> entry : result.entrySet()) {
String replacement = idMapping.get(entry.getValue().get(0));
if (replacement != null) {
result.put(entry.getKey(), asList(replacement));
}
}
return result;
}
}