/** * Aggregate the InvocationSequenceData to the AggregatedDiagnosisData. * * @param aggregatedObject * aggregatedObject * @param objectToAdd * object to add to aggregation */ public void aggregate(AggregatedDiagnosisData aggregatedObject, InvocationSequenceData objectToAdd) { aggregatedObject.aggregate(objectToAdd); }
/** * Aggregate the list of InvocationSequenceData. * * @param invocationSequenceDataList * list of invocationSequenceDataList to be aggregated */ public void aggregateInvocationSequenceDataList(List<InvocationSequenceData> invocationSequenceDataList) { for (InvocationSequenceData invocationSequenceData : invocationSequenceDataList) { aggregateInvocationSequenceData(invocationSequenceData); } }
/** * Checks whether the passed {@link #InvocationSequenceData} is a <code>Root * Cause</code>. * * @param invocation * The {@link InvocationSequenceData} that is investigated. * @return Whether the {@link InvocationSequenceData} is a <code>Root Cause</code>. */ private boolean isCauseInvocation(InvocationSequenceData invocation) { Object key = diagnosisDataAggregator.getAggregationKey(invocation); if (key.equals(rootCause.getAggregationKey())) { return true; } return false; }
@Test private void musteReturnAnInstanceWithHttpSourceTypeDataIfTheTimerDataIsHttpTimerData() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 108L); HttpTimerData timerData = new HttpTimerData(); invocationSequenceData.setTimerData(timerData); AggregatedDiagnosisData aggregatedDiagnosisData = DiagnosisDataAggregator.getInstance().getAggregatedDiagnosisData(invocationSequenceData); assertThat("The object must have HTTP as source type", aggregatedDiagnosisData.getSourceType(), is(SourceType.HTTP)); }
@Test private void ifTheAggregatedObjectIsNotDefineInTheMapItMustBeAggregated() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 2L); diagnosisDataAggregationPerformer = new DiagnosisDataAggregationPerformer(); TimerData timerData = new TimerData(new Timestamp(10), 10, 10, 108L); invocationSequenceData.setTimerData(timerData); diagnosisDataAggregationPerformer.aggregateInvocationSequenceData(invocationSequenceData); List<AggregatedDiagnosisData> resultList = diagnosisDataAggregationPerformer.getAggregationResultList(); assertThat("The aggregated object must have the same method ident that the invocationSequenceData", resultList.get(0).getMethodIdent(), equalTo(invocationSequenceData.getMethodIdent())); }
@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); } }
/** * Add one InvocationSequenceData to the aggregation. * * @param invocationSequenceData * invocationSequenceData to be aggregated */ public void aggregateInvocationSequenceData(InvocationSequenceData invocationSequenceData) { Object key = DIAGNOSIS_DATA_AGGREGATOR.getAggregationKey(invocationSequenceData); AggregatedDiagnosisData aggregatedObject = diagnosisDataAggregationMap.get(key); if (null != aggregatedObject) { DIAGNOSIS_DATA_AGGREGATOR.aggregate(aggregatedObject, invocationSequenceData); } else { aggregatedObject = DIAGNOSIS_DATA_AGGREGATOR.getAggregatedDiagnosisData(invocationSequenceData); diagnosisDataAggregationMap.put(key, aggregatedObject); } }
if ((causeCandidatesChecked > 1) && (causeCandidatesChecked < causeCandidates.size())) { double mean = sumExclusiveTime / causeCandidatesChecked; double[] durations = new double[rootCause.size()]; int i = 0; for (InvocationSequenceData invocation : rootCause.getRawInvocationsSequenceElements()) { durations[i] = DiagnosisHelper.getExclusiveDuration(invocation); i++; double duration = DiagnosisHelper.getExclusiveDuration(invocation); if (duration > lowerThreshold) { diagnosisDataAggregator.aggregate(rootCause, invocation); } else { break;
/** * Convert a {@link InvocationSequenceData} to a {@link AggregatedDiagnosisData}. * * @param invocationSequenceData * input invocationSequenceData * @return AggregatedDiagnosisData based on invocationSequenceData */ public AggregatedDiagnosisData getAggregatedDiagnosisData(InvocationSequenceData invocationSequenceData) { if (InvocationSequenceDataHelper.hasHttpTimerData(invocationSequenceData)) { return new AggregatedDiagnosisData(SourceType.HTTP, invocationSequenceData, getAggregationKey(invocationSequenceData)); } else if (InvocationSequenceDataHelper.hasSQLData(invocationSequenceData)) { return new AggregatedDiagnosisData(SourceType.DATABASE, invocationSequenceData, getAggregationKey(invocationSequenceData)); } else if (InvocationSequenceDataHelper.hasTimerData(invocationSequenceData)) { return new AggregatedDiagnosisData(SourceType.TIMERDATA, invocationSequenceData, getAggregationKey(invocationSequenceData)); } else { throw new IllegalArgumentException("No timer data available!"); } }
/** * Rule execution. * * @return DIAGNOSIS_TAG_CAUSE_STRUCTURE */ @Action(resultTag = RuleConstants.DIAGNOSIS_TAG_CAUSE_STRUCTURE) public CauseStructure action() { // In case there is just one Root Cause method. if (rootCause.size() == 1) { return new CauseStructure(CauseType.SINGLE, rootCause.getSourceType()); } // The Root Causes are called either recursive if (calculateMaxRecursionDepth() > 1) { return new CauseStructure(CauseType.RECURSIVE, rootCause.getSourceType()); // or iterative. } else { return new CauseStructure(CauseType.ITERATIVE, rootCause.getSourceType()); } }
@Test(expectedExceptions = IllegalArgumentException.class) private void musteReturnAnExceptionIfThereIsNoTimerData() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 108L); DiagnosisDataAggregator.getInstance().getAggregatedDiagnosisData(invocationSequenceData); }
/** * Sorts list with aggregated {@link InvocationSequenceData} with the help of the summed * up exclusive times. */ @Override public int compare(AggregatedDiagnosisData o1, AggregatedDiagnosisData o2) { return Double.compare(o2.getAggregatedDiagnosisTimerData().getExclusiveDuration(), o1.getAggregatedDiagnosisTimerData().getExclusiveDuration()); } });
/** * Creates list with clusters. For each InvocationSequenceData in the Time Wasting Operation a * cluster is build initially. * * @return Returns a list of causeCluster. */ private List<CauseCluster> populateCauseCluster() { List<InvocationSequenceData> causeInvocations = timeWastingOperation.getRawInvocationsSequenceElements(); List<CauseCluster> causeClusters = new LinkedList<>(); for (InvocationSequenceData invocation : causeInvocations) { causeClusters.add(new CauseCluster(invocation)); } return causeClusters; }
@Test private void musteReturnAnInstanceWithTimerDataSourceTypeDataIfTheTimerDataIsTimerData() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 108L); TimerData timerData = new TimerData(); invocationSequenceData.setTimerData(timerData); AggregatedDiagnosisData aggregatedDiagnosisData = DiagnosisDataAggregator.getInstance().getAggregatedDiagnosisData(invocationSequenceData); assertThat("The object must have TIMERDATA as source type", aggregatedDiagnosisData.getSourceType(), is(SourceType.TIMERDATA)); }
@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); }
/** * Default constructor. * * @param sourceType * timer sourceType * @param invocationSequenceData * invocationSequenceData is used to aggregate to AggregatedDiagnosisData * @param aggregationKey * aggregationKey of AggregatedDiagnosisData */ public AggregatedDiagnosisData(final SourceType sourceType, final InvocationSequenceData invocationSequenceData, final Object aggregationKey) { this.sourceType = sourceType; this.methodIdent = invocationSequenceData.getMethodIdent(); this.aggregationKey = aggregationKey; aggregate(invocationSequenceData); }
/** * Gets the most significant cluster in the list. * * @param causeClusters * List of clusters to get the most significant. * @return Returns the most significant cluster in the list. */ private CauseCluster getSignificantCluster(List<CauseCluster> causeClusters) { // Checks if there is already a cluster with higher duration ratio // from overallExclusiveDuration. CauseCluster significantCluster = getHighDurationCluster(causeClusters, timeWastingOperation.getAggregatedDiagnosisTimerData().getExclusiveDuration()); // Iterates as long as there is no significantCluster. while ((null == significantCluster) && !stopClustering) { calculateDistancesToNextCluster(causeClusters); causeClusters = mergeClusters(causeClusters); significantCluster = getHighDurationCluster(causeClusters, timeWastingOperation.getAggregatedDiagnosisTimerData().getExclusiveDuration()); } // This rule does not return the Problem Context directly, but the significant cluster. // The Problem Context is the deepest node in the invocation tree that subsumes all // InvocationSequenceData the significant cluster holds and can be accessed via // cluster.getCommonContext(). return significantCluster; }
/** * 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 musteReturnAnInstanceWithDataBaseSourceTypeDataIfHasSqlData() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 108L); SqlStatementData sqlStatementData = new SqlStatementData(new Timestamp(10), 10, 10, 108L); sqlStatementData.setCount(1); sqlStatementData.setSql("blahblahblah"); invocationSequenceData.setSqlStatementData(sqlStatementData); AggregatedDiagnosisData aggregatedDiagnosisData = DiagnosisDataAggregator.getInstance().getAggregatedDiagnosisData(invocationSequenceData); assertThat("The object must have DATABASE as source type", aggregatedDiagnosisData.getSourceType(), is(SourceType.DATABASE)); }
@Test private void mustReturnAnInstanceWithDataBaseSourceTypeDataIfHasSqlDataAndTimerData() { InvocationSequenceData invocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 108L); SqlStatementData sqlStatementData = new SqlStatementData(new Timestamp(10), 10, 10, 108L); sqlStatementData.setCount(1); sqlStatementData.setSql("blahblahblah"); invocationSequenceData.setSqlStatementData(sqlStatementData); TimerData timerData = new TimerData(new Timestamp(10), 10L, 20, 108L); invocationSequenceData.setTimerData(timerData); AggregatedDiagnosisData aggregatedDiagnosisData = DiagnosisDataAggregator.getInstance().getAggregatedDiagnosisData(invocationSequenceData); assertThat("The object must have DATABASE as source type", aggregatedDiagnosisData.getSourceType(), is(SourceType.DATABASE)); } }