/** * Returns whether the given {@link InvocationTreeElement} is a child of a span or the parent is * a span respectively. * * @param element * the element to check * @return <code>true</code> when the parent is a span */ public static boolean isChildOfSpan(InvocationTreeElement element) { if (element == null) { throw new IllegalArgumentException("The given InvocationTreeElement must not be null."); } return (element.getParent() != null) && element.getParent().isSpan(); }
/** * Returns whether the given element is considered as asynchronous. It will return always * <code>false</code> if the type is not {@link TreeElementType#SPAN}. * * @param element * the element to check * @return <code>true</code> if the element is considered as asynchronous */ public static boolean isConsideredAsync(InvocationTreeElement element) { if (!element.isSpan()) { return false; } return References.FOLLOWS_FROM.equals(((Span) element.getDataElement()).getReferenceType()); } }
/** * Starts resolving the tree elements. */ private void resolve() { if (tree.isSpan()) { resolveSpan(tree); } else { resolveInvocationSequence(tree); } }
/** * Returns exclusive duration of the Span contained in the given {@link InvocationTreeElement}. * Note: This method works only with {@link InvocationTreeElement} of type * {@link TreeElementType#SPAN}. * * @param element * the {@link InvocationTreeElement} to calculate the exclusive duration for * @return Returns exclusive duration. */ public static double calculateSpanExclusiveDuration(InvocationTreeElement element) { if (element == null) { return Double.NaN; } if (!element.isSpan()) { return 0D; } double childrenDuration = element.getChildren().stream().mapToDouble(InvocationTreeUtil::calculateSpanParentRelativeDuration).sum(); double exclusiveDuration = ((Span) element.getDataElement()).getDuration() - childrenDuration; return Math.max(exclusiveDuration, 0D); }
/** * Returns the relative duration of the span contained in the given element. If the element is * an asynchronous span, the method will return <code>0</code> because we cannot specify a * relative duration of an asynchronous span relative to its parent. * <p> * If the element is not of type {@link TreeElementType#SPAN} the sum of all direct child spans * are calculated. This means that when the child spans are not direct children in the tree but * are connected via several invocation sequence to the parent span we handle them as well. * * @param element * the element to calculate the duration * @return the relative duration of the span or the sum of all direct child spans */ private static double calculateSpanParentRelativeDuration(InvocationTreeElement element) { if (element.isSpan()) { if (InvocationTreeUtil.isConsideredAsync(element)) { return 0D; } else { return ((Span) element.getDataElement()).getDuration(); } } // This case is only necessary in full trees which do not consist of span elements only but // multiple spans are connected together over several invocation sequences. In a tree // consisting only of span elements, this case can never happen. double nestedDuration = element.getChildren().stream().mapToDouble(InvocationTreeUtil::calculateSpanParentRelativeDuration).sum(); return nestedDuration; }
/** * Resolves additional span details (e.g. has nested exception or SQL data) for the given * {@link InvocationTreeElement}. * * @param element * the {@link InvocationTreeElement} which details should be resolved * @param spanToInvocationSequenceMap * lookup map for mapping the spans to {@link InvocationSequenceData} */ private void resolveSpanDetails(InvocationTreeElement element, Map<Long, InvocationSequenceData> spanToInvocationSequenceMap) { if (!element.isSpan()) { return; } InvocationSequenceData sequenceData = spanToInvocationSequenceMap.get(((Span) element.getDataElement()).getSpanIdent().getId()); if (sequenceData != null) { element.setHasNestedSqls((sequenceData.isNestedSqlStatements() != null) && sequenceData.isNestedSqlStatements()); element.setHasNestedExceptions((sequenceData.isNestedExceptions() != null) && sequenceData.isNestedExceptions()); } }
/** * Returns exclusive duration as a percentage relative to its parents. Note: This method works * only with {@link InvocationTreeElement} of type {@link TreeElementType#SPAN}. * * @param element * the {@link InvocationTreeElement} to calculate the exclusive percentage for * @return Returns exclusive duration. */ public static double calculateSpanExclusivePercentage(InvocationTreeElement element) { if (element == null) { return Double.NaN; } InvocationTreeElement topElement = element; while ((topElement.getParent() != null) && !isConsideredAsync(topElement)) { topElement = topElement.getParent(); } if (topElement.isSpan()) { return InvocationTreeUtil.calculateSpanExclusiveDuration(element) / ((Span) topElement.getDataElement()).getDuration(); } return 0D; }
} else { if ((parent.getParent() == null) || !parent.getParent().isSpan() || (((Span) parent.getParent().getDataElement()).getSpanIdent().getId() != span.getSpanIdent().getId())) { child = createTreeElement(span, parent);