package rocks.inspectit.shared.all.communication.data;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import rocks.inspectit.shared.all.cmr.cache.IObjectSizes;
import rocks.inspectit.shared.all.communication.MethodSensorData;
import rocks.inspectit.shared.all.tracing.data.ISpanIdentAware;
import rocks.inspectit.shared.all.tracing.data.SpanIdent;
/**
* The invocation sequence data object which is used to store the path of method invocations from
* instrumented methods.
*
* Notice that the <code>InvocationSequenceDataHelper</code> class provides utility methods to query
* <code>InvocationSequenceData</code> instances.
*
* @author Patrice Bouillet
* @see rocks.inspectit.shared.cs.communication.data.InvocationSequenceDataHelper
*/
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class InvocationSequenceData extends MethodSensorData implements ISpanIdentAware {
/**
* The serial version UID.
*/
private static final long serialVersionUID = 1388734093735447105L;
/**
* The nested invocation traces are stored in this list.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
private List<InvocationSequenceData> nestedSequences = new ArrayList<InvocationSequenceData>(0);
/**
* The parent sequence of this sequence if there is any.
*/
@JsonIgnore
private InvocationSequenceData parentSequence;
/**
* The associated timer data object. Can be <code>null</code>.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
private TimerData timerData;
/**
* The associated sql statement data object. Can be <code>null</code>.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
private SqlStatementData sqlStatementData;
/**
* The associated exception sensor data object. Can be <code>null</code>.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
private List<ExceptionSensorData> exceptionSensorDataObjects;
/**
* The associated logging data. Can be <code>null</code>.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
private LoggingData loggingData;
/**
* The information about the span the invocation is belonging to or invocation is calling to.
* Can be <code>null</code>.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
private SpanIdent spanIdent;
/**
* The position if parent sequence is not <code>null</code>.
*/
@JsonIgnore
private long position;
/**
* The duration of this invocation sequence.
*/
private double duration;
/**
* The start time of this invocation sequence.
*/
@JsonIgnore
private double start;
/**
* The end time of this invocation sequence.
*/
@JsonIgnore
private double end;
/**
* The count of the nested sequences (all levels).
*/
private long childCount = 0;
/**
* If the {@link SqlStatementData} is available in this or one of the nested invocations.
*/
@JsonIgnore
private Boolean nestedSqlStatements;
/**
* If the {@link ExceptionSensorData} is available in this or one of the nested invocations.
*/
@JsonIgnore
private Boolean nestedExceptions;
/**
* Identifier of the application this invocation sequence belongs to.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_DEFAULT)
private int applicationId = 0;
/**
* Identifier of the business transaction this invocation sequence belongs to.
*/
@JsonSerialize(include = JsonSerialize.Inclusion.NON_DEFAULT)
private int businessTransactionId = 0;
/**
* Default no-args constructor.
*/
public InvocationSequenceData() {
}
/**
* Creates a new instance.
*
* @param timeStamp
* the timestamp.
* @param platformIdent
* the platform identifier.
* @param sensorTypeIdent
* the sensor type identifier.
* @param methodIdent
* the method identifier.
*/
public InvocationSequenceData(Timestamp timeStamp, long platformIdent, long sensorTypeIdent, long methodIdent) {
super(timeStamp, platformIdent, sensorTypeIdent, methodIdent);
}
/**
* Gets {@link #nestedSequences}.
*
* @return {@link #nestedSequences}
*/
public List<InvocationSequenceData> getNestedSequences() {
return nestedSequences;
}
/**
* Sets {@link #nestedSequences}.
*
* @param nestedSequences
* New value for {@link #nestedSequences}
*/
public void setNestedSequences(List<InvocationSequenceData> nestedSequences) {
this.nestedSequences = nestedSequences;
}
/**
* Gets {@link #parentSequence}.
*
* @return {@link #parentSequence}
*/
public InvocationSequenceData getParentSequence() {
return parentSequence;
}
/**
* Sets {@link #parentSequence}.
*
* @param parentSequence
* New value for {@link #parentSequence}
*/
public void setParentSequence(InvocationSequenceData parentSequence) {
this.parentSequence = parentSequence;
}
/**
* Gets {@link #timerData}.
*
* @return {@link #timerData}
*/
public TimerData getTimerData() {
return timerData;
}
/**
* Sets {@link #timerData}.
*
* @param timerData
* New value for {@link #timerData}
*/
public void setTimerData(TimerData timerData) {
this.timerData = timerData;
}
/**
* Gets {@link #sqlStatementData}.
*
* @return {@link #sqlStatementData}
*/
public SqlStatementData getSqlStatementData() {
return sqlStatementData;
}
/**
* Sets {@link #sqlStatementData}.
*
* @param sqlStatementData
* New value for {@link #sqlStatementData}
*/
public void setSqlStatementData(SqlStatementData sqlStatementData) {
this.sqlStatementData = sqlStatementData;
}
/**
* Gets {@link #loggingData}.
*
* @return {@link #loggingData}
*/
public LoggingData getLoggingData() {
return loggingData;
}
/**
* Sets {@link #loggingData}.
*
* @param loggingData
* New value for {@link #loggingData}
*/
public void setLoggingData(LoggingData loggingData) {
this.loggingData = loggingData;
}
/**
* Gets {@link #spanIdent}.
*
* @return {@link #spanIdent}
*/
@Override
public SpanIdent getSpanIdent() {
return this.spanIdent;
}
/**
* Sets {@link #spanIdent}.
*
* @param spanIdent
* New value for {@link #spanIdent}
*/
public void setSpanIdent(SpanIdent spanIdent) {
this.spanIdent = spanIdent;
}
/**
* @param position
* the position to set
*/
public void setPosition(long position) {
this.position = position;
}
/**
* @return the position
*/
public long getPosition() {
return position;
}
/**
* @param duration
* the duration to set
*/
public void setDuration(double duration) {
this.duration = duration;
}
/**
* @return the duration
*/
public double getDuration() {
return duration;
}
/**
* @return the start time of the invocation sequence
*/
public double getStart() {
return start;
}
/**
*
* @param start
* the start time of the invocation sequence
*/
public void setStart(double start) {
this.start = start;
}
/**
*
* @return the end time of the invocation sequence
*/
public double getEnd() {
return end;
}
/**
* Gets {@link #exceptionSensorDataObjects}.
*
* @return {@link #exceptionSensorDataObjects}
*/
public List<ExceptionSensorData> getExceptionSensorDataObjects() {
return exceptionSensorDataObjects;
}
/**
* Sets {@link #exceptionSensorDataObjects}.
*
* @param exceptionSensorDataObjects
* New value for {@link #exceptionSensorDataObjects}
*/
public void setExceptionSensorDataObjects(List<ExceptionSensorData> exceptionSensorDataObjects) {
this.exceptionSensorDataObjects = exceptionSensorDataObjects;
}
/**
* Adds the given exception data to this invocation sequence.
*
* @param data
* the exception data to add.
*/
public void addExceptionSensorData(ExceptionSensorData data) {
if (null == exceptionSensorDataObjects) {
exceptionSensorDataObjects = new ArrayList<ExceptionSensorData>();
}
exceptionSensorDataObjects.add(data);
}
/**
*
* @param end
* the end time of the invocation sequence
*/
public void setEnd(double end) {
this.end = end;
}
/**
* @param childCount
* the childCount to set
*/
public void setChildCount(long childCount) {
this.childCount = childCount;
}
/**
* @return the childCount
*/
public long getChildCount() {
return childCount;
}
/**
* Gets {@link #nestedSqlStatements}.
*
* @return {@link #nestedSqlStatements}
*/
public Boolean isNestedSqlStatements() {
return nestedSqlStatements;
}
/**
* Sets {@link #nestedSqlStatements}.
*
* @param nestedSqlStatements
* New value for {@link #nestedSqlStatements}
*/
public void setNestedSqlStatements(Boolean nestedSqlStatements) {
this.nestedSqlStatements = nestedSqlStatements;
}
/**
* Gets {@link #nestedExceptions}.
*
* @return {@link #nestedExceptions}
*/
public Boolean isNestedExceptions() {
return nestedExceptions;
}
/**
* Sets {@link #nestedExceptions}.
*
* @param nestedExceptions
* New value for {@link #nestedExceptions}
*/
public void setNestedExceptions(Boolean nestedExceptions) {
this.nestedExceptions = nestedExceptions;
}
/**
* Gets {@link #applicationId}.
*
* @return {@link #applicationId}
*/
public int getApplicationId() {
return applicationId;
}
/**
* Sets {@link #applicationId}.
*
* @param applicationId
* New value for {@link #applicationId}
*/
public void setApplicationId(int applicationId) {
this.applicationId = applicationId;
}
/**
* Gets {@link #businessTransactionId}.
*
* @return {@link #businessTransactionId}
*/
public int getBusinessTransactionId() {
return businessTransactionId;
}
/**
* Sets {@link #businessTransactionId}.
*
* @param businessTransactionId
* New value for {@link #businessTransactionId}
*/
public void setBusinessTransactionId(int businessTransactionId) {
this.businessTransactionId = businessTransactionId;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = (prime * result) + ((exceptionSensorDataObjects == null) ? 0 : exceptionSensorDataObjects.hashCode());
result = (prime * result) + ((sqlStatementData == null) ? 0 : sqlStatementData.hashCode());
result = (prime * result) + ((timerData == null) ? 0 : timerData.hashCode());
result = (prime * result) + ((loggingData == null) ? 0 : loggingData.hashCode());
result = (prime * result) + ((spanIdent == null) ? 0 : spanIdent.hashCode());
result = (prime * result) + applicationId;
result = (prime * result) + businessTransactionId;
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
InvocationSequenceData other = (InvocationSequenceData) obj;
if (exceptionSensorDataObjects == null) {
if (other.exceptionSensorDataObjects != null) {
return false;
}
} else if (!exceptionSensorDataObjects.equals(other.exceptionSensorDataObjects)) {
return false;
}
if (sqlStatementData == null) {
if (other.sqlStatementData != null) {
return false;
}
} else if (!sqlStatementData.equals(other.sqlStatementData)) {
return false;
}
if (timerData == null) {
if (other.timerData != null) {
return false;
}
} else if (!timerData.equals(other.timerData)) {
return false;
}
if (loggingData == null) {
if (other.loggingData != null) {
return false;
}
} else if (!loggingData.equals(other.loggingData)) {
return false;
}
if (spanIdent == null) {
if (other.spanIdent != null) {
return false;
}
} else if (!spanIdent.equals(other.spanIdent)) {
return false;
}
if (applicationId != other.applicationId) {
return false;
}
if (businessTransactionId != other.businessTransactionId) {
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public long getObjectSize(IObjectSizes objectSizes, boolean doAlign) {
long size = super.getObjectSize(objectSizes, doAlign);
size += objectSizes.getPrimitiveTypesSize(9, 0, 2, 0, 2, 3);
size += objectSizes.getSizeOf(timerData);
size += objectSizes.getSizeOf(loggingData);
size += objectSizes.getSizeOf(sqlStatementData);
size += objectSizes.getSizeOf(spanIdent);
if (nestedSequences instanceof ArrayList) {
size += objectSizes.getSizeOf(nestedSequences, 0);
for (InvocationSequenceData invocationSequenceData : nestedSequences) {
size += objectSizes.getSizeOf(invocationSequenceData);
}
}
if (null != exceptionSensorDataObjects) {
size += objectSizes.getSizeOf(exceptionSensorDataObjects);
for (ExceptionSensorData exceptionSensorData : exceptionSensorDataObjects) {
size += objectSizes.getSizeOf(exceptionSensorData);
}
}
if (null != nestedSqlStatements) {
size += objectSizes.getSizeOfBooleanObject();
}
if (null != nestedExceptions) {
size += objectSizes.getSizeOfBooleanObject();
}
if (doAlign) {
return objectSizes.alignTo8Bytes(size);
} else {
return size;
}
}
/**
* 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;
}
}