private static String toString(ThreadInfo info) {
    StringBuilder sb = new StringBuilder("\"" + info.getThreadName() + "\""
        + " Id=" + info.getThreadId() + " " + info.getThreadState());
    if (info.getLockName() != null) {
      sb.append(" on " + info.getLockName());
    }
    if (info.getLockOwnerName() != null) {
      sb.append(" owned by \"" + info.getLockOwnerName() + "\" Id="
          + info.getLockOwnerId());
    }
    if (info.isSuspended()) {
      sb.append(" (suspended)");
    }
    if (info.isInNative()) {
      sb.append(" (in native)");
    }
    sb.append('\n');
    int i = 0;
    for (; i < info.getStackTrace().length; i++) {
      StackTraceElement ste = info.getStackTrace()[i];
      sb.append("\tat " + ste.toString());
      sb.append('\n');
      if (i == 0 && info.getLockInfo() != null) {
        Thread.State ts = info.getThreadState();
        switch (ts) {
          case BLOCKED:
            sb.append("\t-  blocked on " + info.getLockInfo());
            sb.append('\n');
            break;
          case WAITING:
            sb.append("\t-  waiting on " + info.getLockInfo());
            sb.append('\n');
            break;
          case TIMED_WAITING:
            sb.append("\t-  waiting on " + info.getLockInfo());
            sb.append('\n');
            break;
          default:
        }
      }

      for (MonitorInfo mi : info.getLockedMonitors()) {
        if (mi.getLockedStackDepth() == i) {
          sb.append("\t-  locked " + mi);
          sb.append('\n');
        }
      }
    }
    if (i < info.getStackTrace().length) {
      sb.append("\t...");
      sb.append('\n');
    }

    LockInfo[] locks = info.getLockedSynchronizers();
    if (locks.length > 0) {
      sb.append("\n\tNumber of locked synchronizers = " + locks.length);
      sb.append('\n');
      for (LockInfo li : locks) {
        sb.append("\t- " + li);
        sb.append('\n');
      }
    }
    sb.append('\n');
    return sb.toString();
  }
Copy of ThreadInfo#toString() without the hardcoded MAX_FRAMES = 8 restriction on thread stack depth.

Returns a string representation of this thread info.
The format of this string depends on the implementation.
The returned string will typically include
the thread name, the getThreadId thread ID, its state,
and a stack trace if any.

@return a string representation of this thread info.
samza-core/src/main/java/org/apache/samza/util/ThreadUtil.java