public synchronized LogReadResponse read()

in api_dev/src/main/java/com/google/appengine/api/log/dev/LocalLogService.java [83:224]


  public synchronized LogReadResponse read(Status status, LogReadRequest request) {
    LogReadResponse.Builder response = LogReadResponse.newBuilder();
    Integer index = 0;

    Set<ByteString> requestedIds = null;
    if (!request.getRequestIdList().isEmpty()) {
      requestedIds = new HashSet<>(request.getRequestIdList());
    }

    // If the user gave us a request ID to start with, look through our logs
    // until we find it. Since it may have been deleted between the time they
    // originally were given that value and now, any value with a timestamp
    // after this one is acceptable.
    if (request.hasOffset()) {
      index = null;
      BigInteger requestToFind =
          new BigInteger(request.getOffset().getRequestId().toStringUtf8(), 16);
      for (int i = 0; i < logs.size(); i++) {
        BigInteger thisRequestId = new BigInteger(logs.get(i).getRequestId().toStringUtf8(), 16);
        if (requestToFind.compareTo(thisRequestId) > 0) {
          index = i;
          break;
        }
      }

      // There is an unlikely scenario that can occur if the user is promised
      // more logs but before they ask for more, they are all deleted. In this
      // scenario, return a response to them with no logs and no offset, so
      // that they don't ask us for any more logs.
      if (index == null) {
        return response.build();
      }
    }

    int numResultsFetched = 0;
    for (int i = index; i < logs.size(); i++) {
      RequestLog thisLog = null;
      int j = 0;
      for (RequestLog log : logs) {
        if (i == j) {
          thisLog = log;
          break;
        }
        j++;
      }

      if (requestedIds != null &&
          !requestedIds.contains(thisLog.getRequestId())) {
        continue;
      }

      // We want to get all logs that have started within the bounds the user
      // has requested, so check the request's starting time (not its ending
      // time) against the provided start/end times.
      if (request.hasStartTime()) {
        if (request.getStartTime() > thisLog.getEndTime()) {
          continue;
        }
      }

      if (request.hasEndTime()) {
        if (request.getEndTime() <= thisLog.getEndTime()) {
          continue;
        }
      }

      // If the user doesn't want incomplete requests and this request is
      // incomplete, don't include it.
      if (!request.getIncludeIncomplete() && !thisLog.getFinished()) {
        continue;
      }

      if (!request.getVersionIdList().isEmpty()
          && !request.getVersionIdList().contains(thisLog.getVersionId())
          && thisLog.hasVersionId()) {
        continue;
      }

      if (!request.getModuleVersionList().isEmpty()
          && (thisLog.hasModuleId() || thisLog.hasVersionId())) {
        boolean moduleVersionMatch = false;
        for (LogModuleVersion moduleVersion : request.getModuleVersionList()) {
          if (thisLog.getModuleId().equals(moduleVersion.getModuleId())
              && thisLog.getVersionId().equals(moduleVersion.getVersionId())) {
            moduleVersionMatch = true;
          }
        }
        if (!moduleVersionMatch) {
          continue;
        }
      }

      if (request.hasMinimumLogLevel()) {
        // Find if there are any logs that meet or exceed minimumLogLevel.
        // If so (and if the user has specified that they want app logs), add
        // all the app logs to the response. If not, don't include this log in
        // the response.
        boolean logLevelMatched = false;

        for (LogLine line : thisLog.getLineList()) {
          if (line.getLevel() >= request.getMinimumLogLevel()) {
            logLevelMatched = true;
            break;
          }
        }

        if (!logLevelMatched) {
          continue;
        }
      }

      // At this point, the thisLog proto might only be partial, which is fine in dev mode
      // (difference between proto1 and proto2),
      // se we are filling mandatory fields with dummy data, so we do not need to change the
      // official
      // log service implementation.
      RequestLog.Builder logCopy = thisLog.toBuilder().clone();
      fillRequiredFields(logCopy);

      if (!request.getIncludeAppLogs()) {
        // If the user doesn't want app logs, make a copy of this log
        // that doesn't have that in it and give them that instead.
        logCopy.clearLine();
      }

      response.addLog(logCopy.build());

      numResultsFetched++;
      if (numResultsFetched >= request.getCount()) {
        // If there are more results, set the offset to the next result's
        // request id
        if (i + 1 < logs.size()) {
          ByteString nextOffset = logs.get(i).getRequestId();
          LogOffset offset = LogOffset.newBuilder().setRequestId(nextOffset).build();
          response.setOffset(offset);
        }

        break;
      }
    }
    return response.build();
  }