@Test public void successfulInTree() { InvocationTreeElement treeElement = InvocationTreeUtil.lookupTreeElement(InvocationTreeUtil.buildLookupMap(tree), span02); double duration = InvocationTreeUtil.calculateSpanExclusiveDuration(treeElement); assertThat(duration, is(100D)); }
@Test public void successfulInTree() { InvocationTreeElement treeElement = InvocationTreeUtil.lookupTreeElement(InvocationTreeUtil.buildLookupMap(tree), span03); InvocationTreeElement root = InvocationTreeUtil.getRoot(treeElement); assertThat(root, is(tree)); }
/** * Builds the {@link #lookupMap} map of the given tree. This allows direct access to the tree * elements via data objects. * * @param tree * the tree * @return the lookup map for the given tree */ public static Map<Object, InvocationTreeElement> buildLookupMap(InvocationTreeElement tree) { return InvocationTreeUtil.getRoot(tree).asStream().collect(Collectors.toMap(e -> calculateLookupKey(e.getDataElement()), Function.identity())); }
/** * {@inheritDoc} */ @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { InvocationTreeElement input = validateInput(newInput); if (input == null) { return; } lookupMap = InvocationTreeUtil.buildLookupMap(input); rootElement = InvocationTreeUtil.getRoot(input); }
@Test public void useNullValue() { Map<Object, InvocationTreeElement> lookupMap = InvocationTreeUtil.buildLookupMap(tree); InvocationTreeElement treeElement = InvocationTreeUtil.lookupTreeElement(lookupMap, null); assertThat(treeElement, is(nullValue())); }
InvocationTreeElement ite = InvocationTreeUtil.lookupTreeElement(contentProvider.getLookupMap(), span); case DURATION: StyledString durationString = new StyledString(NumberFormatter.formatDouble(span.getDuration(), timeDecimalPlaces)); if (InvocationTreeUtil.isConsideredAsync(ite)) { durationString.append(TextFormatter.getWarningSign()); case EXCLUSIVE: StyledString exclusive = new StyledString(); exclusive.append(NumberFormatter.formatDouble(InvocationTreeUtil.calculateSpanExclusiveDuration(ite), timeDecimalPlaces)); exclusive.append(" (", StyledString.COUNTER_STYLER); int percentage = Math.round((float) InvocationTreeUtil.calculateSpanExclusivePercentage(ite) * 100); exclusive.append(NumberFormatter.formatInteger(percentage), StyledString.COUNTER_STYLER); exclusive.append("%)", StyledString.COUNTER_STYLER); if (InvocationTreeUtil.isConsideredAsync(ite)) { exclusive.append(TextFormatter.getWarningSign()); Collection<InvocationSequenceData> sequences = InvocationTreeUtil.getInvocationSequences(ite); if (CollectionUtils.isNotEmpty(sequences)) { Set<Integer> applicationIds = new HashSet<>(1); Collection<InvocationSequenceData> sequences2 = InvocationTreeUtil.getInvocationSequences(ite); if (CollectionUtils.isNotEmpty(sequences2)) { Set<Integer> transationsIds = new HashSet<>(1);
@Test public void successfulOfAsync() { InvocationTreeElement treeElement = InvocationTreeUtil.lookupTreeElement(InvocationTreeUtil.buildLookupMap(tree), span03); double duration = InvocationTreeUtil.calculateSpanExclusivePercentage(treeElement); assertThat(duration, is(0.2D)); }
@Test public void parentIsNotSpan() { InvocationTreeElement treeElement = InvocationTreeUtil.lookupTreeElement(InvocationTreeUtil.buildLookupMap(tree), _invoc02); boolean result = InvocationTreeUtil.isChildOfSpan(treeElement); assertThat(result, is(false)); }
@Test public void buildWithNestedExceptions() { Span span01 = createServerSpan(null); InvocationSequenceData invoc01 = createSequence(span01); InvocationSequenceData _invoc02 = createSequence(null); invoc01.getNestedSequences().add(_invoc02); invoc01.setNestedExceptions(true); doReturn(Arrays.asList(span01)).when(spanService).getSpans(1337L); doReturn(Arrays.asList(invoc01)).when(invocationService).getInvocationSequenceDetail(1337L); builder.setSpanService(spanService).setInvocationService(invocationService).setTraceId(1337L); InvocationTreeElement tree = builder.build(); Map<Object, InvocationTreeElement> lookupMap = InvocationTreeUtil.buildLookupMap(tree); assertThat(lookupMap.size(), is(3)); assertThat(tree.hasNestedExceptions(), is(true)); assertThat(tree.hasNestedSqls(), is(false)); }
/** * {@inheritDoc} */ @Override public Object[] getObjectsToSearch(Object treeInput) { return InvocationTreeUtil.getDataElements(spanTree, false).toArray(); }
/** * {@inheritDoc} */ @Override public ElementOccurrenceCount countOccurrences(Object element, ViewerFilter[] filters) { InvocationTreeContentProvider contentProvider = (InvocationTreeContentProvider) getContentProvider(); // count span occurence if (element instanceof Span) { boolean containsSpan = contentProvider.getLookupMap().containsKey(InvocationTreeUtil.calculateLookupKey(element)); if (containsSpan) { ElementOccurrenceCount elementCount = new ElementOccurrenceCount(); elementCount.increaseVisibleOccurrences(); return elementCount; } } // count invocation occurence if (contentProvider.getRootElement() != null) { List<InvocationSequenceData> sequences; sequences = InvocationTreeUtil.getInvocationSequences(contentProvider.getRootElement()); return OccurrenceFinderFactory.getOccurrenceCount(sequences, element, filters); } return ElementOccurrenceCount.emptyElement(); }
@Test public void successful() { InvocationTreeElement root = InvocationTreeUtil.getRoot(tree); assertThat(root, is(tree)); }
@Test public void nullValue() { List<InvocationSequenceData> sequences = InvocationTreeUtil.getInvocationSequences(null); assertThat(sequences, is(empty())); } }
/** * {@inheritDoc} */ @Override public boolean hasChildren(Object element) { InvocationTreeElement ite = InvocationTreeUtil.lookupTreeElement(lookupMap, element); if (ite == null) { return false; } return ite.hasChildren(); }
/** * 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; }
@Test public void successfulAtRoot() { double duration = InvocationTreeUtil.calculateSpanExclusiveDuration(tree); assertThat(duration, is(130D)); }
/** * Returns the {@link InvocationTreeElement} of the given lookup map which contains the given * data object. <code>null</code> is returned if no {@link InvocationTreeElement} matches. * * @param lookupMap * the lookup map * @param object * the data object to search * @return the {@link InvocationTreeElement} related to the given data object */ public static InvocationTreeElement lookupTreeElement(Map<Object, InvocationTreeElement> lookupMap, Object object) { if (lookupMap == null) { return null; } return lookupMap.get(calculateLookupKey(object)); }
@Test public void successfulAtRoot() { double duration = InvocationTreeUtil.calculateSpanExclusivePercentage(tree); assertThat(duration, is(0.5D)); }
/** * 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; }
@Test public void successful01() { Map<Object, InvocationTreeElement> lookupMap = InvocationTreeUtil.buildLookupMap(tree); InvocationTreeElement treeElement = InvocationTreeUtil.lookupTreeElement(lookupMap, _invoc02); assertThat(treeElement.getDataElement(), is(_invoc02)); }