InvocationSequenceData invocationSequenceData = new InvocationSequenceData(timestamp, platformId, sensorTypeId, methodId); threadLocalInvocationData.set(invocationSequenceData); invocationSequenceData.setChildCount(invocationSequenceData.getChildCount() + 1L); InvocationSequenceData nestedInvocationSequenceData = new InvocationSequenceData(timestamp, platformId, invocationSequenceData.getSensorTypeIdent(), methodId); nestedInvocationSequenceData.setStart(timer.getCurrentTime()); nestedInvocationSequenceData.setParentSequence(invocationSequenceData); invocationSequenceData.getNestedSequences().add(nestedInvocationSequenceData);
/** * Clones invocation sequence. This method returns new object exactly same as the original * object, but with out nested sequences set. * * @return Cloned invocation sequence. */ public InvocationSequenceData getClonedInvocationSequence() { InvocationSequenceData clone = new InvocationSequenceData(this.getTimeStamp(), this.getPlatformIdent(), this.getSensorTypeIdent(), this.getMethodIdent()); clone.setId(this.getId()); clone.setSpanIdent(this.getSpanIdent()); clone.setChildCount(this.getChildCount()); clone.setDuration(this.getDuration()); clone.setEnd(this.getEnd()); clone.setNestedSequences(Collections.<InvocationSequenceData> emptyList()); clone.setParameterContentData(this.getParameterContentData()); clone.setParentSequence(this.getParentSequence()); clone.setPosition(this.getPosition()); clone.setSqlStatementData(this.getSqlStatementData()); clone.setTimerData(this.getTimerData()); clone.setExceptionSensorDataObjects(this.getExceptionSensorDataObjects()); clone.setStart(this.getStart()); clone.setNestedSqlStatements(this.isNestedSqlStatements()); clone.setNestedExceptions(this.isNestedExceptions()); clone.setLoggingData(this.getLoggingData()); clone.setApplicationId(this.getApplicationId()); clone.setBusinessTransactionId(this.getBusinessTransactionId()); return clone; }
/** * Returns if the given {@link InvocationSequenceData} should be removed due to no data. Can be * in case of * <ul> * <li>the wrapping of the prepared SQL statements. * <li>having an empty logging element (if the logging occurred with a lower logging level than * the configuration) * <li>running remote sensor that provided no span * <li>having invocation sensor without any other sensor on the method * </ul> * * @param invocationSequenceData * {@link InvocationSequenceData} to check. * * @return True if the invocation should be removed. */ private boolean removeDueToNoData(InvocationSequenceData invocationSequenceData) { return (null == invocationSequenceData.getTimerData()) && (null == invocationSequenceData.getSqlStatementData()) && (null == invocationSequenceData.getLoggingData()) && (null == invocationSequenceData.getSpanIdent()) && CollectionUtils.isEmpty(invocationSequenceData.getExceptionSensorDataObjects()); }
/** * Sets the parent to all nested sequences of the invocation to the correct one. * * @param parent * Parent to start from. */ private void connectChildren(InvocationSequenceData parent) { if (null != parent.getNestedSequences()) { for (InvocationSequenceData child : parent.getNestedSequences()) { child.setParentSequence(parent); connectChildren(child); } } }
assertThat(invocation.getPlatformIdent(), is(platformId)); assertThat(invocation.getMethodIdent(), is(methodId)); assertThat(invocation.getSensorTypeIdent(), is(sensorTypeId)); assertThat(invocation.getDuration(), is(secondTimerValue - firstTimerValue)); assertThat(invocation.getNestedSequences(), is(empty())); assertThat(invocation.getChildCount(), is(0L)); assertThat(invocation.getSpanIdent(), is(SpanContextTransformer.transformSpanContext(context)));
assertThat(invocation.getPlatformIdent(), is(platformId)); assertThat(invocation.getMethodIdent(), is(methodId)); assertThat(invocation.getSensorTypeIdent(), is(sensorTypeId)); assertThat(invocation.getDuration(), is(secondTimerValue - firstTimerValue)); assertThat(invocation.getNestedSequences(), is(empty())); assertThat(invocation.getChildCount(), is(0L)); assertThat(invocation.getTimerData(), is(timerData)); assertThat(invocation.getSqlStatementData(), is(sqlStatementData)); assertThat(invocation.getSpanIdent(), is(nullValue()));
@Test public void timerDataMustReturnAEmptyListOfAggregatedDiagnosisDataWhenTheDurationIsZero() { long platformIdent = 108; long sensorTypeIdent = 1; Timestamp defDate = new Timestamp(new Date().getTime()); List<InvocationSequenceData> nestedSequences = new ArrayList<>(); InvocationSequenceData firstChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 1L); TimerData firstSeqTimerData = new TimerData(new Timestamp(System.currentTimeMillis()), 10L, 20L, 30L); firstSeqTimerData.calculateExclusiveMin(200d); firstChildSequence.setTimerData(firstSeqTimerData); InvocationSequenceData secondChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstChildSequence); nestedSequences.add(secondChildSequence); when(globalContext.getDuration()).thenReturn(new Double(0)); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Action method must return an array of AggregatedDiagnosisData not empty", timeWastingOperationsResults, hasSize(0)); }
assertThat(invocation.getPlatformIdent(), is(platformId)); assertThat(invocation.getMethodIdent(), is(methodId1)); assertThat(invocation.getSensorTypeIdent(), is(sensorTypeId)); assertThat(invocation.getDuration(), is(fourthTimerValue - firstTimerValue)); assertThat(invocation.getNestedSequences(), hasSize(1)); assertThat(invocation.getChildCount(), is(1L)); InvocationSequenceData child = invocation.getNestedSequences().iterator().next(); assertThat(child.getPlatformIdent(), is(platformId)); assertThat(child.getMethodIdent(), is(methodId2)); assertThat(child.getSensorTypeIdent(), is(sensorTypeId)); assertThat(child.getDuration(), is(thirdTimerValue - secondTimerValue)); assertThat(child.getNestedSequences(), is(empty())); assertThat(child.getParentSequence(), is(invocation)); assertThat(child.getChildCount(), is(0L)); assertThat(child.getTimerData(), is(timerData));
@Test public void noBusinessContext() throws Exception { when(cachedDataService.getPlatformIdentForId(PLATFORM_ID)).thenReturn(platformIdent); when(cachedDataService.getBusinessTransactionForId(APP_ID, BT_ID)).thenReturn(null); double duration = RandomUtils.nextDouble(); long time = RandomUtils.nextLong(); when(data.getPlatformIdent()).thenReturn(PLATFORM_ID); when(data.getApplicationId()).thenReturn(APP_ID); when(data.getBusinessTransactionId()).thenReturn(BT_ID); when(data.getTimeStamp()).thenReturn(new Timestamp(time)); when(data.getDuration()).thenReturn(duration); Collection<Builder> pointBuilderCol = builder.createBuilders(data); assertThat(pointBuilderCol.size(), is(1)); Builder pointBuilder = pointBuilderCol.iterator().next(); assertThat(getMeasurement(pointBuilder), is(Series.BusinessTransaction.NAME)); assertThat(getTime(pointBuilder), is(time)); assertThat(getPrecision(pointBuilder), is(TimeUnit.MILLISECONDS)); assertThat(getTags(pointBuilder), hasEntry(Series.TAG_AGENT_ID, String.valueOf(PLATFORM_ID))); assertThat(getTags(pointBuilder), hasEntry(Series.TAG_AGENT_NAME, String.valueOf(AGENT_NAME))); assertThat(getTags(pointBuilder), hasEntry(Series.BusinessTransaction.TAG_APPLICATION_NAME, String.valueOf(ApplicationDefinition.UNKNOWN_APP))); assertThat(getTags(pointBuilder), hasEntry(Series.BusinessTransaction.TAG_BUSINESS_TRANSACTION_NAME, String.valueOf(BusinessTransactionDefinition.UNKNOWN_BUSINESS_TX))); assertThat(getFields(pointBuilder), hasEntry(Series.BusinessTransaction.FIELD_DURATION, (Object) duration)); }
assertThat(invocation.getPlatformIdent(), is(platformId)); assertThat(invocation.getMethodIdent(), is(methodId1)); assertThat(invocation.getSensorTypeIdent(), is(sensorTypeId)); assertThat(invocation.getDuration(), is(fourthTimerValue - firstTimerValue)); assertThat(invocation.getNestedSequences(), hasSize(1)); assertThat(invocation.getChildCount(), is(1L)); InvocationSequenceData child = invocation.getNestedSequences().iterator().next(); assertThat(child.getPlatformIdent(), is(platformId)); assertThat(child.getMethodIdent(), is(methodId2)); assertThat(child.getSensorTypeIdent(), is(sensorTypeId)); assertThat(child.getDuration(), is(thirdTimerValue - secondTimerValue)); assertThat(child.getNestedSequences(), is(empty())); assertThat(child.getParentSequence(), is(invocation)); assertThat(child.getChildCount(), is(0L)); assertThat(child.getSqlStatementData(), is(sqlStatementData));
assertThat(invocation.getPlatformIdent(), is(platformId)); assertThat(invocation.getMethodIdent(), is(methodId1)); assertThat(invocation.getSensorTypeIdent(), is(sensorTypeId)); assertThat(invocation.getDuration(), is(fourthTimerValue - firstTimerValue)); assertThat(invocation.getNestedSequences(), hasSize(1)); assertThat(invocation.getChildCount(), is(1L)); InvocationSequenceData child = invocation.getNestedSequences().iterator().next(); assertThat(child.getPlatformIdent(), is(platformId)); assertThat(child.getMethodIdent(), is(methodId2)); assertThat(child.getSensorTypeIdent(), is(sensorTypeId)); assertThat(child.getDuration(), is(thirdTimerValue - secondTimerValue)); assertThat(child.getNestedSequences(), is(empty())); assertThat(child.getParentSequence(), is(invocation)); assertThat(child.getChildCount(), is(0L)); assertThat(child.getLoggingData(), is(loggingData));
@Test public void sqlStatementDataMustReturnAEmptyListOfAggregatedDiagnosisDataWhenTheDurationIsZero() { long platformIdent = 108; long sensorTypeIdent = 1; Timestamp defDate = new Timestamp(new Date().getTime()); List<InvocationSequenceData> nestedSequences = new ArrayList<>(); InvocationSequenceData firstMethod = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 1L); SqlStatementData firstSqlStatementData = new SqlStatementData(); firstSqlStatementData.calculateExclusiveMin(200d); firstSqlStatementData.setExclusiveDuration(200d); firstSqlStatementData.setCount(1); firstMethod.setSqlStatementData(firstSqlStatementData); nestedSequences.add(firstMethod); InvocationSequenceData secondMethod = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(secondMethod); when(globalContext.getDuration()).thenReturn(new Double(0)); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Action method must return an array of AggregatedDiagnosisData not empty", timeWastingOperationsResults, hasSize(0)); }
/** * Extract data from the invocation and return it to the storage writer to process it. * * @param invocation * {@link InvocationSequenceData} */ private void extractDataFromInvocation(InvocationSequenceData invocation) { if (null != invocation.getTimerData()) { passToChainedProcessors(invocation.getTimerData()); } if (null != invocation.getSqlStatementData()) { passToChainedProcessors(invocation.getSqlStatementData()); } if (null != invocation.getExceptionSensorDataObjects()) { for (ExceptionSensorData exceptionSensorData : invocation.getExceptionSensorDataObjects()) { if (exceptionSensorData.getExceptionEvent() == ExceptionEvent.CREATED) { passToChainedProcessors(exceptionSensorData); } } } for (InvocationSequenceData child : invocation.getNestedSequences()) { extractDataFromInvocation(child); } }
@Test private void ifTheAggregatedObjectHasSQLDataAndIsDefinedInTheMapItMustBeAggregatedToTheDiagnosisAggregator() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 2L); diagnosisDataAggregationPerformer = new DiagnosisDataAggregationPerformer(); SqlStatementData sqlStatementData = new SqlStatementData(new Timestamp(10), 10, 10, 108L); sqlStatementData.setCount(1); sqlStatementData.setSql("blahblahblah"); invocationSequenceData.setSqlStatementData(sqlStatementData); HttpTimerData timerData = new HttpTimerData(new Timestamp(10), 10, 10, 108L); invocationSequenceData.setTimerData(timerData); Object key = new Pair<Long, String>(invocationSequenceData.getMethodIdent(), invocationSequenceData.getSqlStatementData().getSql()); diagnosisDataAggregationPerformer.diagnosisDataAggregationMap.put(key, alreadyAggregatedObject); diagnosisDataAggregationPerformer.aggregateInvocationSequenceData(invocationSequenceData); verify(alreadyAggregatedObject, times(1)).aggregate(invocationSequenceData); }
@Test public void rootCauseMustBeNullWhenMethodIdentIsEqualAndInvocationHasNotTimerData() { double highDuration = RANDOM.nextDouble() + 1000; List<InvocationSequenceData> nestedSequences = new ArrayList<InvocationSequenceData>(); nestedSequences.add(new InvocationSequenceData(DEF_DATE, PLATFORM_IDENT, SENSOR_TYPE_IDENT, METHOD_IDENT_EQUAL)); nestedSequences.add(new InvocationSequenceData(DEF_DATE, PLATFORM_IDENT, SENSOR_TYPE_IDENT, METHOD_IDENT_EQUAL)); when(problemContext.getCommonContext()).thenReturn(commonContext); when(commonContext.getMethodIdent()).thenReturn(1L); when(commonContext.getDuration()).thenReturn(highDuration); when(commonContext.getNestedSequences()).thenReturn(nestedSequences); AggregatedDiagnosisData rootCause = problemCauseRule.action(); assertThat("The returned root cause rule must be null", rootCause, nullValue()); }
@Test public void timerDataMustReturnAClonedElementOfTheGlobalContextIfItHasNoNestedSequences() { long platformIdent = 108; double highDuration = 2000; TimerData timerData = new TimerData(new Timestamp(System.currentTimeMillis()), 10L, 20L, 30L); timerData.calculateExclusiveMin(1); List<InvocationSequenceData> nestedSequences = new ArrayList<>(); when(globalContext.getTimerData()).thenReturn(timerData); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getMethodIdent()).thenReturn(platformIdent); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Method ident must be the same than the global context", timeWastingOperationsResults.get(0).getMethodIdent(), is(platformIdent)); }
/** * Create new InvocationIdentifier based on InvocationSequenceData. * * @param invocationSequenceData * the InvocationIdentifier the InvocationIdentifier is created */ public InvocationIdentifier(final InvocationSequenceData invocationSequenceData) { if (null == invocationSequenceData) { throw new IllegalArgumentException("Cannot create InvocationIdentifier when invocationSequenceData is null."); } this.methodIdent = invocationSequenceData.getMethodIdent(); this.invocationId = invocationSequenceData.getId(); TimerData timerData = null; if (InvocationSequenceDataHelper.hasSQLData(invocationSequenceData)) { timerData = invocationSequenceData.getSqlStatementData(); } else if (InvocationSequenceDataHelper.hasTimerData(invocationSequenceData)) { timerData = invocationSequenceData.getTimerData(); } else { throw new IllegalStateException("Timer data unknown."); } this.diagnosisTimerData = new DiagnosisTimerData(timerData); }
/** * Checks that the sequenceData have all the mandatory attributes. * * @param AggregatedDiagnosisInvocationData * Sequence data to check if has all the mandatory data. */ private void isAValidAggregatedDiagnosisData(AggregatedDiagnosisData AggregatedDiagnosisInvocationData) { for (InvocationSequenceData aggregatedSequence : AggregatedDiagnosisInvocationData.getRawInvocationsSequenceElements()) { assertThat("The aggregated sequence cannot be null", aggregatedSequence, notNullValue()); assertThat("Duration of the aggregated sequence cannot be null", aggregatedSequence.getDuration(), notNullValue()); assertThat("Start time of the aggregated cannot be null", aggregatedSequence.getStart(), notNullValue()); assertThat("End time of the aggregated cannot be null", aggregatedSequence.getEnd(), notNullValue()); assertThat("Child count of the aggregated sequence cannot be null", aggregatedSequence.getChildCount(), notNullValue()); assertThat("ApplicationId of the aggregated sequence cannot be null", aggregatedSequence.getApplicationId(), notNullValue()); assertThat("Business transaction id of the aggregated sequence cannot be null", aggregatedSequence.getBusinessTransactionId(), notNullValue()); } }
@Test private void ifTheAggregatedObjectHasHttpTimerDataAndIsDefinedInTheMapItMustBeAggregatedToTheDiagnosisAggregator() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 2L); diagnosisDataAggregationPerformer = new DiagnosisDataAggregationPerformer(); HttpTimerData timerData = new HttpTimerData(new Timestamp(10), 10, 10, 108L); HttpInfo httpInfo = new HttpInfo("URI", "requestMethod", "headerValue"); timerData.setHttpInfo(httpInfo); invocationSequenceData.setTimerData(timerData); Object key = new Pair<Long, String>(invocationSequenceData.getMethodIdent(), ((HttpTimerData) invocationSequenceData.getTimerData()).getHttpInfo().getUri()); diagnosisDataAggregationPerformer.diagnosisDataAggregationMap.put(key, alreadyAggregatedObject); diagnosisDataAggregationPerformer.aggregateInvocationSequenceData(invocationSequenceData); verify(alreadyAggregatedObject, times(1)).aggregate(invocationSequenceData); } }
/** * Calculates the duration starting from this invocation sequence data element. Includes span * duration as last resource if the span ident exists on the data. * * @param data * the <code>InvocationSequenceData</code> object. * @param spanService * Span service providing the additional span information if needed. * @return the duration starting from this invocation sequence data element. */ public static double calculateDuration(InvocationSequenceData data, ISpanService spanService) { if (InvocationSequenceDataHelper.hasTimerData(data)) { return data.getTimerData().getDuration(); } else if (InvocationSequenceDataHelper.hasSQLData(data)) { return data.getSqlStatementData().getDuration(); } else if ((null != spanService) && hasSpanIdent(data)) { Span span = spanService.get(data.getSpanIdent()); if ((span != null) && !References.FOLLOWS_FROM.equals(span.getReferenceType())) { return span.getDuration(); } } if (InvocationSequenceDataHelper.isRootElementInSequence(data)) { return data.getDuration(); } return -1.0d; }