Bug 1119061 - Part 2: Add Sync 1.1 -> Sync 1.5 migration telemetry. r=rnewman

========

f7eaef78c1
Author: Nick Alexander <nalexander@mozilla.com>
Date:   Wed Jan 14 17:36:29 2015 -0800

    Bug 1119061 - Part 2: Add Sync 1.1 to Sync 1.5 migration telemetry.

========

e64f968703
Author: Nick Alexander <nalexander@mozilla.com>
Date:   Mon Jan 12 16:30:09 2015 -0800

    Bug 1119061 - Part 1: Add TelemetryWrapper.

    This is cribbed, more or less directly, from the stumbler.

========

51299e74e4
Author: Nick Alexander <nalexander@mozilla.com>
Date:   Mon Jan 12 17:26:41 2015 -0800

    Bug 1119061 - Pre: Clear Firefox Account notifications when Android Account is removed.

--HG--
extra : rebase_source : 1bea34bc9fb4efd2e75cf965f59b5c568dc0ca0e
This commit is contained in:
Nick Alexander 2015-01-16 17:42:34 -08:00
parent 01e6889b20
commit 5019e233d7
8 changed files with 138 additions and 1 deletions

View File

@ -780,6 +780,7 @@ sync_java_files = [
'background/common/log/writers/StringLogWriter.java',
'background/common/log/writers/TagLogWriter.java',
'background/common/log/writers/ThreadLocalTagLogWriter.java',
'background/common/telemetry/TelemetryWrapper.java',
'background/datareporting/TelemetryRecorder.java',
'background/db/CursorDumper.java',
'background/db/Tab.java',
@ -1132,6 +1133,7 @@ sync_java_files = [
'sync/synchronizer/UnbundleError.java',
'sync/synchronizer/UnexpectedSessionException.java',
'sync/SynchronizerConfiguration.java',
'sync/telemetry/TelemetryContract.java',
'sync/ThreadPool.java',
'sync/UnexpectedJSONException.java',
'sync/UnknownSynchronizerConfigurationVersionException.java',

View File

@ -0,0 +1,56 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.background.common.telemetry;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.mozilla.gecko.background.common.log.Logger;
/**
* Android Background Services are normally built into Fennec, but can also be
* built as a stand-alone APK for rapid local development. The current Telemetry
* implementation is coupled to Gecko, and Background Services should not
* interact with Gecko directly. To maintain this independence, Background
* Services lazily introspects the relevant Telemetry class from the enclosing
* package, warning but otherwise ignoring failures during introspection or
* invocation.
* <p>
* It is possible that Background Services will introspect and invoke the
* Telemetry implementation while Gecko is not running. In this case, the Fennec
* process itself buffers Telemetry events until such time as they can be
* flushed to disk and uploaded. <b>There is no guarantee that all Telemetry
* events will be uploaded!</b> Depending on the volume of data and the
* application lifecycle, Telemetry events may be dropped.
*/
public class TelemetryWrapper {
private static final String LOG_TAG = TelemetryWrapper.class.getSimpleName();
// Marking this volatile maintains thread safety cheaply.
private static volatile Method mAddToHistogram;
public static void addToHistogram(String key, int value) {
if (mAddToHistogram == null) {
try {
final Class<?> telemetry = Class.forName("org.mozilla.gecko.Telemetry");
mAddToHistogram = telemetry.getMethod("addToHistogram", String.class, int.class);
} catch (ClassNotFoundException e) {
Logger.warn(LOG_TAG, "org.mozilla.gecko.Telemetry class found!");
return;
} catch (NoSuchMethodException e) {
Logger.warn(LOG_TAG, "org.mozilla.gecko.Telemetry.addToHistogram(String, int) method not found!");
return;
}
}
if (mAddToHistogram != null) {
try {
mAddToHistogram.invoke(null, key, value);
} catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
Logger.warn(LOG_TAG, "Got exception invoking telemetry!");
}
}
}
}

View File

@ -9,6 +9,7 @@ import java.util.concurrent.Executors;
import org.mozilla.gecko.R;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper;
import org.mozilla.gecko.background.fxa.FxAccountClient;
import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
import org.mozilla.gecko.background.fxa.FxAccountClient20;
@ -22,6 +23,7 @@ import org.mozilla.gecko.fxa.login.Engaged;
import org.mozilla.gecko.fxa.login.State;
import org.mozilla.gecko.fxa.tasks.FxAccountSignInTask;
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
import org.mozilla.gecko.sync.telemetry.TelemetryContract;
import android.content.Intent;
import android.os.Bundle;
@ -150,6 +152,8 @@ public abstract class FxAccountAbstractUpdateCredentialsActivity extends FxAccou
startActivity(successIntent);
}
finish();
TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATIONS_COMPLETED, 1);
}
}

View File

@ -6,6 +6,8 @@ package org.mozilla.gecko.fxa.receivers;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.fxa.FxAccountConstants;
import org.mozilla.gecko.fxa.sync.FxAccountNotificationManager;
import org.mozilla.gecko.fxa.sync.FxAccountSyncAdapter;
import org.mozilla.gecko.sync.config.AccountPickler;
import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
@ -63,6 +65,9 @@ public class FxAccountDeletedService extends IntentService {
// Delete client database and non-local tabs.
Logger.info(LOG_TAG, "Deleting the entire clients database and non-local tabs");
FennecTabsRepository.deleteNonLocalClientsAndTabs(context);
// Remove any displayed notifications.
new FxAccountNotificationManager(FxAccountSyncAdapter.NOTIFICATION_ID).clear(context);
}
public static void deletePickle(final Context context) {

View File

@ -7,12 +7,14 @@ package org.mozilla.gecko.fxa.sync;
import org.mozilla.gecko.BrowserLocaleManager;
import org.mozilla.gecko.R;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper;
import org.mozilla.gecko.background.fxa.FxAccountUtils;
import org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivity;
import org.mozilla.gecko.fxa.activities.FxAccountStatusActivity;
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
import org.mozilla.gecko.fxa.login.State;
import org.mozilla.gecko.fxa.login.State.Action;
import org.mozilla.gecko.sync.telemetry.TelemetryContract;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -43,6 +45,17 @@ public class FxAccountNotificationManager {
this.notificationId = notificationId;
}
/**
* Remove all Firefox Account related notifications from the notification manager.
*
* @param context
* Android context.
*/
public void clear(Context context) {
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(notificationId);
}
/**
* Reflect new Firefox Account state to the notification manager: show or hide
* notifications reflecting the state of a Firefox Account.
@ -72,6 +85,8 @@ public class FxAccountNotificationManager {
final String text;
final Intent notificationIntent;
if (action == Action.NeedsFinishMigrating) {
TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATION_NOTIFICATIONS_OFFERED, 1);
title = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_title);
text = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_text, state.email);
notificationIntent = new Intent(context, FxAccountFinishMigratingActivity.class);

View File

@ -67,7 +67,7 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
public static final String SYNC_EXTRAS_RESPECT_LOCAL_RATE_LIMIT = "respect_local_rate_limit";
public static final String SYNC_EXTRAS_RESPECT_REMOTE_SERVER_BACKOFF = "respect_remote_server_backoff";
protected static final int NOTIFICATION_ID = LOG_TAG.hashCode();
public static final int NOTIFICATION_ID = LOG_TAG.hashCode();
// Tracks the last seen storage hostname for backoff purposes.
private static final String PREF_BACKOFF_STORAGE_HOST = "backoffStorageHost";

View File

@ -7,6 +7,7 @@ package org.mozilla.gecko.sync;
import java.net.URISyntaxException;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper;
import org.mozilla.gecko.background.fxa.FxAccountUtils;
import org.mozilla.gecko.fxa.FxAccountConstants;
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
@ -18,6 +19,7 @@ import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate;
import org.mozilla.gecko.sync.net.SyncStorageResponse;
import org.mozilla.gecko.sync.stage.AbstractNonRepositorySyncStage;
import org.mozilla.gecko.sync.stage.NoSuchStageException;
import org.mozilla.gecko.sync.telemetry.TelemetryContract;
/**
* The purpose of this class is to talk to a Sync 1.1 server and check
@ -152,6 +154,7 @@ public class MigrationSentinelSyncStage extends AbstractNonRepositorySyncStage {
private void onMigrated() {
Logger.info(LOG_TAG, "Account migrated!");
TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATIONS_SUCCEEDED, 1);
session.config.persistLastMigrationSentinelCheckTimestamp(fetchTimestamp);
session.abort(null, "Account migrated.");
}
@ -163,6 +166,7 @@ public class MigrationSentinelSyncStage extends AbstractNonRepositorySyncStage {
private void onError(Exception ex, String reason) {
Logger.info(LOG_TAG, "Could not migrate: " + reason, ex);
TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATIONS_FAILED, 1);
session.abort(ex, reason);
}
@ -181,6 +185,9 @@ public class MigrationSentinelSyncStage extends AbstractNonRepositorySyncStage {
public void handleRequestSuccess(SyncStorageResponse response) {
Logger.info(LOG_TAG, "Found " + META_FXA_CREDENTIALS + " record; attempting migration.");
setTimestamp(response.normalizedWeaveTimestamp());
TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATION_SENTINELS_SEEN, 1);
try {
final ExtendedJSONObject body = response.jsonObjectBody();
final CryptoRecord cryptoRecord = CryptoRecord.fromJSONRecord(body);

View File

@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.sync.telemetry;
public class TelemetryContract {
/**
* We are a Sync 1.1 (legacy) client, and we downloaded a migration sentinel.
*/
public static final String SYNC11_MIGRATION_SENTINELS_SEEN = "FENNEC_SYNC11_MIGRATION_SENTINELS_SEEN";
/**
* We are a Sync 1.1 (legacy) client and we have downloaded a migration
* sentinel, but there was an error creating a Firefox Account from that
* sentinel.
* <p>
* We have logged the error and are ignoring that sentinel.
*/
public static final String SYNC11_MIGRATIONS_FAILED = "FENNEC_SYNC11_MIGRATIONS_FAILED";
/**
* We are a Sync 1.1 (legacy) client and we have downloaded a migration
* sentinel, and there was no reported error creating a Firefox Account from
* that sentinel.
* <p>
* We have created a Firefox Account corresponding to the sentinel and have
* queued the existing Old Sync account for removal.
*/
public static final String SYNC11_MIGRATIONS_SUCCEEDED = "FENNEC_SYNC11_MIGRATIONS_SUCCEEDED";
/**
* We are (now) a Sync 1.5 (Firefox Accounts-based) client that migrated from
* Sync 1.1. We have presented the user the "complete upgrade" notification.
* <p>
* We will offer every time a sync is triggered, including when a notification
* is already pending.
*/
public static final String SYNC11_MIGRATION_NOTIFICATIONS_OFFERED = "FENNEC_SYNC11_MIGRATION_NOTIFICATIONS_OFFERED";
/**
* We are (now) a Sync 1.5 (Firefox Accounts-based) client that migrated from
* Sync 1.1. We have presented the user the "complete upgrade" notification
* and they have successfully completed the upgrade process by entering their
* Firefox Account credentials.
*/
public static final String SYNC11_MIGRATIONS_COMPLETED = "FENNEC_SYNC11_MIGRATIONS_COMPLETED";
}