use of zipkin2.internal.DependencyLinker in project zipkin by openzipkin.
the class AggregateDependencies method apply.
@Override
public List<DependencyLink> apply(DSLContext context) {
// Subquery on trace IDs to prevent only matching the part of the trace that exists within
// the interval: we want all of the trace.
SelectConditionStep<Record1<Long>> traceIDs = context.selectDistinct(ZIPKIN_SPANS.TRACE_ID).from(ZIPKIN_SPANS).where(startTsBegin == startTsEnd ? ZIPKIN_SPANS.START_TS.lessOrEqual(startTsEnd) : ZIPKIN_SPANS.START_TS.between(startTsBegin, startTsEnd));
// Lazy fetching the cursor prevents us from buffering the whole dataset in memory.
Cursor<Record> cursor = context.selectDistinct(schema.dependencyLinkerFields).from(ZIPKIN_SPANS.leftJoin(ZIPKIN_ANNOTATIONS).on(ZIPKIN_SPANS.TRACE_ID.eq(ZIPKIN_ANNOTATIONS.TRACE_ID).and(ZIPKIN_SPANS.ID.eq(ZIPKIN_ANNOTATIONS.SPAN_ID))).and(ZIPKIN_ANNOTATIONS.A_KEY.in("lc", "cs", "ca", "sr", "sa", "ma", "mr", "ms", "error"))).where(ZIPKIN_SPANS.TRACE_ID.in(traceIDs)).groupBy(schema.dependencyLinkerGroupByFields).fetchLazy();
Iterator<Iterator<Span>> traces = new DependencyLinkV2SpanIterator.ByTraceId(cursor.iterator(), schema.hasTraceIdHigh);
if (!traces.hasNext())
return Collections.emptyList();
DependencyLinker linker = new DependencyLinker();
List<Span> nextTrace = new ArrayList<>();
while (traces.hasNext()) {
Iterator<Span> i = traces.next();
while (i.hasNext()) nextTrace.add(i.next());
linker.putTrace(nextTrace);
nextTrace.clear();
}
return linker.link();
}
use of zipkin2.internal.DependencyLinker in project zipkin by openzipkin.
the class DependencyLinker method putTrace.
/**
* All {@code spans} must have the same trace id.
*/
public DependencyLinker putTrace(List<Span> spans) {
if (spans.isEmpty())
return this;
SpanNode traceTree = builder.build(spans);
if (logger.isLoggable(FINE))
logger.fine("traversing trace tree, breadth-first");
for (Iterator<SpanNode> i = traceTree.traverse(); i.hasNext(); ) {
SpanNode current = i.next();
Span currentSpan = current.span();
if (logger.isLoggable(FINE)) {
logger.fine("processing " + currentSpan);
}
Kind kind = currentSpan.kind();
// spans, we proceed to use the name the client chose.
if (Kind.CLIENT.equals(kind) && !current.children().isEmpty()) {
continue;
}
String serviceName = currentSpan.localServiceName();
String remoteServiceName = currentSpan.remoteServiceName();
if (kind == null) {
// Treat unknown type of span as a client span if we know both sides
if (serviceName != null && remoteServiceName != null) {
kind = Kind.CLIENT;
} else {
logger.fine("non remote span; skipping");
continue;
}
}
String child;
String parent;
switch(kind) {
case SERVER:
case CONSUMER:
child = serviceName;
parent = remoteServiceName;
if (current == traceTree) {
// we are the root-most span.
if (parent == null) {
logger.fine("root's client is unknown; skipping");
continue;
}
}
break;
case CLIENT:
case PRODUCER:
parent = serviceName;
child = remoteServiceName;
break;
default:
logger.fine("unknown kind; skipping");
continue;
}
boolean isError = currentSpan.tags().containsKey("error");
if (kind == Kind.PRODUCER || kind == Kind.CONSUMER) {
if (parent == null || child == null) {
logger.fine("cannot link messaging span to its broker; skipping");
} else {
addLink(parent, child, isError);
}
continue;
}
// Local spans may be between the current node and its remote parent
Span remoteAncestor = firstRemoteAncestor(current);
String remoteAncestorName;
if (remoteAncestor != null && (remoteAncestorName = remoteAncestor.localServiceName()) != null) {
// Check for this and backfill a link from the nearest remote to that service as necessary.
if (kind == Kind.CLIENT && serviceName != null && !remoteAncestorName.equals(serviceName)) {
logger.fine("detected missing link to client span");
// we don't know if there's an error here
addLink(remoteAncestorName, serviceName, false);
}
if (kind == Kind.SERVER || parent == null)
parent = remoteAncestorName;
// client, we need to check it for errors.
if (!isError && Kind.CLIENT.equals(remoteAncestor.kind()) && currentSpan.parentId() != null && currentSpan.parentId().equals(remoteAncestor.id())) {
isError = remoteAncestor.tags().containsKey("error");
}
}
if (parent == null || child == null) {
logger.fine("cannot find remote ancestor; skipping");
continue;
}
addLink(parent, child, isError);
}
return this;
}
use of zipkin2.internal.DependencyLinker in project zipkin by openzipkin.
the class ITDependencies method aggregateLinks.
/**
* Returns links aggregated by midnight
*/
public static Map<Long, List<DependencyLink>> aggregateLinks(List<Span> spans) {
Map<Long, DependencyLinker> midnightToLinker = new LinkedHashMap<>();
for (List<Span> trace : GroupByTraceId.create(false).map(spans)) {
long midnightOfTrace = flooredTraceTimestamp(trace);
DependencyLinker linker = midnightToLinker.get(midnightOfTrace);
if (linker == null)
midnightToLinker.put(midnightOfTrace, (linker = new DependencyLinker()));
linker.putTrace(trace);
}
Map<Long, List<DependencyLink>> result = new LinkedHashMap<>();
midnightToLinker.forEach((midnight, linker) -> result.put(midnight, linker.link()));
return result;
}
Aggregations