Search in sources :

Example 6 with Device

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

the class ErrorLogHelper method parseDevice.

/**
 * Look for 'deviceInfo' data in file inside the minidump folder and parse it.
 * @param contextInformation - data with information about userId.
 * @return deviceInfo or null.
 */
@VisibleForTesting
static Device parseDevice(String contextInformation) {
    try {
        Device device = new Device();
        JSONObject jsonObject = new JSONObject(contextInformation);
        JSONObject deviceJson;
        if (jsonObject.has(DEVICE_INFO_KEY)) {
            deviceJson = new JSONObject(jsonObject.getString(DEVICE_INFO_KEY));
        } else {
            deviceJson = jsonObject;
        }
        device.read(deviceJson);
        return device;
    } catch (JSONException e) {
        AppCenterLog.error(Crashes.LOG_TAG, "Failed to deserialize device info.", e);
    }
    return null;
}
Also used : JSONObject(org.json.JSONObject) Device(com.microsoft.appcenter.ingestion.models.Device) JSONException(org.json.JSONException) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 7 with Device

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

the class ErrorLogHelper method getNewMinidumpSubfolderWithContextData.

/**
 * A one-time run-specific folder where unprocessed NDK crashes are saved.
 * Each launch of the application creates its own sub-folder with a random name
 * to store information about the current device (including the application version),
 * which is used in the error report.
 *
 * @return a folder name e.g. /lib/files/error/minidump/new/aae16c29-f9e7-42a9-baee-0777e6ba8fe3
 */
@NonNull
public static synchronized File getNewMinidumpSubfolderWithContextData(Context context) {
    File directorySubfolder = getNewMinidumpSubfolder();
    File deviceInfoFile = new File(directorySubfolder, ErrorLogHelper.DEVICE_INFO_FILE);
    try {
        Device deviceInfo = DeviceInfoHelper.getDeviceInfo(context);
        String userIdContext = UserIdContext.getInstance().getUserId();
        deviceInfo.setWrapperSdkName(WRAPPER_SDK_NAME_NDK);
        /* To JSON. */
        JSONStringer writer = new JSONStringer();
        writer.object();
        deviceInfo.write(writer);
        writer.endObject();
        String deviceInfoString = writer.toString();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(DEVICE_INFO_KEY, deviceInfoString);
        jsonObject.put(USER_ID_KEY, userIdContext);
        /* Write file. */
        FileManager.write(deviceInfoFile, jsonObject.toString());
    } catch (DeviceInfoHelper.DeviceInfoException | IOException | JSONException e) {
        AppCenterLog.error(Crashes.LOG_TAG, "Failed to store device info in a minidump folder.", e);
        // noinspection ResultOfMethodCallIgnored
        deviceInfoFile.delete();
    }
    return directorySubfolder;
}
Also used : JSONObject(org.json.JSONObject) Device(com.microsoft.appcenter.ingestion.models.Device) JSONException(org.json.JSONException) IOException(java.io.IOException) File(java.io.File) JSONStringer(org.json.JSONStringer) NonNull(androidx.annotation.NonNull)

Example 8 with Device

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

the class CrashesTest method testNativeCrashLog.

private ManagedErrorLog testNativeCrashLog(long appStartTime, long crashTime, boolean correlateSession, boolean hasDeviceInfo, boolean hasUserId) throws Exception {
    /* Create minidump sub-folder. */
    File minidumpSubfolder = mTemporaryFolder.newFolder("mockFolder");
    String mockUserId = "user-id";
    /* Create a file for a crash in disk. */
    File minidumpFile = new File(minidumpSubfolder, "mockFile.dmp");
    assertTrue(minidumpFile.createNewFile());
    assertTrue(minidumpFile.setLastModified(crashTime));
    /* Create an additional file in a folder to be filtered later. */
    File otherFile = new File(minidumpSubfolder, "otherFile.txt");
    long fakeCrashTime = new Date().getTime();
    assertTrue(otherFile.createNewFile());
    assertTrue(otherFile.setLastModified(fakeCrashTime));
    /* Mock session context. */
    mockStatic(SessionContext.class);
    SessionContext sessionContext = mock(SessionContext.class);
    when(SessionContext.getInstance()).thenReturn(sessionContext);
    if (correlateSession) {
        SessionContext.SessionInfo sessionInfo = mock(SessionContext.SessionInfo.class);
        when(sessionContext.getSessionAt(crashTime)).thenReturn(sessionInfo);
        when(sessionInfo.getAppLaunchTimestamp()).thenReturn(appStartTime);
    }
    /* Mock device info and ErrorLogHelper. */
    mockStatic(ErrorLogHelper.class);
    mockStatic(DeviceInfoHelper.class);
    Device device = mock(Device.class);
    when(DeviceInfoHelper.getDeviceInfo(any(Context.class))).thenReturn(mock(Device.class));
    when(ErrorLogHelper.getStoredDeviceInfo(any(File.class))).thenReturn(hasDeviceInfo ? device : null);
    when(ErrorLogHelper.getStoredUserInfo(any(File.class))).thenReturn(hasUserId ? mockUserId : null);
    ErrorReport report = new ErrorReport();
    File errorLogFile = mock(File.class);
    when(errorLogFile.length()).thenReturn(1L);
    when(ErrorLogHelper.getLastErrorLogFile()).thenReturn(errorLogFile);
    when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { mock(File.class) });
    when(ErrorLogHelper.getNewMinidumpFiles()).thenReturn(new File[] { minidumpSubfolder });
    File pendingDir = mock(File.class);
    Whitebox.setInternalState(pendingDir, "path", "");
    when(ErrorLogHelper.getPendingMinidumpDirectory()).thenReturn(pendingDir);
    when(ErrorLogHelper.getErrorReportFromErrorLog(any(ManagedErrorLog.class), anyString())).thenReturn(report);
    when(ErrorLogHelper.parseLogFolderUuid(any(File.class))).thenReturn(UUID.randomUUID());
    when(FileManager.read(any(File.class))).thenReturn("");
    LogSerializer logSerializer = mock(LogSerializer.class);
    ArgumentCaptor<Log> log = ArgumentCaptor.forClass(Log.class);
    when(logSerializer.serializeLog(log.capture())).thenReturn("{}");
    when(logSerializer.deserializeLog(anyString(), anyString())).thenAnswer(new Answer<ManagedErrorLog>() {

        @Override
        public ManagedErrorLog answer(InvocationOnMock invocation) {
            com.microsoft.appcenter.crashes.ingestion.models.Exception mockException = new com.microsoft.appcenter.crashes.ingestion.models.Exception();
            mockException.setType(MINIDUMP_FILE);
            mockException.setMessage("message");
            ManagedErrorLog log = mock(ManagedErrorLog.class);
            when(log.getId()).thenReturn(UUID.randomUUID());
            when(log.getException()).thenReturn(mockException);
            return log;
        }
    });
    /* Start crashes. */
    Crashes crashes = Crashes.getInstance();
    crashes.setLogSerializer(logSerializer);
    crashes.onStarting(mAppCenterHandler);
    crashes.onStarted(mock(Context.class), mock(Channel.class), "", null, true);
    /* Verify timestamps on the crash log. */
    assertTrue(Crashes.hasCrashedInLastSession().get());
    assertTrue(log.getValue() instanceof ManagedErrorLog);
    assertEquals(1, log.getAllValues().size());
    assertNotEquals(new Date(fakeCrashTime), log.getValue().getTimestamp());
    return (ManagedErrorLog) log.getValue();
}
Also used : Matchers.anyString(org.mockito.Matchers.anyString) Log.getStackTraceString(android.util.Log.getStackTraceString) DefaultLogSerializer(com.microsoft.appcenter.ingestion.models.json.DefaultLogSerializer) LogSerializer(com.microsoft.appcenter.ingestion.models.json.LogSerializer) ErrorReport(com.microsoft.appcenter.crashes.model.ErrorReport) ManagedErrorLog(com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog) SessionContext(com.microsoft.appcenter.utils.context.SessionContext) Context(android.content.Context) ManagedErrorLog(com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog) Log(com.microsoft.appcenter.ingestion.models.Log) AppCenterLog(com.microsoft.appcenter.utils.AppCenterLog) HandledErrorLog(com.microsoft.appcenter.crashes.ingestion.models.HandledErrorLog) ErrorAttachmentLog(com.microsoft.appcenter.crashes.ingestion.models.ErrorAttachmentLog) Device(com.microsoft.appcenter.ingestion.models.Device) Channel(com.microsoft.appcenter.channel.Channel) Date(java.util.Date) JSONException(org.json.JSONException) IOException(java.io.IOException) TestCrashException(com.microsoft.appcenter.crashes.model.TestCrashException) InvocationOnMock(org.mockito.invocation.InvocationOnMock) SessionContext(com.microsoft.appcenter.utils.context.SessionContext) File(java.io.File)

Example 9 with Device

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

the class Crashes method processSingleMinidump.

/**
 * Process the minidump, save an error log with a reference to the minidump, move the minidump file to the 'pending' folder.
 *
 * @param minidumpFile   a file where an ndk crash is saved.
 * @param minidumpFolder a folder that contains device info and a minidump file.
 */
private void processSingleMinidump(File minidumpFile, File minidumpFolder) {
    /* Create missing files from the native crash that we detected. */
    AppCenterLog.debug(LOG_TAG, "Process pending minidump file: " + minidumpFile);
    long minidumpDate = minidumpFile.lastModified();
    File dest = new File(ErrorLogHelper.getPendingMinidumpDirectory(), minidumpFile.getName());
    Exception modelException = new Exception();
    modelException.setType("minidump");
    modelException.setWrapperSdkName(WRAPPER_SDK_NAME_NDK);
    modelException.setMinidumpFilePath(dest.getPath());
    ManagedErrorLog errorLog = new ManagedErrorLog();
    errorLog.setException(modelException);
    errorLog.setTimestamp(new Date(minidumpDate));
    errorLog.setFatal(true);
    errorLog.setId(ErrorLogHelper.parseLogFolderUuid(minidumpFolder));
    /* Lookup app launch timestamp in session history. */
    SessionContext.SessionInfo session = SessionContext.getInstance().getSessionAt(minidumpDate);
    if (session != null && session.getAppLaunchTimestamp() <= minidumpDate) {
        errorLog.setAppLaunchTimestamp(new Date(session.getAppLaunchTimestamp()));
    } else {
        /*
             * Fall back to log date if app launch timestamp information lost
             * or in the future compared to crash time.
             * This also covers the case where app launches then crashes within 1s:
             * app launch timestamp would have ms accuracy while minidump file is without
             * ms, in that case we also falls back to log timestamp
             * (this would be same result as truncating ms).
             */
        errorLog.setAppLaunchTimestamp(errorLog.getTimestamp());
    }
    /*
         * TODO The following properties are placeholders because fields are required.
         * They should be removed from schema as not used by server.
         */
    errorLog.setProcessId(0);
    errorLog.setProcessName("");
    try {
        String savedUserId = ErrorLogHelper.getStoredUserInfo(minidumpFolder);
        Device savedDeviceInfo = ErrorLogHelper.getStoredDeviceInfo(minidumpFolder);
        if (savedDeviceInfo == null) {
            /*
                 * Fallback to use device info from the current launch.
                 * It may lead to an incorrect app version being reported.
                 */
            savedDeviceInfo = getDeviceInfo(mContext);
            savedDeviceInfo.setWrapperSdkName(WRAPPER_SDK_NAME_NDK);
        }
        errorLog.setDevice(savedDeviceInfo);
        errorLog.setUserId(savedUserId);
        saveErrorLogFiles(new NativeException(), errorLog);
        if (!minidumpFile.renameTo(dest)) {
            throw new IOException("Failed to move file");
        }
    } catch (java.lang.Exception e) {
        // noinspection ResultOfMethodCallIgnored
        minidumpFile.delete();
        removeAllStoredErrorLogFiles(errorLog.getId());
        AppCenterLog.error(LOG_TAG, "Failed to process new minidump file: " + minidumpFile, e);
    }
}
Also used : Device(com.microsoft.appcenter.ingestion.models.Device) Log.getStackTraceString(android.util.Log.getStackTraceString) IOException(java.io.IOException) Exception(com.microsoft.appcenter.crashes.ingestion.models.Exception) JSONException(org.json.JSONException) NativeException(com.microsoft.appcenter.crashes.model.NativeException) TestCrashException(com.microsoft.appcenter.crashes.model.TestCrashException) IOException(java.io.IOException) Date(java.util.Date) ManagedErrorLog(com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog) SessionContext(com.microsoft.appcenter.utils.context.SessionContext) File(java.io.File) NativeException(com.microsoft.appcenter.crashes.model.NativeException)

Example 10 with Device

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

the class AnalyticsSerializerTest method someBatch.

@Test
public void someBatch() throws JSONException {
    LogContainer expectedContainer = new LogContainer();
    Device device = new Device();
    device.setSdkName("appcenter.android");
    device.setSdkVersion("1.2.3");
    device.setModel("S5");
    device.setOemName("HTC");
    device.setOsName("Android");
    device.setOsVersion("4.0.3");
    device.setOsBuild("LMY47X");
    device.setOsApiLevel(15);
    device.setLocale("en_US");
    device.setTimeZoneOffset(120);
    device.setScreenSize("800x600");
    device.setAppVersion("3.2.1");
    device.setAppBuild("42");
    List<Log> logs = new ArrayList<>();
    {
        StartSessionLog startSessionLog = new StartSessionLog();
        startSessionLog.setTimestamp(new Date());
        logs.add(startSessionLog);
    }
    expectedContainer.setLogs(logs);
    {
        PageLog pageLog = new PageLog();
        pageLog.setTimestamp(new Date());
        pageLog.setName("home");
        logs.add(pageLog);
    }
    {
        PageLog pageLog = new PageLog();
        pageLog.setTimestamp(new Date());
        pageLog.setName("settings");
        pageLog.setProperties(new HashMap<String, String>() {

            {
                put("from", "home_menu");
                put("orientation", "portrait");
            }
        });
        logs.add(pageLog);
    }
    {
        EventLog eventLog = new EventLog();
        eventLog.setTimestamp(new Date());
        eventLog.setId(UUID.randomUUID());
        eventLog.setName("subscribe");
        logs.add(eventLog);
    }
    {
        EventLog eventLog = new EventLog();
        eventLog.setTimestamp(new Date());
        eventLog.setId(UUID.randomUUID());
        eventLog.setName("click");
        eventLog.setProperties(new HashMap<String, String>() {

            {
                put("x", "1");
                put("y", "2");
            }
        });
        logs.add(eventLog);
    }
    {
        List<TypedProperty> properties = new ArrayList<>();
        BooleanTypedProperty bp = new BooleanTypedProperty();
        bp.setName("n1");
        bp.setValue(true);
        properties.add(bp);
        DateTimeTypedProperty dtp = new DateTimeTypedProperty();
        dtp.setName("n2");
        dtp.setValue(new Date());
        properties.add(dtp);
        DoubleTypedProperty dp = new DoubleTypedProperty();
        dp.setName("n3");
        dp.setValue(10);
        properties.add(dp);
        LongTypedProperty lp = new LongTypedProperty();
        lp.setName("n4");
        lp.setValue(10000000000L);
        properties.add(lp);
        StringTypedProperty sp = new StringTypedProperty();
        sp.setName("n5");
        sp.setValue("value");
        properties.add(sp);
        EventLog eventLog = new EventLog();
        eventLog.setTimestamp(new Date());
        eventLog.setId(UUID.randomUUID());
        eventLog.setName("event");
        eventLog.setTypedProperties(properties);
        logs.add(eventLog);
    }
    UUID sid = UUID.randomUUID();
    for (Log log : logs) {
        log.setSid(sid);
        log.setDevice(device);
    }
    LogSerializer serializer = new DefaultLogSerializer();
    serializer.addLogFactory(StartSessionLog.TYPE, new StartSessionLogFactory());
    serializer.addLogFactory(PageLog.TYPE, new PageLogFactory());
    serializer.addLogFactory(EventLog.TYPE, new EventLogFactory());
    String payload = serializer.serializeContainer(expectedContainer);
    android.util.Log.v(TAG, payload);
    LogContainer actualContainer = serializer.deserializeContainer(payload, null);
    Assert.assertEquals(expectedContainer, actualContainer);
}
Also used : DoubleTypedProperty(com.microsoft.appcenter.ingestion.models.properties.DoubleTypedProperty) StartSessionLog(com.microsoft.appcenter.analytics.ingestion.models.StartSessionLog) PageLog(com.microsoft.appcenter.analytics.ingestion.models.PageLog) EventLog(com.microsoft.appcenter.analytics.ingestion.models.EventLog) Log(com.microsoft.appcenter.ingestion.models.Log) HashMap(java.util.HashMap) Device(com.microsoft.appcenter.ingestion.models.Device) PageLog(com.microsoft.appcenter.analytics.ingestion.models.PageLog) EventLog(com.microsoft.appcenter.analytics.ingestion.models.EventLog) ArrayList(java.util.ArrayList) PageLogFactory(com.microsoft.appcenter.analytics.ingestion.models.json.PageLogFactory) DefaultLogSerializer(com.microsoft.appcenter.ingestion.models.json.DefaultLogSerializer) LogSerializer(com.microsoft.appcenter.ingestion.models.json.LogSerializer) Date(java.util.Date) DateTimeTypedProperty(com.microsoft.appcenter.ingestion.models.properties.DateTimeTypedProperty) LongTypedProperty(com.microsoft.appcenter.ingestion.models.properties.LongTypedProperty) StartSessionLogFactory(com.microsoft.appcenter.analytics.ingestion.models.json.StartSessionLogFactory) StartSessionLog(com.microsoft.appcenter.analytics.ingestion.models.StartSessionLog) BooleanTypedProperty(com.microsoft.appcenter.ingestion.models.properties.BooleanTypedProperty) ArrayList(java.util.ArrayList) List(java.util.List) LogContainer(com.microsoft.appcenter.ingestion.models.LogContainer) StringTypedProperty(com.microsoft.appcenter.ingestion.models.properties.StringTypedProperty) UUID(java.util.UUID) EventLogFactory(com.microsoft.appcenter.analytics.ingestion.models.json.EventLogFactory) DefaultLogSerializer(com.microsoft.appcenter.ingestion.models.json.DefaultLogSerializer) Test(org.junit.Test)

Aggregations

Device (com.microsoft.appcenter.ingestion.models.Device)46 Test (org.junit.Test)32 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)29 Context (android.content.Context)18 File (java.io.File)15 Date (java.util.Date)11 ManagedErrorLog (com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog)10 Matchers.anyString (org.mockito.Matchers.anyString)10 TestCrashException (com.microsoft.appcenter.crashes.model.TestCrashException)9 IOException (java.io.IOException)9 ErrorReport (com.microsoft.appcenter.crashes.model.ErrorReport)8 Log (com.microsoft.appcenter.ingestion.models.Log)8 JSONException (org.json.JSONException)8 PackageInfo (android.content.pm.PackageInfo)7 PackageManager (android.content.pm.PackageManager)7 Build (android.os.Build)7 InvocationOnMock (org.mockito.invocation.InvocationOnMock)7 TelephonyManager (android.telephony.TelephonyManager)6 Log.getStackTraceString (android.util.Log.getStackTraceString)6 DefaultLogSerializer (com.microsoft.appcenter.ingestion.models.json.DefaultLogSerializer)6