Search in sources :

Example 1 with LogOffset

use of com.google.apphosting.api.logservice.LogServicePb.LogOffset in project appengine-java-standard by GoogleCloudPlatform.

the class LocalLogService method findLogInLogMapOrAddNewLog.

private synchronized RequestLog findLogInLogMapOrAddNewLog(String requestId) {
    if (requestId == null) {
        requestId = "null";
    }
    // assumed to be sorted by requestId.
    for (int i = 0; i < logs.size(); i++) {
        RequestLog possibleLog = logs.get(i);
        if (possibleLog.getRequestId().toStringUtf8().equals(requestId)) {
            return possibleLog;
        }
    }
    /* Items are sorted in descending order w.r.t. request id. Since request ids
     * are monotonically increasing, this means that the new request id we're
     * about to generate will have the largest value ever seen in the log list,
     * so put it at the beginning of the list. Lists also are not
     * thread-safe for adds and deletes, so synchronize access to it. */
    // Fill with required fields with dummy data that will be replaced later anyway.
    RequestLog.Builder log = RequestLog.newBuilder().setRequestId(ByteString.copyFromUtf8(requestId)).setFinished(false);
    LogOffset offset = LogOffset.newBuilder().setRequestId(ByteString.copyFromUtf8(requestId)).build();
    RequestLog built = log.setOffset(offset).buildPartial();
    logs.add(0, built);
    // If there are too many logs stored, remove the oldest (last) one.
    if (logs.size() > MAX_NUM_LOGS) {
        logs.remove(logs.size() - 1);
    }
    return built;
}
Also used : RequestLog(com.google.apphosting.api.logservice.LogServicePb.RequestLog) LogOffset(com.google.apphosting.api.logservice.LogServicePb.LogOffset)

Example 2 with LogOffset

use of com.google.apphosting.api.logservice.LogServicePb.LogOffset in project appengine-java-standard by GoogleCloudPlatform.

the class LocalLogServiceTest method testHexRequestIdOffsetHandling.

@Test
public void testHexRequestIdOffsetHandling() {
    LogOffset offset = LogOffset.newBuilder().setRequestId(ByteString.copyFromUtf8(String.format("%x", new BigInteger("12345")))).build();
    LogReadRequest request = LogReadRequest.newBuilder().setAppId("").setOffset(offset).build();
    LocalLogService service = new LocalLogService();
    assertThat(service.read(null, request)).isNotNull();
}
Also used : LogReadRequest(com.google.apphosting.api.logservice.LogServicePb.LogReadRequest) LogOffset(com.google.apphosting.api.logservice.LogServicePb.LogOffset) BigInteger(java.math.BigInteger) Test(org.junit.Test)

Example 3 with LogOffset

use of com.google.apphosting.api.logservice.LogServicePb.LogOffset in project appengine-java-standard by GoogleCloudPlatform.

the class LogServiceImplTest method testGetAllLogs.

@Test
public void testGetAllLogs() throws Exception {
    int totalNumItems = LogService.DEFAULT_ITEMS_PER_FETCH * 2;
    List<RequestLog> expectedLogs = getTestData(totalNumItems);
    // The first request should have all the user-specified filters.
    LogReadRequest.Builder initialRequest = LogReadRequest.newBuilder().setAppId(APPLICATION_ID);
    initialRequest.addModuleVersionBuilder().setVersionId(MAJOR_VERSION_ID);
    initialRequest.setIncludeIncomplete(false).setCount(LogService.DEFAULT_ITEMS_PER_FETCH).setIncludeAppLogs(false);
    // The offset returned by the first request will be a reference to where the
    // next request should begin - here, since we ask for MAX_ITEMS, the offset
    // should be pointing at MAX_ITEMS.
    LogOffset offset = LogOffset.newBuilder().setRequestId(ByteString.copyFromUtf8(Integer.toString(LogService.DEFAULT_ITEMS_PER_FETCH))).build();
    // The first response will contain the first batch of logs and an offset for
    // the second (and last) batch of logs.
    LogReadResponse.Builder initialResponse = LogReadResponse.newBuilder();
    for (int i = 0; i < LogService.DEFAULT_ITEMS_PER_FETCH; i++) {
        initialResponse.addLog(expectedLogs.get(i));
    }
    initialResponse.setOffset(offset);
    // The second request should contain everything the first request had, but
    // with the offset given to us by the first response.
    LogReadRequest.Builder secondRequest = LogReadRequest.newBuilder().setAppId(APPLICATION_ID);
    secondRequest.addModuleVersionBuilder().setVersionId(MAJOR_VERSION_ID);
    secondRequest.setIncludeIncomplete(false).setCount(LogService.DEFAULT_ITEMS_PER_FETCH).setIncludeAppLogs(false).setOffset(offset);
    // The second response contains the second batch of logs and a None pointer
    // in the offset, as there are no more logs after this.
    LogReadResponse.Builder secondResponse = LogReadResponse.newBuilder();
    for (int i = LogService.DEFAULT_ITEMS_PER_FETCH; i < LogService.DEFAULT_ITEMS_PER_FETCH * 2; i++) {
        secondResponse.addLog(expectedLogs.get(i));
    }
    ApiProxy.ApiConfig apiConfig = new ApiProxy.ApiConfig();
    Future<byte[]> mockedFirstFuture = immediateFuture(initialResponse.build().toByteArray());
    when(delegate.makeAsyncCall(same(ApiProxy.getCurrentEnvironment()), eq(LogServiceImpl.PACKAGE), eq(LogServiceImpl.READ_RPC_NAME), eq(initialRequest.build().toByteArray()), isA(apiConfig.getClass()))).thenReturn(mockedFirstFuture);
    Future<byte[]> mockedSecondFuture = immediateFuture(secondResponse.build().toByteArray());
    when(delegate.makeAsyncCall(same(ApiProxy.getCurrentEnvironment()), eq(LogServiceImpl.PACKAGE), eq(LogServiceImpl.READ_RPC_NAME), eq(secondRequest.build().toByteArray()), isA(apiConfig.getClass()))).thenReturn(mockedSecondFuture);
    LogQuery query = LogQuery.Builder.withDefaults();
    List<RequestLogs> actualLogs = new ArrayList<>();
    for (RequestLogs record : new LogServiceImpl().fetch(query)) {
        actualLogs.add(record);
    }
    assertThat(actualLogs).hasSize(expectedLogs.size());
}
Also used : ApiProxy(com.google.apphosting.api.ApiProxy) LogOffset(com.google.apphosting.api.logservice.LogServicePb.LogOffset) ArrayList(java.util.ArrayList) RequestLog(com.google.apphosting.api.logservice.LogServicePb.RequestLog) LogReadRequest(com.google.apphosting.api.logservice.LogServicePb.LogReadRequest) LogReadResponse(com.google.apphosting.api.logservice.LogServicePb.LogReadResponse) Test(org.junit.Test)

Example 4 with LogOffset

use of com.google.apphosting.api.logservice.LogServicePb.LogOffset in project appengine-java-standard by GoogleCloudPlatform.

the class LogServiceImplTest method testFetchWithOffset.

@Test
public void testFetchWithOffset() throws Exception {
    List<RequestLog> expectedData = getTestData(LogService.DEFAULT_ITEMS_PER_FETCH);
    LogReadRequest.Builder request = createLogReadRequest(null, null, null, null).toBuilder();
    LogOffset offset = LogOffset.newBuilder().setRequestId(ByteString.copyFrom(new byte[] { (byte) 0xfe, (byte) 0xff, (byte) 0xcd })).build();
    request.setOffset(offset);
    LogReadResponse response = createLogReadResponse(expectedData);
    setupExpectations(request.build(), response);
    LogQuery query = LogQuery.Builder.withDefaults();
    query.offset(base64().encode(offset.toByteArray()));
    new LogServiceImpl().fetch(query);
    // Test negative case.
    // Not parseable as Base64.
    query.offset("!");
    assertThrows(IllegalArgumentException.class, () -> new LogServiceImpl().fetch(query));
}
Also used : RequestLog(com.google.apphosting.api.logservice.LogServicePb.RequestLog) LogReadRequest(com.google.apphosting.api.logservice.LogServicePb.LogReadRequest) LogOffset(com.google.apphosting.api.logservice.LogServicePb.LogOffset) LogReadResponse(com.google.apphosting.api.logservice.LogServicePb.LogReadResponse) Test(org.junit.Test)

Example 5 with LogOffset

use of com.google.apphosting.api.logservice.LogServicePb.LogOffset in project appengine-java-standard by GoogleCloudPlatform.

the class LocalLogService method read.

/**
 * Reads log records from the in-memory log list and applies user-specified filters to the results
 * to return.
 *
 * @param request A set of parameters that indicate restrictions on the results that should be
 *     returned.
 * @return A set of logs matching the parameters given. If the number of logs returned exceed
 *     either the user-specified amount or the API-specified limit, then an offset is returned
 *     that has a reference to the next record to read from in subsequent requests.
 */
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());
    }
    // 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;
            }
        }
        // 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;
        }
        // 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;
            }
        }
        // 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()) {
            // 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();
}
Also used : ByteString(com.google.protobuf.ByteString) LogOffset(com.google.apphosting.api.logservice.LogServicePb.LogOffset) LogLine(com.google.apphosting.api.logservice.LogServicePb.LogLine) LogModuleVersion(com.google.apphosting.api.logservice.LogServicePb.LogModuleVersion) BigInteger(java.math.BigInteger) RequestLog(com.google.apphosting.api.logservice.LogServicePb.RequestLog) BigInteger(java.math.BigInteger) LogReadResponse(com.google.apphosting.api.logservice.LogServicePb.LogReadResponse)

Aggregations

LogOffset (com.google.apphosting.api.logservice.LogServicePb.LogOffset)5 RequestLog (com.google.apphosting.api.logservice.LogServicePb.RequestLog)4 LogReadRequest (com.google.apphosting.api.logservice.LogServicePb.LogReadRequest)3 LogReadResponse (com.google.apphosting.api.logservice.LogServicePb.LogReadResponse)3 Test (org.junit.Test)3 BigInteger (java.math.BigInteger)2 ApiProxy (com.google.apphosting.api.ApiProxy)1 LogLine (com.google.apphosting.api.logservice.LogServicePb.LogLine)1 LogModuleVersion (com.google.apphosting.api.logservice.LogServicePb.LogModuleVersion)1 ByteString (com.google.protobuf.ByteString)1 ArrayList (java.util.ArrayList)1