Skip to content

Commit

Permalink
Add analytics package + setTelemetry method attached (#124015)
Browse files Browse the repository at this point in the history
The first of many PRs for transitioning to `package:unified_analytics`.
This PR is only focused on disabling and enabling telemetry via the
`flutter config --[no-]analytics` flag

Fixes: flutter/flutter#121617

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat

---------

Co-authored-by: Christopher Fujino <[email protected]>
Co-authored-by: Christopher Fujino <[email protected]>
  • Loading branch information
3 people committed Apr 5, 2023
1 parent eca86e8 commit a32f0bb
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 1 deletion.
39 changes: 39 additions & 0 deletions packages/flutter_tools/lib/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'src/context_runner.dart';
import 'src/doctor.dart';
import 'src/globals.dart' as globals;
import 'src/reporting/crash_reporting.dart';
import 'src/reporting/reporting.dart';
import 'src/runner/flutter_command.dart';
import 'src/runner/flutter_command_runner.dart';

Expand Down Expand Up @@ -61,6 +62,44 @@ Future<int> run(
StackTrace? firstStackTrace;
return runZoned<Future<int>>(() async {
try {
// Ensure that the consent message has been displayed
if (globals.analytics.shouldShowMessage) {
globals.logger.printStatus(globals.analytics.getConsentMessage);

// Invoking this will onboard the flutter tool onto
// the package on the developer's machine and will
// allow for events to be sent to Google Analytics
// on subsequent runs of the flutter tool (ie. no events
// will be sent on the first run to allow developers to
// opt out of collection)
globals.analytics.clientShowedMessage();
}

// Disable analytics if user passes in the `--disable-telemetry` option
// `flutter --disable-telemetry`
//
// Same functionality as `flutter config --no-analytics` for disabling
// except with the `value` hard coded as false
if (args.contains('--disable-telemetry')) {
const bool value = false;
// The tool sends the analytics event *before* toggling the flag
// intentionally to be sure that opt-out events are sent correctly.
AnalyticsConfigEvent(enabled: value).send();
if (!value) {
// Normally, the tool waits for the analytics to all send before the
// tool exits, but only when analytics are enabled. When reporting that
// analytics have been disable, the wait must be done here instead.
await globals.flutterUsage.ensureAnalyticsSent();
}
globals.flutterUsage.enabled = value;
globals.printStatus('Analytics reporting disabled.');

// TODO(eliasyishak): Set the telemetry for the unified_analytics
// package as well, the above will be removed once we have
// fully transitioned to using the new package
await globals.analytics.setTelemetry(value);
}

await runner.run(args);

// Triggering [runZoned]'s error callback does not necessarily mean that
Expand Down
5 changes: 5 additions & 0 deletions packages/flutter_tools/lib/src/commands/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ class ConfigCommand extends FlutterCommand {
}
globals.flutterUsage.enabled = value;
globals.printStatus('Analytics reporting ${value ? 'enabled' : 'disabled'}.');

// TODO(eliasyishak): Set the telemetry for the unified_analytics
// package as well, the above will be removed once we have
// fully transitioned to using the new package
await globals.analytics.setTelemetry(value);
}

if (argResults?.wasParsed('android-sdk') ?? false) {
Expand Down
18 changes: 18 additions & 0 deletions packages/flutter_tools/lib/src/globals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:intl/date_symbol_data_local.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';

import 'android/android_sdk.dart';
import 'android/android_studio.dart';
Expand Down Expand Up @@ -86,6 +88,22 @@ final BotDetector _defaultBotDetector = BotDetector(
);
Future<bool> get isRunningOnBot => botDetector.isRunningOnBot;

// Analytics instance for package:unified_analytics for telemetry
// reporting for all Flutter and Dart related tooling
Analytics get analytics => context.get<Analytics>() ?? getDefaultAnalytics();
Analytics getDefaultAnalytics() {

initializeDateFormatting();
final Analytics defaultAnalytics = Analytics(
tool: DashTool.flutterTool,
flutterChannel: flutterVersion.channel,
flutterVersion: flutterVersion.frameworkVersion,
dartVersion: flutterVersion.dartSdkVersion,
);

return defaultAnalytics;
}

/// Currently active implementation of the file system.
///
/// By default it uses local disk-based implementation. Override this in tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class FlutterCommandRunner extends CommandRunner<void> {
argParser.addFlag('suppress-analytics',
negatable: false,
help: 'Suppress analytics reporting when this command runs.');
argParser.addFlag('disable-telemetry',
negatable: false,
help: 'Disable telemetry reporting when this command runs.');
argParser.addOption('packages',
hide: !verboseHelp,
help: 'Path to your "package_config.json" file.');
Expand Down Expand Up @@ -185,6 +188,11 @@ class FlutterCommandRunner extends CommandRunner<void> {
Future<void> runCommand(ArgResults topLevelResults) async {
final Map<Type, Object?> contextOverrides = <Type, Object?>{};

// If the disable-telemetry flag has been passed, return out
if (topLevelResults.wasParsed('disable-telemetry')) {
return;
}

// Don't set wrapColumns unless the user said to: if it's set, then all
// wrapping will occur at this width explicitly, and won't adapt if the
// terminal size changes during a run.
Expand Down
3 changes: 2 additions & 1 deletion packages/flutter_tools/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dependencies:
http_multi_server: 3.2.1
convert: 3.1.1
async: 2.11.0
unified_analytics: 1.0.1

# We depend on very specific internal implementation details of the
# 'test' package, which change between versions, so when upgrading
Expand Down Expand Up @@ -104,4 +105,4 @@ dartdoc:
# Exclude this package from the hosted API docs.
nodoc: true

# PUBSPEC CHECKSUM: 7ab7
# PUBSPEC CHECKSUM: 8913
52 changes: 52 additions & 0 deletions packages/flutter_tools/test/general.shard/runner/runner_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/reporting/crash_reporting.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';

import '../../src/common.dart';
import '../../src/context.dart';
Expand Down Expand Up @@ -313,6 +315,29 @@ void main() {
});
});
});

testUsingContext('runner disable telemetry with flag', () async {
io.setExitFunctionForTests((int exitCode) {});

expect(globals.analytics.telemetryEnabled, true);
expect(globals.analytics.shouldShowMessage, true);

await runner.run(
<String>['--disable-telemetry'],
() => <FlutterCommand>[],
// This flutterVersion disables crash reporting.
flutterVersion: '[user-branch]/',
shutdownHooks: ShutdownHooks(),
);

expect(globals.analytics.telemetryEnabled, false);
},
overrides: <Type, Generator>{
Analytics: () => FakeAnalytics(),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
},
);
}

class CrashingFlutterCommand extends FlutterCommand {
Expand Down Expand Up @@ -451,3 +476,30 @@ class WaitingCrashReporter implements CrashReporter {
return _future;
}
}

/// A fake [Analytics] that will be used to test
/// the --disable-telemetry flag
class FakeAnalytics extends Fake implements Analytics {
bool _fakeTelemetryStatus = true;
bool _fakeShowMessage = true;

@override
String get getConsentMessage => 'message';

@override
bool get shouldShowMessage => _fakeShowMessage;

@override
void clientShowedMessage() {
_fakeShowMessage = false;
}

@override
Future<void> setTelemetry(bool reportingBool) {
_fakeTelemetryStatus = reportingBool;
return Future<void>.value();
}

@override
bool get telemetryEnabled => _fakeTelemetryStatus;
}

0 comments on commit a32f0bb

Please sign in to comment.