subprojects/parseq/src/main/java/com/linkedin/parseq/BaseTask.java
private void appendTaskStackTrace(final Throwable error) {
    StackTraceElement[] taskStackTrace = _taskStackTraceHolder != null ? _taskStackTraceHolder.getStackTrace() : null;

    // At a minimum, any stack trace should have at least 3 stack frames (caller + BaseTask + getStackTrace).
    // So if there are less than 3 stack frames available then there's something fishy and it's better to ignore them.
    if (!ParSeqGlobalConfiguration.isCrossThreadStackTracesEnabled() || error == null ||
        taskStackTrace == null || taskStackTrace.length <= 2) {
      return;
    }

    StackTraceElement[] errorStackTrace = error.getStackTrace();
    if (errorStackTrace.length <= 2) {
      return;
    }

    // Skip stack frames up to the BaseTask (useless java.util.concurrent stuff)
    int skipErrorFrames = 1;
    while (skipErrorFrames < errorStackTrace.length) {
      int index = errorStackTrace.length - 1 - skipErrorFrames;
      if (!errorStackTrace[index].getClassName().equals(CANONICAL_NAME) &&
          errorStackTrace[index + 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipErrorFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipErrorFrames == errorStackTrace.length) {
      skipErrorFrames = 0;
    }

    // Skip stack frames up to the BaseTask (useless Thread.getStackTrace stuff)
    int skipTaskFrames = 1;
    while (skipTaskFrames < taskStackTrace.length) {
      if (!taskStackTrace[skipTaskFrames].getClassName().equals(CANONICAL_NAME) &&
          taskStackTrace[skipTaskFrames - 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipTaskFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipTaskFrames == taskStackTrace.length) {
      skipTaskFrames = 0;
    }

    int combinedLength = errorStackTrace.length - skipErrorFrames + taskStackTrace.length - skipTaskFrames;
    if (combinedLength <= 0) {
      return;
    }

    StackTraceElement[] concatenatedStackTrace = new StackTraceElement[combinedLength + 1];
    System.arraycopy(errorStackTrace, 0, concatenatedStackTrace,
        0, errorStackTrace.length - skipErrorFrames);
    concatenatedStackTrace[errorStackTrace.length - skipErrorFrames] =
        new StackTraceElement("********** Task \"" + getName() + "\" (above) was instantiated as following (below): **********", "",null, 0);
    System.arraycopy(taskStackTrace, skipTaskFrames, concatenatedStackTrace,
        errorStackTrace.length - skipErrorFrames + 1, taskStackTrace.length - skipTaskFrames);
    error.setStackTrace(concatenatedStackTrace);
  }
private void appendTaskStackTrace(final Throwable error) {
    StackTraceElement[] taskStackTrace = _taskStackTraceHolder != null ? _taskStackTraceHolder.getStackTrace() : null;

    // At a minimum, any stack trace should have at least 3 stack frames (caller + BaseTask + getStackTrace).
    // So if there are less than 3 stack frames available then there's something fishy and it's better to ignore them.
    if (!ParSeqGlobalConfiguration.isCrossThreadStackTracesEnabled() || error == null ||
        taskStackTrace == null || taskStackTrace.length <= 2) {
      return;
    }

    StackTraceElement[] errorStackTrace = error.getStackTrace();
    if (errorStackTrace.length <= 2) {
      return;
    }

    // Skip stack frames up to the BaseTask (useless java.util.concurrent stuff)
    int skipErrorFrames = 1;
    while (skipErrorFrames < errorStackTrace.length) {
      int index = errorStackTrace.length - 1 - skipErrorFrames;
      if (!errorStackTrace[index].getClassName().equals(CANONICAL_NAME) &&
          errorStackTrace[index + 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipErrorFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipErrorFrames == errorStackTrace.length) {
      skipErrorFrames = 0;
    }

    // Skip stack frames up to the BaseTask (useless Thread.getStackTrace stuff)
    int skipTaskFrames = 1;
    while (skipTaskFrames < taskStackTrace.length) {
      if (!taskStackTrace[skipTaskFrames].getClassName().equals(CANONICAL_NAME) &&
          taskStackTrace[skipTaskFrames - 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipTaskFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipTaskFrames == taskStackTrace.length) {
      skipTaskFrames = 0;
    }

    int combinedLength = errorStackTrace.length - skipErrorFrames + taskStackTrace.length - skipTaskFrames;
    if (combinedLength <= 0) {
      return;
    }

    StackTraceElement[] concatenatedStackTrace = new StackTraceElement[combinedLength + 1];
    System.arraycopy(errorStackTrace, 0, concatenatedStackTrace,
        0, errorStackTrace.length - skipErrorFrames);
    concatenatedStackTrace[errorStackTrace.length - skipErrorFrames] =
        new StackTraceElement("********** Task \"" + getName() + "\" (above) was instantiated as following (below): **********", "",null, 0);
    System.arraycopy(taskStackTrace, skipTaskFrames, concatenatedStackTrace,
        errorStackTrace.length - skipErrorFrames + 1, taskStackTrace.length - skipTaskFrames);
    error.setStackTrace(concatenatedStackTrace);
  }
private void appendTaskStackTrace ( final Throwable error ) { StackTraceElement [ ] taskStackTrace = _taskStackTraceHolder != null ? _taskStackTraceHolder . getStackTrace ( ) : null ; // At a minimum, any stack trace should have at least 3 stack frames (caller + BaseTask + getStackTrace). // So if there are less than 3 stack frames available then there's something fishy and it's better to ignore them. if ( ! ParSeqGlobalConfiguration . isCrossThreadStackTracesEnabled ( ) || error == null || taskStackTrace == null || taskStackTrace . length <= 2 ) { return ; } StackTraceElement [ ] errorStackTrace = error . getStackTrace ( ) ; if ( errorStackTrace . length <= 2 ) { return ; } // Skip stack frames up to the BaseTask (useless java.util.concurrent stuff) int skipErrorFrames = 1 ; while ( skipErrorFrames < errorStackTrace . length ) { int index = errorStackTrace . length - 1 - skipErrorFrames ; if ( ! errorStackTrace [ index ] . getClassName ( ) . equals ( CANONICAL_NAME ) && errorStackTrace [ index + 1 ] . getClassName ( ) . equals ( CANONICAL_NAME ) ) { break ; } skipErrorFrames ++ ; } // Safeguard against accidentally removing entire stack trace if ( skipErrorFrames == errorStackTrace . length ) { skipErrorFrames = 0 ; } // Skip stack frames up to the BaseTask (useless Thread.getStackTrace stuff) int skipTaskFrames = 1 ; while ( skipTaskFrames < taskStackTrace . length ) { if ( ! taskStackTrace [ skipTaskFrames ] . getClassName ( ) . equals ( CANONICAL_NAME ) && taskStackTrace [ skipTaskFrames - 1 ] . getClassName ( ) . equals ( CANONICAL_NAME ) ) { break ; } skipTaskFrames ++ ; } // Safeguard against accidentally removing entire stack trace if ( skipTaskFrames == taskStackTrace . length ) { skipTaskFrames = 0 ; } int combinedLength = errorStackTrace . length - skipErrorFrames + taskStackTrace . length - skipTaskFrames ; if ( combinedLength <= 0 ) { return ; } StackTraceElement [ ] concatenatedStackTrace = new StackTraceElement [ combinedLength + 1 ] ; System . arraycopy ( errorStackTrace , 0 , concatenatedStackTrace , 0 , errorStackTrace . length - skipErrorFrames ) ; concatenatedStackTrace [ errorStackTrace . length - skipErrorFrames ] = new StackTraceElement ( "********** Task \"" + getName ( ) + "\" (above) was instantiated as following (below): **********" , "" , null , 0 ) ; System . arraycopy ( taskStackTrace , skipTaskFrames , concatenatedStackTrace , errorStackTrace . length - skipErrorFrames + 1 , taskStackTrace . length - skipTaskFrames ) ; error . setStackTrace ( concatenatedStackTrace ) ; }
Concatenate stack traces if kept the original stack trace from the task creation
Concatenate stack traces if kept the original stack trace from the task creation