Search in sources :

Example 56 with Log

use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.

the class DefaultLogSerializer method serializeContainer.

@NonNull
@Override
public String serializeContainer(@NonNull LogContainer logContainer) throws JSONException {
    /* Init JSON serializer, in verbose: try to make it pretty. */
    JSONStringer writer = null;
    if (AppCenterLog.getLogLevel() <= android.util.Log.VERBOSE) {
        try {
            Constructor<JSONStringer> constructor = JSONStringer.class.getDeclaredConstructor(int.class);
            constructor.setAccessible(true);
            writer = constructor.newInstance(2);
        } catch (Exception e) {
            AppCenterLog.error(AppCenter.LOG_TAG, "Failed to setup pretty json, falling back to default one", e);
        }
    }
    if (writer == null) {
        writer = new JSONStringer();
    }
    /* Start writing JSON. */
    writer.object();
    writer.key(LOGS).array();
    for (Log log : logContainer.getLogs()) {
        writeLog(writer, log);
    }
    writer.endArray();
    writer.endObject();
    return writer.toString();
}
Also used : AppCenterLog(com.microsoft.appcenter.utils.AppCenterLog) Log(com.microsoft.appcenter.ingestion.models.Log) JSONStringer(org.json.JSONStringer) JSONException(org.json.JSONException) NonNull(android.support.annotation.NonNull)

Example 57 with Log

use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.

the class DatabasePersistence method getLogs.

@Override
@Nullable
public String getLogs(@NonNull String group, @IntRange(from = 0) int limit, @NonNull List<Log> outLogs) {
    /* Log. */
    AppCenterLog.debug(LOG_TAG, "Trying to get " + limit + " logs from the Persistence database for " + group);
    /* Query database and get scanner. */
    DatabaseStorage.DatabaseScanner scanner = mDatabaseStorage.getScanner(COLUMN_GROUP, group);
    /* Add logs to output parameter after deserialization if logs are not already sent. */
    int count = 0;
    Map<Long, Log> candidates = new TreeMap<>();
    List<Long> failedDbIdentifiers = new ArrayList<>();
    File largePayloadGroupDirectory = getLargePayloadGroupDirectory(group);
    for (Iterator<ContentValues> iterator = scanner.iterator(); iterator.hasNext() && count < limit; ) {
        ContentValues values = iterator.next();
        Long dbIdentifier = values.getAsLong(DatabaseManager.PRIMARY_KEY);
        /*
             * When we can't even read the identifier (in this case ContentValues is most likely empty).
             * That probably means it contained a record larger than 2MB (from a previous SDK version)
             * and we hit the cursor limit.
             * Get rid of first non pending log.
             */
        if (dbIdentifier == null) {
            AppCenterLog.error(LOG_TAG, "Empty database record, probably content was larger than 2MB, need to delete as it's now corrupted.");
            DatabaseStorage.DatabaseScanner idScanner = mDatabaseStorage.getScanner(COLUMN_GROUP, group, true);
            for (ContentValues idValues : idScanner) {
                Long invalidId = idValues.getAsLong(DatabaseManager.PRIMARY_KEY);
                if (!mPendingDbIdentifiers.contains(invalidId) && !candidates.containsKey(invalidId)) {
                    /* Found the record to delete that we could not read when selecting all fields. */
                    deleteLog(largePayloadGroupDirectory, invalidId);
                    AppCenterLog.error(LOG_TAG, "Empty database corrupted empty record deleted, id=" + invalidId);
                    break;
                }
            }
            idScanner.close();
            continue;
        }
        /* If the log is already in pending state, then skip. Otherwise put the log to candidate container. */
        if (!mPendingDbIdentifiers.contains(dbIdentifier)) {
            try {
                /* Deserialize JSON to Log. */
                String logPayload;
                String databasePayload = values.getAsString(COLUMN_LOG);
                if (databasePayload == null) {
                    File file = getLargePayloadFile(largePayloadGroupDirectory, dbIdentifier);
                    AppCenterLog.debug(LOG_TAG, "Read payload file " + file);
                    logPayload = StorageHelper.InternalStorage.read(file);
                    if (logPayload == null) {
                        throw new JSONException("Log payload is null and not stored as a file.");
                    }
                } else {
                    logPayload = databasePayload;
                }
                candidates.put(dbIdentifier, getLogSerializer().deserializeLog(logPayload));
                count++;
            } catch (JSONException e) {
                /* If it is not able to deserialize, delete and get another log. */
                AppCenterLog.error(LOG_TAG, "Cannot deserialize a log in the database", e);
                /* Put the failed identifier to delete. */
                failedDbIdentifiers.add(dbIdentifier);
            }
        }
    }
    scanner.close();
    /* Delete any logs that cannot be de-serialized. */
    if (failedDbIdentifiers.size() > 0) {
        for (long id : failedDbIdentifiers) {
            deleteLog(largePayloadGroupDirectory, id);
        }
        AppCenterLog.warn(LOG_TAG, "Deleted logs that cannot be deserialized");
    }
    /* No logs found. */
    if (candidates.size() <= 0) {
        AppCenterLog.debug(LOG_TAG, "No logs found in the Persistence database at the moment");
        return null;
    }
    /* Generate an ID. */
    String id = UUIDUtils.randomUUID().toString();
    /* Log. */
    AppCenterLog.debug(LOG_TAG, "Returning " + candidates.size() + " log(s) with an ID, " + id);
    AppCenterLog.debug(LOG_TAG, "The SID/ID pairs for returning log(s) is/are:");
    List<Long> pendingDbIdentifiersGroup = new ArrayList<>();
    for (Map.Entry<Long, Log> entry : candidates.entrySet()) {
        Long dbIdentifier = entry.getKey();
        /* Change a database identifier to pending state. */
        mPendingDbIdentifiers.add(dbIdentifier);
        /* Store a database identifier to a group of the ID. */
        pendingDbIdentifiersGroup.add(dbIdentifier);
        /* Add to output parameter. */
        outLogs.add(entry.getValue());
        /* Log. */
        AppCenterLog.debug(LOG_TAG, "\t" + entry.getValue().getSid() + " / " + dbIdentifier);
    }
    /* Update pending IDs. */
    mPendingDbIdentifiersGroups.put(group + id, pendingDbIdentifiersGroup);
    return id;
}
Also used : ContentValues(android.content.ContentValues) AppCenterLog(com.microsoft.appcenter.utils.AppCenterLog) Log(com.microsoft.appcenter.ingestion.models.Log) ArrayList(java.util.ArrayList) JSONException(org.json.JSONException) TreeMap(java.util.TreeMap) DatabaseStorage(com.microsoft.appcenter.utils.storage.StorageHelper.DatabaseStorage) File(java.io.File) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) Map(java.util.Map) Nullable(android.support.annotation.Nullable)

Example 58 with Log

use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.

the class ChannelLogDecorateTest method checkLogAttributes.

@Test
public void checkLogAttributes() throws DeviceInfoHelper.DeviceInfoException {
    mockStatic(DeviceInfoHelper.class);
    Device device = mock(Device.class);
    when(DeviceInfoHelper.getDeviceInfo(any(Context.class))).thenReturn(device);
    mockStatic(IdHelper.class);
    Channel channel = new DefaultChannel(mock(Context.class), UUID.randomUUID().toString(), mock(Persistence.class), mock(Ingestion.class), mock(Handler.class));
    channel.addGroup("", 0, 0, 0, null);
    /* Test a log that should be decorated. */
    for (int i = 0; i < 3; i++) {
        Log log = mock(Log.class);
        channel.enqueue(log, "");
        verify(log).setDevice(device);
        verify(log).setTimestamp(any(Date.class));
    }
    /* Check cache was used, meaning only 1 call to generate a device. */
    verifyStatic();
    DeviceInfoHelper.getDeviceInfo(any(Context.class));
    /* Test a log that is already decorated. */
    Log log2 = mock(Log.class);
    when(log2.getDevice()).thenReturn(device);
    when(log2.getTimestamp()).thenReturn(new Date(123L));
    channel.enqueue(log2, "");
    verify(log2, never()).setDevice(any(Device.class));
    verify(log2, never()).setTimestamp(any(Date.class));
    /* Simulate update to wrapper SDK. */
    Device device2 = mock(Device.class);
    when(DeviceInfoHelper.getDeviceInfo(any(Context.class))).thenReturn(device2);
    channel.invalidateDeviceCache();
    /* Generate some logs to verify device properties have been updated. */
    for (int i = 0; i < 3; i++) {
        Log log3 = mock(Log.class);
        channel.enqueue(log3, "");
        verify(log3).setDevice(device2);
        verify(log3).setTimestamp(any(Date.class));
    }
    /* Check only 1 device has been generated after cache invalidate. */
    verifyStatic(times(2));
    DeviceInfoHelper.getDeviceInfo(any(Context.class));
}
Also used : Context(android.content.Context) Persistence(com.microsoft.appcenter.persistence.Persistence) Log(com.microsoft.appcenter.ingestion.models.Log) Device(com.microsoft.appcenter.ingestion.models.Device) Handler(android.os.Handler) Date(java.util.Date) Ingestion(com.microsoft.appcenter.ingestion.Ingestion) Test(org.junit.Test) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest)

Example 59 with Log

use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.

the class DefaultChannelTest method listener.

@Test
public void listener() throws Persistence.PersistenceException {
    @SuppressWarnings("ConstantConditions") DefaultChannel channel = new DefaultChannel(mock(Context.class), null, mock(Persistence.class), mock(IngestionHttp.class), mCoreHandler);
    channel.addGroup(TEST_GROUP, 50, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, null);
    Channel.Listener listener = spy(new AbstractChannelListener());
    channel.addListener(listener);
    Log log = mock(Log.class);
    channel.enqueue(log, TEST_GROUP);
    verify(listener).onEnqueuingLog(log, TEST_GROUP);
    verify(listener).shouldFilter(log);
    /* Check no more calls after removing listener. */
    log = mock(Log.class);
    channel.removeListener(listener);
    channel.enqueue(log, TEST_GROUP);
    verifyNoMoreInteractions(listener);
}
Also used : Context(android.content.Context) Persistence(com.microsoft.appcenter.persistence.Persistence) IngestionHttp(com.microsoft.appcenter.ingestion.IngestionHttp) Log(com.microsoft.appcenter.ingestion.models.Log) Test(org.junit.Test)

Example 60 with Log

use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.

the class DefaultChannelTest method shutdown.

@Test
public void shutdown() throws Exception {
    Persistence mockPersistence = mock(Persistence.class);
    IngestionHttp mockIngestion = mock(IngestionHttp.class);
    Channel.GroupListener mockListener = mock(Channel.GroupListener.class);
    when(mockPersistence.getLogs(any(String.class), anyInt(), Matchers.<List<Log>>any())).then(getGetLogsAnswer(1));
    DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), mockPersistence, mockIngestion, mCoreHandler);
    channel.addGroup(TEST_GROUP, 1, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, mockListener);
    /* Enqueuing 1 event. */
    channel.enqueue(mock(Log.class), TEST_GROUP);
    verify(mockListener).onBeforeSending(notNull(Log.class));
    channel.shutdown();
    verify(mockListener, never()).onFailure(any(Log.class), any(Exception.class));
    verify(mockPersistence).clearPendingLogState();
}
Also used : Persistence(com.microsoft.appcenter.persistence.Persistence) Context(android.content.Context) IngestionHttp(com.microsoft.appcenter.ingestion.IngestionHttp) Log(com.microsoft.appcenter.ingestion.models.Log) Matchers.anyString(org.mockito.Matchers.anyString) HttpException(com.microsoft.appcenter.http.HttpException) SocketException(java.net.SocketException) IOException(java.io.IOException) CancellationException(com.microsoft.appcenter.CancellationException) Test(org.junit.Test)

Aggregations

Log (com.microsoft.appcenter.ingestion.models.Log)64 Test (org.junit.Test)50 ArrayList (java.util.ArrayList)27 AppCenterLog (com.microsoft.appcenter.utils.AppCenterLog)25 Context (android.content.Context)24 UUID (java.util.UUID)23 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)22 LogSerializer (com.microsoft.appcenter.ingestion.models.json.LogSerializer)20 EventLog (com.microsoft.appcenter.analytics.ingestion.models.EventLog)15 DefaultLogSerializer (com.microsoft.appcenter.ingestion.models.json.DefaultLogSerializer)15 StartSessionLog (com.microsoft.appcenter.analytics.ingestion.models.StartSessionLog)14 LogContainer (com.microsoft.appcenter.ingestion.models.LogContainer)14 Channel (com.microsoft.appcenter.channel.Channel)12 Persistence (com.microsoft.appcenter.persistence.Persistence)12 HashMap (java.util.HashMap)11 Matchers.anyString (org.mockito.Matchers.anyString)11 InvocationOnMock (org.mockito.invocation.InvocationOnMock)11 Date (java.util.Date)10 MediumTest (android.support.test.filters.MediumTest)9 IngestionHttp (com.microsoft.appcenter.ingestion.IngestionHttp)9