/** * Checks whether this data object contains SQL data. * * @param data * the <code>InvocationSequenceData</code> object. * @return whether this data object contains SQL data. */ public static boolean hasSQLData(InvocationSequenceData data) { return (null != data.getSqlStatementData()) && (1 == data.getSqlStatementData().getCount()); }
/** * Processes all the {@link SqlStatementData}s in the given invocations creating the list of the * existing statement and calculating the total duration of the statements. * * @param invocationSequenceDataList * Input as list of invocations * @param sqlStatementDataList * List where results will be stored. Needed because of reflection. * @param totalDuration * {@link MutableDouble} where total duration will be stored. */ public static void collectSqlsInInvocations(List<InvocationSequenceData> invocationSequenceDataList, List<SqlStatementData> sqlStatementDataList, MutableDouble totalDuration) { for (InvocationSequenceData invocationSequenceData : invocationSequenceDataList) { if (null != invocationSequenceData.getSqlStatementData()) { sqlStatementDataList.add(invocationSequenceData.getSqlStatementData()); totalDuration.add(invocationSequenceData.getSqlStatementData().getDuration()); } if (CollectionUtils.isNotEmpty(invocationSequenceDataList)) { collectSqlsInInvocations(invocationSequenceData.getNestedSequences(), sqlStatementDataList, totalDuration); } } }
/** * Aggregate by adding a new InvocationSequenceData. * * @param invocationSequenceData * InvocationSequenceData to be added to the aggregation */ public void aggregate(InvocationSequenceData invocationSequenceData) { TimerData timerData = null; switch (sourceType) { case DATABASE: timerData = invocationSequenceData.getSqlStatementData(); break; case HTTP: case TIMERDATA: timerData = invocationSequenceData.getTimerData(); break; default: throw new IllegalStateException("Source type unknown."); } // aggregate the timer data if (aggregatedDiagnosisTimerData == null) { aggregatedDiagnosisTimerData = new AggregatedDiagnosisTimerData(timerData); } else { aggregatedDiagnosisTimerData.aggregate(timerData); } // save involved invocation rawInvocationsSequenceElements.add(invocationSequenceData); }
/** * Returns the {@link SqlStatementData} or the {@link TimerData} of the InvocationSequenceData. * * @param data * the <code>InvocationSequenceData</code> object. * @return the timerData of this object. */ public static TimerData getTimerDataOrSQLData(final InvocationSequenceData data) { if (hasSQLData(data)) { return data.getSqlStatementData(); } else if (hasTimerData(data)) { return data.getTimerData(); } return null; }
if (null == invocationSequenceData.getSqlStatementData()) { invocationSequenceData.setSqlStatementData((SqlStatementData) dataObject);
/** * {@inheritDoc} */ @Override public Object execute(ExecutionEvent event) throws ExecutionException { Object firstElement = ((StructuredSelection) HandlerUtil.getCurrentSelection(event)).getFirstElement(); if (firstElement instanceof InvocationSequenceData) { InvocationSequenceData data = (InvocationSequenceData) firstElement; SqlStatementData sqlStatementData = data.getSqlStatementData(); if (null == sqlStatementData) { return null; } ClipboardUtil.textToClipboard(HandlerUtil.getActiveShell(event).getDisplay(), data.getSqlStatementData().getSqlWithParameterValues()); } if (firstElement instanceof SqlStatementData) { SqlStatementData sqlStatementData = (SqlStatementData) firstElement; ClipboardUtil.textToClipboard(HandlerUtil.getActiveShell(event).getDisplay(), sqlStatementData.getSqlWithParameterValues()); } return null; }
/** * 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()); }
/** * 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); }
/** * Process SQL statement if one exists in the invData object and passes it to the chained * processors. * * @param entityManager * {@link EntityManager} needed for DB persistence. * @param invData * Invocation data to be processed. * @param topInvocationParent * Top invocation object. */ private void processSqlStatementData(EntityManager entityManager, InvocationSequenceData invData, InvocationSequenceData topInvocationParent) { SqlStatementData sqlStatementData = invData.getSqlStatementData(); if (null != sqlStatementData) { topInvocationParent.setNestedSqlStatements(Boolean.TRUE); sqlStatementData.addInvocationParentId(topInvocationParent.getId()); passToChainedProcessors(sqlStatementData, entityManager); } }
/** * Gets the exclusive duration of the invocation sequence data element, in case the element has * not timer data or has not the exclusive time available it will returns 0. * * @param data * the <code>InvocationSequenceData</code> object. * @return the exclusive duration of this invocation sequence data element or 0. */ public static double getExclusiveDuration(InvocationSequenceData data) { TimerData timerData; if (InvocationSequenceDataHelper.hasSQLData(data)) { timerData = data.getSqlStatementData(); } else if (InvocationSequenceDataHelper.hasTimerData(data)) { timerData = data.getTimerData(); } else { return 0.0; } if (timerData.isExclusiveTimeDataAvailable()) { return timerData.getExclusiveDuration(); } else { return 0.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 private void ifTheAggregatedObjectIsNotDefineInTheMapItMustBeAggregated() { 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); TimerData timerData = new TimerData(new Timestamp(10), 10, 10, 108L); invocationSequenceData.setTimerData(timerData); Object key = new Pair<Long, String>(invocationSequenceData.getMethodIdent(), invocationSequenceData.getSqlStatementData().getSql()); AggregatedDiagnosisData alreadyAggregatedObject = new AggregatedDiagnosisData(SourceType.TIMERDATA, invocationSequenceData, key); diagnosisDataAggregationPerformer.diagnosisDataAggregationMap.put(key, alreadyAggregatedObject); InvocationSequenceData secondInvocationSequenceData = new InvocationSequenceData(new Timestamp(10L), 10L, 20L, 2L); secondInvocationSequenceData.setTimerData(timerData); List<InvocationSequenceData> invocationSequenceDataList = new ArrayList<>(); invocationSequenceDataList.add(invocationSequenceData); invocationSequenceDataList.add(secondInvocationSequenceData); diagnosisDataAggregationPerformer.aggregateInvocationSequenceDataList(invocationSequenceDataList); List<AggregatedDiagnosisData> resultList = diagnosisDataAggregationPerformer.getAggregationResultList(); assertThat("The list must have 2 aggregated objects", resultList.size(), is(2)); assertThat("The first aggregated object must have the same method ident that the invocationSequenceData", resultList.get(0).getMethodIdent(), equalTo(invocationSequenceData.getMethodIdent())); assertThat("The second aggregated object must have the same method ident that the secondInvocationSequenceData", resultList.get(1).getMethodIdent(), equalTo(secondInvocationSequenceData.getMethodIdent())); } }
assertThat(invocation.getChildCount(), is(0L)); assertThat(invocation.getTimerData(), is(timerData)); assertThat(invocation.getSqlStatementData(), is(sqlStatementData)); assertThat(invocation.getSpanIdent(), is(nullValue()));
when(commonContext.getParentSequence()).thenReturn(parentSequence); when(commonContext.getTimerData()).thenReturn(timerDataSql); when(commonContext.getSqlStatementData()).thenReturn(timerDataSql); when(rootCause.getRawInvocationsSequenceElements()).thenReturn(rawInvocations); when(rootCause.getMethodIdent()).thenReturn(methodIdentEqual);
} else if (null != child.getSqlStatementData()) { exclusiveDurationDelta += child.getSqlStatementData().getDuration(); } else { exclusiveDurationDelta += InvocationSequenceDataHelper.computeNestedDuration(child);
when(commonContext.getTimerData()).thenReturn(firstMethod.getTimerData()); when(commonContext.getDuration()).thenReturn(firstMethod.getDuration()); when(commonContext.getSqlStatementData()).thenReturn(timerDataSql); when(problemContext.getCauseInvocations()).thenReturn(detectedProblemContext.getNestedSequences());
/** * 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; }
/** * Get key for aggregation. * * @param invocationSequenceData * invocationSequenceData to key should be determined * @return key as object */ public Object getAggregationKey(InvocationSequenceData invocationSequenceData) { if (InvocationSequenceDataHelper.hasSQLData(invocationSequenceData)) { return new Pair<Long, String>(invocationSequenceData.getMethodIdent(), invocationSequenceData.getSqlStatementData().getSql()); } else if (InvocationSequenceDataHelper.hasHttpTimerData(invocationSequenceData)) { return new Pair<Long, String>(invocationSequenceData.getMethodIdent(), ((HttpTimerData) invocationSequenceData.getTimerData()).getHttpInfo().getUri()); } else { return invocationSequenceData.getMethodIdent(); } }
/** * 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; }