Skip to content

Commit

Permalink
Unified analytics events migration for BuildEvent (#137562)
Browse files Browse the repository at this point in the history
Related to tracker issue:
- flutter/flutter#128251
  • Loading branch information
eliasyishak authored Nov 1, 2023
1 parent 01b8854 commit 70456f5
Show file tree
Hide file tree
Showing 18 changed files with 313 additions and 33 deletions.
51 changes: 42 additions & 9 deletions packages/flutter_tools/lib/src/android/gradle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:math';
import 'package:crypto/crypto.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import 'package:xml/xml.dart';

import '../artifacts.dart';
Expand Down Expand Up @@ -149,6 +150,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
required FileSystem fileSystem,
required Artifacts artifacts,
required Usage usage,
required Analytics analytics,
required GradleUtils gradleUtils,
required Platform platform,
required AndroidStudio? androidStudio,
Expand All @@ -157,6 +159,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
_fileSystem = fileSystem,
_artifacts = artifacts,
_usage = usage,
_analytics = analytics,
_gradleUtils = gradleUtils,
_androidStudio = androidStudio,
_fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform),
Expand All @@ -168,6 +171,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
final FileSystem _fileSystem;
final Artifacts _artifacts;
final Usage _usage;
final Analytics _analytics;
final GradleUtils _gradleUtils;
final FileSystemUtils _fileSystemUtils;
final AndroidStudio? _androidStudio;
Expand Down Expand Up @@ -300,7 +304,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
@visibleForTesting int? maxRetries,
}) async {
if (!project.android.isSupportedVersion) {
_exitWithUnsupportedProjectMessage(_usage, _logger.terminal);
_exitWithUnsupportedProjectMessage(_usage, _logger.terminal, analytics: _analytics);
}

final List<ProjectMigrator> migrators = <ProjectMigrator>[
Expand All @@ -318,8 +322,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
final bool usesAndroidX = isAppUsingAndroidX(project.android.hostAppGradleRoot);
if (usesAndroidX) {
BuildEvent('app-using-android-x', type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: 'app-using-android-x', buildType: 'gradle'));
} else if (!usesAndroidX) {
BuildEvent('app-not-using-android-x', type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: 'app-not-using-android-x', buildType: 'gradle'));

_logger.printStatus("${_logger.terminal.warningMark} Your app isn't using AndroidX.", emphasis: true);
_logger.printStatus(
'To avoid potential build failures, you can quickly migrate your app '
Expand Down Expand Up @@ -488,6 +495,8 @@ class AndroidGradleBuilder implements AndroidBuilder {
if (exitCode != 0) {
if (detectedGradleError == null) {
BuildEvent('gradle-unknown-failure', type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: 'gradle-unknown-failure', buildType: 'gradle'));

throwToolExit(
'Gradle task $assembleTask failed with exit code $exitCode',
exitCode: exitCode,
Expand Down Expand Up @@ -520,21 +529,27 @@ class AndroidGradleBuilder implements AndroidBuilder {
configOnly: configOnly,
);
final String successEventLabel = 'gradle-${detectedGradleError!.eventLabel}-success';

BuildEvent(successEventLabel, type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: successEventLabel, buildType: 'gradle'));

return;
case GradleBuildStatus.exit:
// Continue and throw tool exit.
}
}
BuildEvent('gradle-${detectedGradleError?.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send();
final String usageLabel = 'gradle-${detectedGradleError?.eventLabel}-failure';
BuildEvent(usageLabel, type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: usageLabel, buildType: 'gradle'));

throwToolExit(
'Gradle task $assembleTask failed with exit code $exitCode',
exitCode: exitCode,
);
}

if (isBuildingBundle) {
final File bundleFile = findBundleFile(project, buildInfo, _logger, _usage);
final File bundleFile = findBundleFile(project, buildInfo, _logger, _usage, _analytics);
final String appSize = (buildInfo.mode == BuildMode.debug)
? '' // Don't display the size when building a debug variant.
: ' (${getSizeAsMB(bundleFile.lengthSync())})';
Expand All @@ -551,7 +566,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
}
// Gradle produced APKs.
final Iterable<String> apkFilesPaths = project.isModule
? findApkFilesModule(project, androidBuildInfo, _logger, _usage)
? findApkFilesModule(project, androidBuildInfo, _logger, _usage, _analytics)
: listApkPaths(androidBuildInfo);
final Directory apkDirectory = getApkDirectory(project);

Expand All @@ -563,6 +578,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
fileExtension: '.apk',
logger: _logger,
usage: _usage,
analytics: _analytics,
);
}

Expand Down Expand Up @@ -886,8 +902,14 @@ String _calculateSha(File file) {
return _hex(sha1.convert(bytes).bytes);
}

void _exitWithUnsupportedProjectMessage(Usage usage, Terminal terminal) {
void _exitWithUnsupportedProjectMessage(Usage usage, Terminal terminal, {required Analytics analytics}) {
BuildEvent('unsupported-project', type: 'gradle', eventError: 'gradle-plugin', flutterUsage: usage).send();
analytics.send(Event.flutterBuildInfo(
label: 'unsupported-project',
buildType: 'gradle',
error: 'gradle-plugin',
));

throwToolExit(
'${terminal.warningMark} Your app is using an unsupported Gradle project. '
'To fix this problem, create a new project by running `flutter create -t app <app-directory>` '
Expand All @@ -913,6 +935,7 @@ Iterable<String> findApkFilesModule(
AndroidBuildInfo androidBuildInfo,
Logger logger,
Usage usage,
Analytics analytics,
) {
final Iterable<String> apkFileNames = _apkFilesFor(androidBuildInfo);
final Directory apkDirectory = getApkDirectory(project);
Expand Down Expand Up @@ -948,6 +971,7 @@ Iterable<String> findApkFilesModule(
fileExtension: '.apk',
logger: logger,
usage: usage,
analytics: analytics,
);
}
return apks.map((File file) => file.path);
Expand Down Expand Up @@ -986,7 +1010,7 @@ Iterable<String> listApkPaths(
}

@visibleForTesting
File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger, Usage usage) {
File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger, Usage usage, Analytics analytics) {
final List<File> fileCandidates = <File>[
getBundleDirectory(project)
.childDirectory(camelCase(buildInfo.modeName))
Expand Down Expand Up @@ -1043,6 +1067,7 @@ File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger,
fileExtension: '.aab',
logger: logger,
usage: usage,
analytics: analytics,
);
}

Expand All @@ -1052,17 +1077,25 @@ Never _exitWithExpectedFileNotFound({
required String fileExtension,
required Logger logger,
required Usage usage,
required Analytics analytics,
}) {

final String androidGradlePluginVersion =
getGradleVersionForAndroidPlugin(project.android.hostAppGradleRoot, logger);
final String gradleBuildSettings = 'androidGradlePluginVersion: $androidGradlePluginVersion, '
'fileExtension: $fileExtension';

BuildEvent('gradle-expected-file-not-found',
type: 'gradle',
settings:
'androidGradlePluginVersion: $androidGradlePluginVersion, '
'fileExtension: $fileExtension',
settings: gradleBuildSettings,
flutterUsage: usage,
).send();
analytics.send(Event.flutterBuildInfo(
label: 'gradle-expected-file-not-found',
buildType: 'gradle',
settings: gradleBuildSettings,
));

throwToolExit(
'Gradle build failed to produce an $fileExtension file. '
"It's likely that this file was generated under ${project.android.buildDirectory.path}, "
Expand Down
6 changes: 6 additions & 0 deletions packages/flutter_tools/lib/src/android/gradle_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';

import '../base/common.dart';
import '../base/file_system.dart';
Expand Down Expand Up @@ -741,6 +742,11 @@ void exitWithNoSdkMessage() {
eventError: 'android-sdk-not-found',
flutterUsage: globals.flutterUsage)
.send();
globals.analytics.send(Event.flutterBuildInfo(
label: 'unsupported-project',
buildType: 'gradle',
error: 'android-sdk-not-found',
));
throwToolExit('${globals.logger.terminal.warningMark} No Android SDK found. '
'Try setting the ANDROID_HOME environment variable.');
}
Expand Down
15 changes: 11 additions & 4 deletions packages/flutter_tools/lib/src/commands/build_ios.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:unified_analytics/unified_analytics.dart';

import '../base/analyze_size.dart';
import '../base/common.dart';
Expand Down Expand Up @@ -669,7 +670,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand {
xcodeBuildResult = result;

if (!result.success) {
await diagnoseXcodeBuildFailure(result, globals.flutterUsage, globals.logger);
await diagnoseXcodeBuildFailure(result, globals.flutterUsage, globals.logger, globals.analytics);
final String presentParticiple = xcodeBuildAction == XcodeBuildAction.build ? 'building' : 'archiving';
throwToolExit('Encountered error while $presentParticiple for $logTarget.');
}
Expand Down Expand Up @@ -739,13 +740,19 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand {
final bool? impellerEnabled = globals.plistParser.getValueFromFile<bool>(
plistPath, PlistParser.kFLTEnableImpellerKey,
);
BuildEvent(
impellerEnabled == false

final String buildLabel = impellerEnabled == false
? 'plist-impeller-disabled'
: 'plist-impeller-enabled',
: 'plist-impeller-enabled';
BuildEvent(
buildLabel,
type: 'ios',
flutterUsage: globals.flutterUsage,
).send();
globals.analytics.send(Event.flutterBuildInfo(
label: buildLabel,
buildType: 'ios',
));

return FlutterCommandResult.success();
}
Expand Down
1 change: 1 addition & 0 deletions packages/flutter_tools/lib/src/commands/build_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ class BuildWebCommand extends BuildSubCommand {
fileSystem: globals.fs,
flutterVersion: globals.flutterVersion,
usage: globals.flutterUsage,
analytics: globals.analytics,
);
await webBuilder.buildWeb(
flutterProject,
Expand Down
2 changes: 2 additions & 0 deletions packages/flutter_tools/lib/src/context_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Future<T> runInContext<T>(
fileSystem: globals.fs,
artifacts: globals.artifacts!,
usage: globals.flutterUsage,
analytics: globals.analytics,
gradleUtils: globals.gradleUtils!,
platform: globals.platform,
androidStudio: globals.androidStudio,
Expand Down Expand Up @@ -387,6 +388,7 @@ Future<T> runInContext<T>(
platform: globals.platform,
fileSystem: globals.fs,
usage: globals.flutterUsage,
analytics: globals.analytics,
),
},
);
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_tools/lib/src/ios/devices.dart
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ class IOSDevice extends Device {
);
if (!buildResult.success) {
_logger.printError('Could not build the precompiled application for the device.');
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, _logger);
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, _logger, globals.analytics);
_logger.printError('');
return LaunchResult.failed();
}
Expand Down
29 changes: 24 additions & 5 deletions packages/flutter_tools/lib/src/ios/mac.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'dart:async';

import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';

import '../artifacts.dart';
import '../base/file_system.dart';
Expand Down Expand Up @@ -581,17 +582,35 @@ return result.exitCode != 0 &&
result.stdout.contains(kConcurrentRunFailureMessage2);
}

Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsage, Logger logger) async {
Future<void> diagnoseXcodeBuildFailure(
XcodeBuildResult result,
Usage flutterUsage,
Logger logger,
Analytics analytics,
) async {
final XcodeBuildExecution? xcodeBuildExecution = result.xcodeBuildExecution;
if (xcodeBuildExecution != null
&& xcodeBuildExecution.environmentType == EnvironmentType.physical
&& (result.stdout?.toUpperCase().contains('BITCODE') ?? false)) {
BuildEvent('xcode-bitcode-failure',
type: 'ios',
command: xcodeBuildExecution.buildCommands.toString(),
settings: xcodeBuildExecution.buildSettings.toString(),

const String label = 'xcode-bitcode-failure';
const String buildType = 'ios';
final String command = xcodeBuildExecution.buildCommands.toString();
final String settings = xcodeBuildExecution.buildSettings.toString();

BuildEvent(
label,
type: buildType,
command: command,
settings: settings,
flutterUsage: flutterUsage,
).send();
analytics.send(Event.flutterBuildInfo(
label: label,
buildType: buildType,
command: command,
settings: settings,
));
}

// Handle errors.
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_tools/lib/src/ios/simulators.dart
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ class IOSSimulator extends Device {
deviceID: id,
);
if (!buildResult.success) {
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, globals.logger);
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, globals.logger, globals.analytics);
throwToolExit('Could not build the application for the simulator.');
}

Expand Down
Loading

0 comments on commit 70456f5

Please sign in to comment.