/** * Resolve the span details (like has nested exceptions, has SQL statement..). */ private void resolveSpanDetails() { // Load invocation sequences for calculating span details. We are doing this here again, // because we did not loaded any invocations at the beginning because we don't needed them // to build the tree. if (mode == Mode.ONLY_SPANS_WITH_SDK) { invocationSequences = loadInvocationSequences(); } // Creating a mapping from span ids to invocation sequences in order to prevent a continuous // iteration over the invocation sequences - when two spans refers the same // trace, we are trying to return the invocation sequence which follows the span (= is a // root span). Map<Long, InvocationSequenceData> spanToInvocationSequenceMap = InvocationSequenceDataHelper.asStream(invocationSequences).filter(InvocationSequenceDataHelper::hasSpanIdent) .collect(Collectors.toMap(i -> i.getSpanIdent().getId(), Function.identity(), (i1, i2) -> InvocationSequenceDataHelper.isRootElementInSequence(i1) ? i1 : i2)); // now we actually resolves the span details (like has nested exceptions..) tree.asStream().filter(e -> e.getType() == TreeElementType.SPAN).forEach(e -> resolveSpanDetails(e, spanToInvocationSequenceMap)); }
/** * Builds the tree. * * @return The root {@link InvocationTreeElement} of the resulting tree. If no tree could be * built, e.g. when finding no root element <code>null</code> will be returned. */ public InvocationTreeElement build() { prepare(); tree = findRoot(); if (tree == null) { return null; } resolve(); sortChildren(tree); resolveSpanDetails(); return tree; }