code: private void ajaxFetchJobLogs(final HttpServletRequest req,
        final HttpServletResponse resp, final HashMap<String, Object> ret, final User user,
        final ExecutableFlow exFlow) throws ServletException {
      final Project project = getProjectAjaxByPermission(ret, exFlow.getProjectId(), user, Type.READ);
      if (project == null) {
        return;
      }
  
      final int offset = this.getIntParam(req, "offset");
      final int length = this.getIntParam(req, "length");
  
      final String jobId = this.getParam(req, "jobId");
      resp.setCharacterEncoding("utf-8");
  
      try {
        final ExecutableNode node = exFlow.getExecutableNodePath(jobId);
        if (node == null) {
          ret.put("error", "Job " + jobId + " doesn't exist in " + exFlow.getExecutionId());
          return;
        }
  
        final int attempt = this.getIntParam(req, "attempt", node.getAttempt());
        final LogData data = this.executorManagerAdapter.getExecutionJobLog(exFlow, jobId, offset, length, attempt);
        ret.putAll(appendLogData(data, offset));
  
      } catch (final ExecutorManagerException e) {
        throw new ServletException(e);
      }
    }
docs: Gets the logs through ajax plain text stream to reduce memory overhead.