/** * {@inheritDoc} */ @Override public boolean canBeProcessed(DefaultData defaultData) { return diagnosisEnabled && influxActive && (defaultData instanceof InvocationSequenceData) && (((InvocationSequenceData) defaultData).getDuration() > baseline); }
/** * Rule execution. * * @return DIAGNOSIS_TAG_GLOBAL_CONTEXT */ @Action(resultTag = RuleConstants.DIAGNOSIS_TAG_GLOBAL_CONTEXT) public InvocationSequenceData action() { InvocationSequenceData childWithMaxDuration = invocationSequenceRoot; InvocationSequenceData currentInvocationSequence; double traceDuration = invocationSequenceRoot.getDuration(); // Dig deeper in the tree as long as there is a dominating call. do { currentInvocationSequence = childWithMaxDuration; childWithMaxDuration = getChildWithMaxDuration(currentInvocationSequence); } while ((null != childWithMaxDuration) && isDominatingCall(childWithMaxDuration.getDuration(), traceDuration)); return currentInvocationSequence; }
@Test private void currentGlobalContextRuleMustNotBeNull() { when(invocationSequenceRoot.getDuration()).thenReturn(HIGH_DURATION); InvocationSequenceData currentGlobalContextRule = globalContextRule.action(); assertThat("Invocation sequence root must not be null", currentGlobalContextRule, notNullValue()); }
/** * Gets the {@link AggregatedDiagnosisData} with all the TimeWastingOperations. Just the * {@link InvocationSequenceData} with highest exclusive time are considered as * TimeWastingOperations. * * @param timeWastingOperationsCandidates * {@link AggregatedDiagnosisData} which are considered as candidates to be * TimeWastingOperations. * @return Returns the list of {@link AggregatedDiagnosisData} which are TimeWastingOperations. */ private List<AggregatedDiagnosisData> getTimeWastingOperations(List<AggregatedDiagnosisData> timeWastingOperationsCandidates) { List<AggregatedDiagnosisData> timeWastingOperations = new ArrayList<>(); double sumExecTime = 0; double globalContextDuration = globalContext.getDuration(); for (AggregatedDiagnosisData aggregatedDiagnosisData : timeWastingOperationsCandidates) { double aggregatedDataExclusiveDuration = aggregatedDiagnosisData.getAggregatedDiagnosisTimerData().getExclusiveDuration(); if ((sumExecTime < (PROPORTION * globalContextDuration)) || (aggregatedDataExclusiveDuration > baseline) || (aggregatedDiagnosisData.getAggregatedDiagnosisTimerData().getExclusiveCount() >= METHODEXECUTIONCOUNT)) { // increase sumExclusiveTime by duration of Time Wasting Operation. sumExecTime += aggregatedDataExclusiveDuration; timeWastingOperations.add(aggregatedDiagnosisData); } } return timeWastingOperations; }
@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)); }
/** * 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 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)); }
@Test public void timerDataMustReturnANotEmptyListOfAggregatedDiagnosisDataWhenTheDurationIsTooLong() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); firstSeqTimerData.setExclusiveDuration(200d); firstChildSequence.setTimerData(firstSeqTimerData); InvocationSequenceData secondChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstChildSequence); nestedSequences.add(secondChildSequence); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Action method must return a list of AggregatedDiagnosisData not empty", timeWastingOperationsResults, not(hasSize(0))); }
@Test public void timerDataMustReturnANotNullListOfAggregatedDiagnosisData() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); firstSeqTimerData.setExclusiveDuration(200d); firstChildSequence.setTimerData(firstSeqTimerData); InvocationSequenceData secondChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstChildSequence); nestedSequences.add(secondChildSequence); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("The returned list of AggregatedDiagnosisData must not be null", timeWastingOperationsResults, notNullValue()); }
@Test public void timerDataMustReturnAListOfAggregatedDiagnosisDataWithOneElement() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); firstSeqTimerData.setExclusiveDuration(200d); firstChildSequence.setTimerData(firstSeqTimerData); InvocationSequenceData secondChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstChildSequence); nestedSequences.add(secondChildSequence); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Action method must return a list with one AggregatedDiagnosisData", timeWastingOperationsResults, hasSize(1)); }
@Test private void currentGlobalContextRuleMustNotBeTheSequenceWithMaximumDuration() { long methodIdent = 108L; double baseline = 1000d; globalContextRule.baseline = baseline; Timestamp defDate = new Timestamp(new Date().getTime()); Random random = new Random(); long platformIdent = random.nextLong(); long sensorTypeIdent = random.nextLong(); List<InvocationSequenceData> nestedSequences = new ArrayList<>(); InvocationSequenceData firstChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, methodIdent); firstChildSequence.setDuration(200d); InvocationSequenceData higherDurationChild = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, methodIdent); higherDurationChild.setDuration(3000d); InvocationSequenceData secondChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, methodIdent); secondChildSequence.setDuration(500d); nestedSequences.add(firstChildSequence); nestedSequences.add(higherDurationChild); nestedSequences.add(secondChildSequence); when(invocationSequenceRoot.getDuration()).thenReturn(HIGH_DURATION); when(invocationSequenceRoot.getNestedSequences()).thenReturn(nestedSequences); InvocationSequenceData currentGlobalContextRule = globalContextRule.action(); assertThat("The returned global context rule must not be the child with higher duration", currentGlobalContextRule, not(is(higherDurationChild))); }
@Test public void timerDataMustReturnAValidListOfAggregatedDiagnosisData() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); firstSeqTimerData.setExclusiveDuration(200d); firstChildSequence.setTimerData(firstSeqTimerData); nestedSequences.add(firstChildSequence); InvocationSequenceData secondChildSequence = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(secondChildSequence); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperations = timeWastingOperationsRule.action(); assertThat("Action method must return a list of AggregatedDiagnosisData not empty", timeWastingOperations, not(hasSize(0))); for (AggregatedDiagnosisData AggregatedDiagnosisInvocationData : timeWastingOperations) { isAValidAggregatedDiagnosisData(AggregatedDiagnosisInvocationData); } }
@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)); }
@Test public void sqlStatementDataMustReturnANotEmptyListOfAggregatedDiagnosisDataWhenTheDurationIsTooLong() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); InvocationSequenceData secondMethod = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstMethod); nestedSequences.add(secondMethod); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Action method must return a group of AggregatedDiagnosisData not empty", timeWastingOperationsResults, not(hasSize(0))); }
@Test public void sqlStatementDataMustReturnANotNullListOfAggregatedDiagnosisData() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); InvocationSequenceData secondMethod = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstMethod); nestedSequences.add(secondMethod); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("The returned list of AggregatedDiagnosisData must not be null", timeWastingOperationsResults, notNullValue()); }
@Test public void sqlStatementDataMustReturnAListOfAggregatedDiagnosisDataWithOneElement() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); InvocationSequenceData secondMethod = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstMethod); nestedSequences.add(secondMethod); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Action method must return a list with one AggregatedDiagnosisData", timeWastingOperationsResults, hasSize(1)); }
@Test public void rootCauseMustBeNotNullWhenMethodIdentIsEqualAndTheInvocationHasTimerData() { double highDuration = RANDOM.nextDouble() + 1000; List<InvocationSequenceData> nestedSequences = new ArrayList<InvocationSequenceData>(); InvocationSequenceData firstChildSequenceData = new InvocationSequenceData(DEF_DATE, PLATFORM_IDENT, SENSOR_TYPE_IDENT, METHOD_IDENT_EQUAL); TimerData timerData = new TimerData(new Timestamp(System.currentTimeMillis()), 10L, 20L, 30L); timerData.calculateExclusiveMin(RANDOM.nextDouble()); timerData.setExclusiveDuration(RANDOM.nextDouble()); firstChildSequenceData.setTimerData(timerData); InvocationSequenceData secondChildSequenceData = new InvocationSequenceData(DEF_DATE, PLATFORM_IDENT, SENSOR_TYPE_IDENT, METHOD_IDENT_EQUAL); timerData.calculateExclusiveMin(RANDOM.nextDouble()); timerData.setExclusiveDuration(RANDOM.nextDouble()); secondChildSequenceData.setTimerData(timerData); nestedSequences.add(firstChildSequenceData); nestedSequences.add(secondChildSequenceData); when(problemContext.getCommonContext()).thenReturn(commonContext); when(commonContext.getMethodIdent()).thenReturn(1L); when(commonContext.getDuration()).thenReturn(highDuration); when(problemContext.getCauseInvocations()).thenReturn(nestedSequences); AggregatedDiagnosisData rootCause = problemCauseRule.action(); assertThat("The returned root cause rule must not be null", rootCause, notNullValue()); }
@Test public void sqlStatementDataMustReturnAValidListOfAggregatedDiagnosisData() { long platformIdent = 108; long sensorTypeIdent = 1; double highDuration = 2000; 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); InvocationSequenceData secondMethod = new InvocationSequenceData(defDate, platformIdent, sensorTypeIdent, 2L); nestedSequences.add(firstMethod); nestedSequences.add(secondMethod); when(globalContext.getDuration()).thenReturn(highDuration); when(globalContext.getNestedSequences()).thenReturn(nestedSequences); List<AggregatedDiagnosisData> timeWastingOperationsResults = timeWastingOperationsRule.action(); assertThat("Action method must return a list of AggregatedDiagnosisData not empty", timeWastingOperationsResults, not(hasSize(0))); for (AggregatedDiagnosisData AggregatedDiagnosisInvocationData : timeWastingOperationsResults) { isAValidAggregatedDiagnosisData(AggregatedDiagnosisInvocationData); } }
/** * {@inheritDoc} */ @Override protected void addFields(InvocationSequenceData data, Builder builder) { builder.addField(Series.BusinessTransaction.FIELD_DURATION, data.getDuration()); builder.addField(Series.BusinessTransaction.FIELD_TRACE_ID, data.getId()); if (InvocationSequenceDataHelper.hasHttpTimerData(data) && HttpTimerDataHelper.hasResponseCode((HttpTimerData) data.getTimerData())) { builder.addField(Series.BusinessTransaction.FIELD_HTTP_RESPONSE_CODE, ((HttpTimerData) data.getTimerData()).getHttpResponseStatus()); } }