Skip to content

Commit a32f0bb

Browse files
Add analytics package + setTelemetry method attached (flutter#124015)
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#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]>
1 parent eca86e8 commit a32f0bb

File tree

6 files changed

+124
-1
lines changed

6 files changed

+124
-1
lines changed

packages/flutter_tools/lib/runner.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import 'src/context_runner.dart';
2222
import 'src/doctor.dart';
2323
import 'src/globals.dart' as globals;
2424
import 'src/reporting/crash_reporting.dart';
25+
import 'src/reporting/reporting.dart';
2526
import 'src/runner/flutter_command.dart';
2627
import 'src/runner/flutter_command_runner.dart';
2728

@@ -61,6 +62,44 @@ Future<int> run(
6162
StackTrace? firstStackTrace;
6263
return runZoned<Future<int>>(() async {
6364
try {
65+
// Ensure that the consent message has been displayed
66+
if (globals.analytics.shouldShowMessage) {
67+
globals.logger.printStatus(globals.analytics.getConsentMessage);
68+
69+
// Invoking this will onboard the flutter tool onto
70+
// the package on the developer's machine and will
71+
// allow for events to be sent to Google Analytics
72+
// on subsequent runs of the flutter tool (ie. no events
73+
// will be sent on the first run to allow developers to
74+
// opt out of collection)
75+
globals.analytics.clientShowedMessage();
76+
}
77+
78+
// Disable analytics if user passes in the `--disable-telemetry` option
79+
// `flutter --disable-telemetry`
80+
//
81+
// Same functionality as `flutter config --no-analytics` for disabling
82+
// except with the `value` hard coded as false
83+
if (args.contains('--disable-telemetry')) {
84+
const bool value = false;
85+
// The tool sends the analytics event *before* toggling the flag
86+
// intentionally to be sure that opt-out events are sent correctly.
87+
AnalyticsConfigEvent(enabled: value).send();
88+
if (!value) {
89+
// Normally, the tool waits for the analytics to all send before the
90+
// tool exits, but only when analytics are enabled. When reporting that
91+
// analytics have been disable, the wait must be done here instead.
92+
await globals.flutterUsage.ensureAnalyticsSent();
93+
}
94+
globals.flutterUsage.enabled = value;
95+
globals.printStatus('Analytics reporting disabled.');
96+
97+
// TODO(eliasyishak): Set the telemetry for the unified_analytics
98+
// package as well, the above will be removed once we have
99+
// fully transitioned to using the new package
100+
await globals.analytics.setTelemetry(value);
101+
}
102+
64103
await runner.run(args);
65104

66105
// Triggering [runZoned]'s error callback does not necessarily mean that

packages/flutter_tools/lib/src/commands/config.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ class ConfigCommand extends FlutterCommand {
139139
}
140140
globals.flutterUsage.enabled = value;
141141
globals.printStatus('Analytics reporting ${value ? 'enabled' : 'disabled'}.');
142+
143+
// TODO(eliasyishak): Set the telemetry for the unified_analytics
144+
// package as well, the above will be removed once we have
145+
// fully transitioned to using the new package
146+
await globals.analytics.setTelemetry(value);
142147
}
143148

144149
if (argResults?.wasParsed('android-sdk') ?? false) {

packages/flutter_tools/lib/src/globals.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'package:intl/date_symbol_data_local.dart';
56
import 'package:process/process.dart';
7+
import 'package:unified_analytics/unified_analytics.dart';
68

79
import 'android/android_sdk.dart';
810
import 'android/android_studio.dart';
@@ -86,6 +88,22 @@ final BotDetector _defaultBotDetector = BotDetector(
8688
);
8789
Future<bool> get isRunningOnBot => botDetector.isRunningOnBot;
8890

91+
// Analytics instance for package:unified_analytics for telemetry
92+
// reporting for all Flutter and Dart related tooling
93+
Analytics get analytics => context.get<Analytics>() ?? getDefaultAnalytics();
94+
Analytics getDefaultAnalytics() {
95+
96+
initializeDateFormatting();
97+
final Analytics defaultAnalytics = Analytics(
98+
tool: DashTool.flutterTool,
99+
flutterChannel: flutterVersion.channel,
100+
flutterVersion: flutterVersion.frameworkVersion,
101+
dartVersion: flutterVersion.dartSdkVersion,
102+
);
103+
104+
return defaultAnalytics;
105+
}
106+
89107
/// Currently active implementation of the file system.
90108
///
91109
/// By default it uses local disk-based implementation. Override this in tests

packages/flutter_tools/lib/src/runner/flutter_command_runner.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class FlutterCommandRunner extends CommandRunner<void> {
7878
argParser.addFlag('suppress-analytics',
7979
negatable: false,
8080
help: 'Suppress analytics reporting when this command runs.');
81+
argParser.addFlag('disable-telemetry',
82+
negatable: false,
83+
help: 'Disable telemetry reporting when this command runs.');
8184
argParser.addOption('packages',
8285
hide: !verboseHelp,
8386
help: 'Path to your "package_config.json" file.');
@@ -185,6 +188,11 @@ class FlutterCommandRunner extends CommandRunner<void> {
185188
Future<void> runCommand(ArgResults topLevelResults) async {
186189
final Map<Type, Object?> contextOverrides = <Type, Object?>{};
187190

191+
// If the disable-telemetry flag has been passed, return out
192+
if (topLevelResults.wasParsed('disable-telemetry')) {
193+
return;
194+
}
195+
188196
// Don't set wrapColumns unless the user said to: if it's set, then all
189197
// wrapping will occur at this width explicitly, and won't adapt if the
190198
// terminal size changes during a run.

packages/flutter_tools/pubspec.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ dependencies:
4848
http_multi_server: 3.2.1
4949
convert: 3.1.1
5050
async: 2.11.0
51+
unified_analytics: 1.0.1
5152

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

107-
# PUBSPEC CHECKSUM: 7ab7
108+
# PUBSPEC CHECKSUM: 8913

packages/flutter_tools/test/general.shard/runner/runner_test.dart

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import 'package:flutter_tools/src/globals.dart' as globals;
1818
import 'package:flutter_tools/src/reporting/crash_reporting.dart';
1919
import 'package:flutter_tools/src/reporting/reporting.dart';
2020
import 'package:flutter_tools/src/runner/flutter_command.dart';
21+
import 'package:test/fake.dart';
22+
import 'package:unified_analytics/unified_analytics.dart';
2123

2224
import '../../src/common.dart';
2325
import '../../src/context.dart';
@@ -313,6 +315,29 @@ void main() {
313315
});
314316
});
315317
});
318+
319+
testUsingContext('runner disable telemetry with flag', () async {
320+
io.setExitFunctionForTests((int exitCode) {});
321+
322+
expect(globals.analytics.telemetryEnabled, true);
323+
expect(globals.analytics.shouldShowMessage, true);
324+
325+
await runner.run(
326+
<String>['--disable-telemetry'],
327+
() => <FlutterCommand>[],
328+
// This flutterVersion disables crash reporting.
329+
flutterVersion: '[user-branch]/',
330+
shutdownHooks: ShutdownHooks(),
331+
);
332+
333+
expect(globals.analytics.telemetryEnabled, false);
334+
},
335+
overrides: <Type, Generator>{
336+
Analytics: () => FakeAnalytics(),
337+
FileSystem: () => MemoryFileSystem.test(),
338+
ProcessManager: () => FakeProcessManager.any(),
339+
},
340+
);
316341
}
317342

318343
class CrashingFlutterCommand extends FlutterCommand {
@@ -451,3 +476,30 @@ class WaitingCrashReporter implements CrashReporter {
451476
return _future;
452477
}
453478
}
479+
480+
/// A fake [Analytics] that will be used to test
481+
/// the --disable-telemetry flag
482+
class FakeAnalytics extends Fake implements Analytics {
483+
bool _fakeTelemetryStatus = true;
484+
bool _fakeShowMessage = true;
485+
486+
@override
487+
String get getConsentMessage => 'message';
488+
489+
@override
490+
bool get shouldShowMessage => _fakeShowMessage;
491+
492+
@override
493+
void clientShowedMessage() {
494+
_fakeShowMessage = false;
495+
}
496+
497+
@override
498+
Future<void> setTelemetry(bool reportingBool) {
499+
_fakeTelemetryStatus = reportingBool;
500+
return Future<void>.value();
501+
}
502+
503+
@override
504+
bool get telemetryEnabled => _fakeTelemetryStatus;
505+
}

0 commit comments

Comments
 (0)