From a00e27099275163fe0d1f7050e6280ee3b3f3f3f Mon Sep 17 00:00:00 2001 From: fractalwrench Date: Tue, 9 Jan 2018 10:03:02 +0000 Subject: [PATCH 1/4] respect notifyReleaseStages for session tracking --- .../java/com/bugsnag/android/SessionTracker.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java index dd6bb90f33..62e6e23aee 100644 --- a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java +++ b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java @@ -73,7 +73,10 @@ void startNewSession(@NonNull Date date, @Nullable User user, boolean autoCaptur Session session = new Session(UUID.randomUUID().toString(), date, user); session.setAutoCaptured(autoCaptured); - if (configuration.shouldAutoCaptureSessions() || !autoCaptured) { + String releaseStage = getReleaseStage(); + boolean notifyForRelease = client != null && configuration.shouldNotifyForReleaseStage(releaseStage); + + if ((configuration.shouldAutoCaptureSessions() || !autoCaptured) && notifyForRelease) { sessionQueue.add(session); sessionStore.write(session); // store session for sending } @@ -82,6 +85,14 @@ void startNewSession(@NonNull Date date, @Nullable User user, boolean autoCaptur } + private String getReleaseStage() { + if (configuration.getReleaseStage() != null) { + return configuration.getReleaseStage(); + } else { + return AppDataSummary.guessReleaseStage(context); + } + } + @Nullable synchronized Session getCurrentSession() { return currentSession; From 2172c503e0a7400e633f71c0a98e779a18704699 Mon Sep 17 00:00:00 2001 From: fractalwrench Date: Tue, 9 Jan 2018 10:34:17 +0000 Subject: [PATCH 2/4] when autocapture enabled via config, track existing session if present --- .../main/java/com/bugsnag/android/Client.java | 47 +++++++++---------- .../com/bugsnag/android/Configuration.java | 9 ++++ .../com/bugsnag/android/SessionTracker.java | 42 +++++++++++++---- 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/sdk/src/main/java/com/bugsnag/android/Client.java b/sdk/src/main/java/com/bugsnag/android/Client.java index 0304611319..56f494a96e 100644 --- a/sdk/src/main/java/com/bugsnag/android/Client.java +++ b/sdk/src/main/java/com/bugsnag/android/Client.java @@ -81,7 +81,7 @@ public class Client extends Observable implements Observer { private final long launchTimeMs; private final EventReceiver eventReceiver = new EventReceiver(); - private final SessionTracker sessionTracker; + final SessionTracker sessionTracker; private ErrorReportApiClient errorReportApiClient; private SessionTrackingApiClient sessionTrackingApiClient; private final Handler handler; @@ -141,10 +141,30 @@ public Client(@NonNull Context androidContext, @NonNull Configuration configurat sessionTracker = new SessionTracker(configuration, this, sessionStore, sessionTrackingApiClient, appContext); - if (configuration.shouldAutoCaptureSessions()) { // create initial session - sessionTracker.startNewSession(new Date(), null, true); + // Set up and collect constant app and device diagnostics + SharedPreferences sharedPref = appContext.getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE); + + appData = new AppData(appContext, config, sessionTracker); + deviceData = new DeviceData(appContext, sharedPref); + + // Set up breadcrumbs + breadcrumbs = new Breadcrumbs(); + + // Set sensible defaults + setProjectPackages(appContext.getPackageName()); + + if (config.getPersistUserBetweenSessions()) { + // Check to see if a user was stored in the SharedPreferences + user.setId(sharedPref.getString(USER_ID_KEY, deviceData.getUserId())); + user.setName(sharedPref.getString(USER_NAME_KEY, null)); + user.setEmail(sharedPref.getString(USER_EMAIL_KEY, null)); + } else { + user.setId(deviceData.getUserId()); } + // create initial session + sessionTracker.startNewSession(new Date(), user, true); + if (appContext instanceof Application) { Application application = (Application) appContext; application.registerActivityLifecycleCallbacks(sessionTracker); @@ -169,27 +189,6 @@ public Client(@NonNull Context androidContext, @NonNull Configuration configurat } } - // Set up and collect constant app and device diagnostics - SharedPreferences sharedPref = appContext.getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE); - - appData = new AppData(appContext, config, sessionTracker); - deviceData = new DeviceData(appContext, sharedPref); - - // Set up breadcrumbs - breadcrumbs = new Breadcrumbs(); - - // Set sensible defaults - setProjectPackages(appContext.getPackageName()); - - if (config.getPersistUserBetweenSessions()) { - // Check to see if a user was stored in the SharedPreferences - user.setId(sharedPref.getString(USER_ID_KEY, deviceData.getUserId())); - user.setName(sharedPref.getString(USER_NAME_KEY, null)); - user.setEmail(sharedPref.getString(USER_EMAIL_KEY, null)); - } else { - user.setId(deviceData.getUserId()); - } - // Create the error store that is used in the exception handler errorStore = new ErrorStore(config, appContext); diff --git a/sdk/src/main/java/com/bugsnag/android/Configuration.java b/sdk/src/main/java/com/bugsnag/android/Configuration.java index 4c33e70f4c..9fd18ae37b 100644 --- a/sdk/src/main/java/com/bugsnag/android/Configuration.java +++ b/sdk/src/main/java/com/bugsnag/android/Configuration.java @@ -357,6 +357,15 @@ public boolean shouldAutoCaptureSessions() { */ public void setAutoCaptureSessions(boolean autoCapture) { this.autoCaptureSessions = autoCapture; + + if (autoCapture) { // track any existing sessions + Client client = Bugsnag.getClient(); + + //noinspection ConstantConditions + if (client != null && client.sessionTracker != null) { + client.sessionTracker.onAutoCaptureEnabled(); + } + } } /** diff --git a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java index 62e6e23aee..22c275dd14 100644 --- a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java +++ b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java @@ -40,6 +40,7 @@ class SessionTracker implements Application.ActivityLifecycleCallbacks { private long lastForegroundMs; private Long sessionStartMs; private Session currentSession; + private boolean trackedFirstSession = false; SessionTracker(Configuration configuration, Client client, SessionStore sessionStore, SessionTrackingApiClient apiClient, Context context) { @@ -68,21 +69,42 @@ class SessionTracker implements Application.ActivityLifecycleCallbacks { */ void startNewSession(@NonNull Date date, @Nullable User user, boolean autoCaptured) { synchronized (sessionStore) { - sessionStartMs = date.getTime(); + currentSession = generateSession(date, user, autoCaptured); + trackSessionIfNeeded(autoCaptured, currentSession); + } + } - Session session = new Session(UUID.randomUUID().toString(), date, user); - session.setAutoCaptured(autoCaptured); + @NonNull + private Session generateSession(@NonNull Date date, @Nullable User user, boolean autoCaptured) { + sessionStartMs = date.getTime(); + Session session = new Session(UUID.randomUUID().toString(), date, user); + session.setAutoCaptured(autoCaptured); + return session; + } - String releaseStage = getReleaseStage(); - boolean notifyForRelease = client != null && configuration.shouldNotifyForReleaseStage(releaseStage); + private void trackSessionIfNeeded(boolean autoCaptured, Session session) { + String releaseStage = getReleaseStage(); + boolean notifyForRelease = client != null && configuration.shouldNotifyForReleaseStage(releaseStage); - if ((configuration.shouldAutoCaptureSessions() || !autoCaptured) && notifyForRelease) { - sessionQueue.add(session); - sessionStore.write(session); // store session for sending - } - currentSession = session; + if ((configuration.shouldAutoCaptureSessions() || !autoCaptured) && notifyForRelease) { + sessionQueue.add(session); + sessionStore.write(session); // store session for sending + trackedFirstSession = true; } + } + /** + * Track a new session when auto capture is enabled via config after initialisation. + */ + void onAutoCaptureEnabled() { + synchronized (sessionStore) { + if (!trackedFirstSession) { + if (currentSession == null) { // unlikely case, will be initialised later + return; + } + trackSessionIfNeeded(currentSession.isAutoCaptured(), currentSession); + } + } } private String getReleaseStage() { From 933279358e3c5bd449420b32b21409cbac1d8d50 Mon Sep 17 00:00:00 2001 From: fractalwrench Date: Tue, 9 Jan 2018 14:23:15 +0000 Subject: [PATCH 3/4] document session tracker method --- sdk/src/main/java/com/bugsnag/android/SessionTracker.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java index 22c275dd14..4b006a0350 100644 --- a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java +++ b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java @@ -82,6 +82,13 @@ private Session generateSession(@NonNull Date date, @Nullable User user, boolean return session; } + /** + * Determines whether or not a session should be tracked. If this is true, the session will be + * stored and sent to the Bugsnag API, otherwise no action will occur in this method. + * + * @param autoCaptured whether the session was automatically captured by the SDK or not + * @param session the session + */ private void trackSessionIfNeeded(boolean autoCaptured, Session session) { String releaseStage = getReleaseStage(); boolean notifyForRelease = client != null && configuration.shouldNotifyForReleaseStage(releaseStage); From acf41b00e9016fef2b8e808da25af52fb6803817 Mon Sep 17 00:00:00 2001 From: fractalwrench Date: Tue, 9 Jan 2018 14:29:58 +0000 Subject: [PATCH 4/4] remove typo null check on client --- sdk/src/main/java/com/bugsnag/android/SessionTracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java index 4b006a0350..0d10f8d9a5 100644 --- a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java +++ b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java @@ -91,7 +91,7 @@ private Session generateSession(@NonNull Date date, @Nullable User user, boolean */ private void trackSessionIfNeeded(boolean autoCaptured, Session session) { String releaseStage = getReleaseStage(); - boolean notifyForRelease = client != null && configuration.shouldNotifyForReleaseStage(releaseStage); + boolean notifyForRelease = configuration.shouldNotifyForReleaseStage(releaseStage); if ((configuration.shouldAutoCaptureSessions() || !autoCaptured) && notifyForRelease) { sessionQueue.add(session);