Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
e8778da1
Unverified
Commit
e8778da1
authored
Mar 18, 2020
by
Zachary Anderson
Committed by
GitHub
Mar 18, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] Don't crash when analytics fails to initialize (#52775)
parent
1444e772
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
103 additions
and
16 deletions
+103
-16
usage.dart
packages/flutter_tools/lib/src/reporting/usage.dart
+44
-7
analytics_test.dart
...ages/flutter_tools/test/general.shard/analytics_test.dart
+59
-9
No files found.
packages/flutter_tools/lib/src/reporting/usage.dart
View file @
e8778da1
...
...
@@ -74,11 +74,13 @@ abstract class Usage {
String
versionOverride
,
String
configDirOverride
,
String
logFile
,
AnalyticsFactory
analyticsIOFactory
,
@required
bool
runningOnBot
,
})
=>
_DefaultUsage
(
settingsName:
settingsName
,
versionOverride:
versionOverride
,
configDirOverride:
configDirOverride
,
logFile:
logFile
,
analyticsIOFactory:
analyticsIOFactory
,
runningOnBot:
runningOnBot
);
/// Uses the global [Usage] instance to send a 'command' to analytics.
...
...
@@ -152,12 +154,37 @@ abstract class Usage {
void
printWelcome
();
}
typedef
AnalyticsFactory
=
Analytics
Function
(
String
trackingId
,
String
applicationName
,
String
applicationVersion
,
{
String
analyticsUrl
,
Directory
documentDirectory
,
});
Analytics
_defaultAnalyticsIOFactory
(
String
trackingId
,
String
applicationName
,
String
applicationVersion
,
{
String
analyticsUrl
,
Directory
documentDirectory
,
})
{
return
AnalyticsIO
(
trackingId
,
applicationName
,
applicationVersion
,
analyticsUrl:
analyticsUrl
,
documentDirectory:
documentDirectory
,
);
}
class
_DefaultUsage
implements
Usage
{
_DefaultUsage
({
String
settingsName
=
'flutter'
,
String
versionOverride
,
String
configDirOverride
,
String
logFile
,
AnalyticsFactory
analyticsIOFactory
,
@required
bool
runningOnBot
,
})
{
final
FlutterVersion
flutterVersion
=
globals
.
flutterVersion
;
...
...
@@ -166,6 +193,8 @@ class _DefaultUsage implements Usage {
final
String
logFilePath
=
logFile
??
globals
.
platform
.
environment
[
'FLUTTER_ANALYTICS_LOG_FILE'
];
final
bool
usingLogFile
=
logFilePath
!=
null
&&
logFilePath
.
isNotEmpty
;
analyticsIOFactory
??=
_defaultAnalyticsIOFactory
;
if
(
// To support testing, only allow other signals to supress analytics
// when analytics are not being shunted to a file.
!
usingLogFile
&&
(
...
...
@@ -187,13 +216,21 @@ class _DefaultUsage implements Usage {
if
(
usingLogFile
)
{
_analytics
=
LogToFileAnalytics
(
logFilePath
);
}
else
{
_analytics
=
AnalyticsIO
(
_kFlutterUA
,
settingsName
,
version
,
documentDirectory:
configDirOverride
!=
null
?
globals
.
fs
.
directory
(
configDirOverride
)
:
null
,
);
try
{
_analytics
=
analyticsIOFactory
(
_kFlutterUA
,
settingsName
,
version
,
documentDirectory:
configDirOverride
!=
null
?
globals
.
fs
.
directory
(
configDirOverride
)
:
null
,
);
}
on
Exception
catch
(
e
)
{
globals
.
printTrace
(
'Failed to initialize analytics reporting:
$e
'
);
suppressAnalytics
=
true
;
_analytics
=
AnalyticsMock
();
return
;
}
}
assert
(
_analytics
!=
null
);
...
...
packages/flutter_tools/test/general.shard/analytics_test.dart
View file @
e8778da1
...
...
@@ -7,7 +7,6 @@ import 'package:file/memory.dart';
import
'package:flutter_tools/src/base/config.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/time.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/commands/build.dart'
;
...
...
@@ -15,12 +14,13 @@ import 'package:flutter_tools/src/commands/config.dart';
import
'package:flutter_tools/src/commands/doctor.dart'
;
import
'package:flutter_tools/src/doctor.dart'
;
import
'package:flutter_tools/src/features.dart'
;
import
'package:flutter_tools/src/globals.dart'
as
globals
;
import
'package:flutter_tools/src/reporting/reporting.dart'
;
import
'package:flutter_tools/src/runner/flutter_command.dart'
;
import
'package:flutter_tools/src/version.dart'
;
import
'package:flutter_tools/src/globals.dart'
as
globals
;
import
'package:mockito/mockito.dart'
;
import
'package:platform/platform.dart'
;
import
'package:usage/usage_io.dart'
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
...
...
@@ -63,6 +63,7 @@ void main() {
final
DoctorCommand
doctorCommand
=
DoctorCommand
();
final
CommandRunner
<
void
>
runner
=
createTestCommandRunner
(
doctorCommand
);
await
runner
.
run
(<
String
>[
'doctor'
]);
expect
(
count
,
0
);
},
overrides:
<
Type
,
Generator
>{
FlutterVersion:
()
=>
FlutterVersion
(
const
SystemClock
()),
...
...
@@ -86,6 +87,7 @@ void main() {
globals
.
flutterUsage
.
enabled
=
true
;
await
runner
.
run
(<
String
>[
'config'
]);
expect
(
count
,
0
);
},
overrides:
<
Type
,
Generator
>{
FlutterVersion:
()
=>
FlutterVersion
(
const
SystemClock
()),
...
...
@@ -103,6 +105,7 @@ void main() {
usage
.
sendCommand
(
'test'
);
final
String
featuresKey
=
cdKey
(
CustomDimensions
.
enabledFlutterFeatures
);
expect
(
globals
.
fs
.
file
(
'test'
).
readAsStringSync
(),
contains
(
'
$featuresKey
: enable-web'
));
},
overrides:
<
Type
,
Generator
>{
FlutterVersion:
()
=>
FlutterVersion
(
const
SystemClock
()),
...
...
@@ -125,7 +128,11 @@ void main() {
usage
.
sendCommand
(
'test'
);
final
String
featuresKey
=
cdKey
(
CustomDimensions
.
enabledFlutterFeatures
);
expect
(
globals
.
fs
.
file
(
'test'
).
readAsStringSync
(),
contains
(
'
$featuresKey
: enable-web,enable-linux-desktop,enable-macos-desktop'
));
expect
(
globals
.
fs
.
file
(
'test'
).
readAsStringSync
(),
contains
(
'
$featuresKey
: enable-web,enable-linux-desktop,enable-macos-desktop'
),
);
},
overrides:
<
Type
,
Generator
>{
FlutterVersion:
()
=>
FlutterVersion
(
const
SystemClock
()),
Config:
()
=>
mockFlutterConfig
,
...
...
@@ -159,7 +166,10 @@ void main() {
testUsingContext
(
'flutter commands send timing events'
,
()
async
{
mockTimes
=
<
int
>[
1000
,
2000
];
when
(
mockDoctor
.
diagnose
(
androidLicenses:
false
,
verbose:
false
)).
thenAnswer
((
_
)
async
=>
true
);
when
(
mockDoctor
.
diagnose
(
androidLicenses:
false
,
verbose:
false
,
)).
thenAnswer
((
_
)
async
=>
true
);
final
DoctorCommand
command
=
DoctorCommand
();
final
CommandRunner
<
void
>
runner
=
createTestCommandRunner
(
command
);
await
runner
.
run
(<
String
>[
'doctor'
]);
...
...
@@ -167,7 +177,12 @@ void main() {
verify
(
mockClock
.
now
()).
called
(
2
);
expect
(
verify
(
mockUsage
.
sendTiming
(
captureAny
,
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
))).
captured
,
verify
(
mockUsage
.
sendTiming
(
captureAny
,
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'flutter'
,
'doctor'
,
const
Duration
(
milliseconds:
1000
),
'success'
],
);
},
overrides:
<
Type
,
Generator
>{
...
...
@@ -186,7 +201,12 @@ void main() {
verify
(
mockClock
.
now
()).
called
(
2
);
expect
(
verify
(
mockUsage
.
sendTiming
(
captureAny
,
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
))).
captured
,
verify
(
mockUsage
.
sendTiming
(
captureAny
,
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'flutter'
,
'doctor'
,
const
Duration
(
milliseconds:
1000
),
'warning'
],
);
},
overrides:
<
Type
,
Generator
>{
...
...
@@ -197,6 +217,7 @@ void main() {
testUsingContext
(
'single command usage path'
,
()
async
{
final
FlutterCommand
doctorCommand
=
DoctorCommand
();
expect
(
await
doctorCommand
.
usagePath
,
'doctor'
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mockUsage
,
...
...
@@ -205,6 +226,7 @@ void main() {
testUsingContext
(
'compound command usage path'
,
()
async
{
final
BuildCommand
buildCommand
=
BuildCommand
();
final
FlutterCommand
buildApkCommand
=
buildCommand
.
subcommands
[
'apk'
]
as
FlutterCommand
;
expect
(
await
buildApkCommand
.
usagePath
,
'build/apk'
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mockUsage
,
...
...
@@ -226,6 +248,7 @@ void main() {
final
String
log
=
globals
.
fs
.
file
(
'analytics.log'
).
readAsStringSync
();
final
DateTime
dateTime
=
DateTime
.
fromMillisecondsSinceEpoch
(
kMillis
);
expect
(
log
.
contains
(
formatDateTime
(
dateTime
)),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
memoryFileSystem
,
...
...
@@ -255,6 +278,7 @@ void main() {
final
String
log
=
globals
.
fs
.
file
(
'analytics.log'
).
readAsStringSync
();
final
DateTime
dateTime
=
DateTime
.
fromMillisecondsSinceEpoch
(
kMillis
);
expect
(
log
.
contains
(
formatDateTime
(
dateTime
)),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
memoryFileSystem
,
...
...
@@ -273,7 +297,9 @@ void main() {
Directory
tempDir
;
setUp
(()
{
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_analytics_bots_test.'
);
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_analytics_bots_test.'
,
);
});
tearDown
(()
{
...
...
@@ -283,8 +309,8 @@ void main() {
testUsingContext
(
"don't send on bots with unknown version"
,
()
async
{
int
count
=
0
;
globals
.
flutterUsage
.
onSend
.
listen
((
Map
<
String
,
dynamic
>
data
)
=>
count
++);
await
createTestCommandRunner
().
run
(<
String
>[
'--version'
]);
expect
(
count
,
0
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Usage
(
...
...
@@ -299,8 +325,8 @@ void main() {
int
count
=
0
;
globals
.
flutterUsage
.
onSend
.
listen
((
Map
<
String
,
dynamic
>
data
)
=>
count
++);
globals
.
flutterUsage
.
enabled
=
true
;
await
createTestCommandRunner
().
run
(<
String
>[
'--version'
]);
expect
(
count
,
0
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Usage
(
...
...
@@ -310,9 +336,33 @@ void main() {
runningOnBot:
false
,
),
});
testUsingContext
(
'Uses AnalyticsMock when .flutter cannot be created'
,
()
async
{
final
Usage
usage
=
Usage
(
settingsName:
'flutter_bot_test'
,
versionOverride:
'dev/known'
,
configDirOverride:
tempDir
.
path
,
analyticsIOFactory:
throwingAnalyticsIOFactory
,
runningOnBot:
false
,
);
final
AnalyticsMock
analyticsMock
=
AnalyticsMock
();
expect
(
usage
.
clientId
,
analyticsMock
.
clientId
);
expect
(
usage
.
suppressAnalytics
,
isTrue
);
});
});
}
Analytics
throwingAnalyticsIOFactory
(
String
trackingId
,
String
applicationName
,
String
applicationVersion
,
{
String
analyticsUrl
,
Directory
documentDirectory
,
})
{
throw
const
FileSystemException
(
'Could not create file'
);
}
class
MockUsage
extends
Mock
implements
Usage
{}
class
MockDoctor
extends
Mock
implements
Doctor
{}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment