Skip to content

Commit

Permalink
Migrate pub to use package:unified_analytics (#4031)
Browse files Browse the repository at this point in the history
  • Loading branch information
bkonyi authored Oct 31, 2023
1 parent 68dc2f5 commit 90ef5f9
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 170 deletions.
10 changes: 2 additions & 8 deletions lib/src/pub_embeddable_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:usage/usage.dart';
import 'package:unified_analytics/unified_analytics.dart';

import 'command.dart' show PubCommand, PubTopLevel;
import 'command.dart';
Expand All @@ -27,17 +27,11 @@ import 'utils.dart';

/// The information needed for the embedded pub command to send analytics.
final class PubAnalytics {
/// Name of the custom dimension of the dependency kind.
final String dependencyKindCustomDimensionName;

final Analytics? Function() _analyticsGetter;

Analytics? get analytics => _analyticsGetter();

PubAnalytics(
this._analyticsGetter, {
required this.dependencyKindCustomDimensionName,
});
PubAnalytics(this._analyticsGetter);
}

/// Exposes the `pub` commands as a command to be embedded in another command
Expand Down
25 changes: 7 additions & 18 deletions lib/src/solver/result.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:unified_analytics/unified_analytics.dart';

import '../http.dart';
import '../io.dart';
Expand Down Expand Up @@ -158,29 +159,17 @@ class SolveResult {
DependencyType.direct: 'direct',
DependencyType.none: 'transitive',
}[_root.pubspec.dependencyType(package.name)]!;
analytics.sendEvent(
'pub-get',
package.name,
label: package.version.canonicalizedVersion,
value: 1,
parameters: {
'ni': '1', // We consider a pub-get a non-interactive event.
pubAnalytics.dependencyKindCustomDimensionName: dependencyKind,
},
analytics.send(
Event.pubGet(
packageName: package.name,
version: package.version.canonicalizedVersion,
dependencyType: dependencyKind,
),
);
log.fine(
'Sending analytics hit for "pub-get" of ${package.name} version ${package.version} as dependency-kind $dependencyKind',
);
}

analytics.sendTiming(
'resolution',
resolutionTime.inMilliseconds,
category: 'pub-get',
);
log.fine(
'Sending analytics timing "pub-get" took ${resolutionTime.inMilliseconds} milliseconds',
);
}

@override
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dependencies:
stack_trace: ^1.10.0
tar: ^1.0.1
typed_data: ^1.3.1
usage: ^4.0.2
unified_analytics: ^4.0.1
yaml: ^3.1.0
yaml_edit: ^2.0.0

Expand Down
75 changes: 1 addition & 74 deletions test/embedding/embedding_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as path;
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart';
import 'package:pub/src/io.dart' show EnvironmentKeys;
Expand Down Expand Up @@ -87,7 +85,7 @@ extension on GoldenTestContext {
Future<void> main() async {
setUpAll(() async {
final tempDir = Directory.systemTemp.createTempSync();
snapshot = path.join(tempDir.path, 'command_runner.dart.snapshot');
snapshot = p.join(tempDir.path, 'command_runner.dart.snapshot');
final r = Process.runSync(
Platform.resolvedExecutable,
['--snapshot=$snapshot', _commandRunner],
Expand Down Expand Up @@ -191,77 +189,6 @@ main() {
);
});

test('analytics', () async {
await servePackages()
..serve('foo', '1.0.0', deps: {'bar': 'any'})
..serve('bar', '1.0.0');
await d.dir('dep', [
d.pubspec({
'name': 'dep',
'environment': {'sdk': '^3.0.0'},
}),
]).create();
final app = d.dir(appPath, [
d.appPubspec(
dependencies: {
'foo': '1.0.0',
// The path dependency should not go to analytics.
'dep': {'path': '../dep'},
},
),
]);
await app.create();

final buffer = StringBuffer();

await runEmbeddingToBuffer(
['pub', 'get'],
buffer,
workingDirectory: app.io.path,
environment: {...getPubTestEnvironment(), '_PUB_LOG_ANALYTICS': 'true'},
);
final analytics = buffer
.toString()
.split('\n')
.where((line) => line.startsWith('[E] [analytics]: '))
.map((line) => json.decode(line.substring('[E] [analytics]: '.length)));
expect(analytics, {
{
'hitType': 'event',
'message': {
'category': 'pub-get',
'action': 'foo',
'label': '1.0.0',
'value': 1,
'cd1': 'direct',
'ni': '1',
},
},
{
'hitType': 'event',
'message': {
'category': 'pub-get',
'action': 'bar',
'label': '1.0.0',
'value': 1,
'cd1': 'transitive',
'ni': '1',
},
},
{
'hitType': 'timing',
'message': {
'variableName': 'resolution',
'time': isA<int>(),
'category': 'pub-get',
'label': null,
},
},
});
// Don't write the logs to file on a normal run.
expect(File(logFile).existsSync(), isFalse);
});

test('`embedding --verbose pub` is verbose', () async {
await servePackages();
final buffer = StringBuffer();
Expand Down
69 changes: 0 additions & 69 deletions tool/test-bin/pub_command_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
/// A trivial embedding of the pub command. Used from tests.
library;

import 'dart:convert';
import 'dart:io';

import 'package:args/args.dart';
Expand All @@ -15,9 +14,6 @@ import 'package:pub/src/command.dart';
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/log.dart' as log;
import 'package:pub/src/utils.dart';
import 'package:usage/usage.dart';

final Analytics loggingAnalytics = _LoggingAnalytics();

/// A command for explicitly throwing an exception, to test the handling of
/// unexpected exceptions.
Expand Down Expand Up @@ -83,15 +79,8 @@ class Runner extends CommandRunner<int> {
late ArgResults _results;

Runner() : super('pub_command_runner', 'Tests the embeddable pub command.') {
final analytics = Platform.environment['_PUB_LOG_ANALYTICS'] == 'true'
? PubAnalytics(
() => loggingAnalytics,
dependencyKindCustomDimensionName: 'cd1',
)
: null;
addCommand(
pubCommand(
analytics: analytics,
isVerbose: () => _results.flag('verbose'),
)
..addSubcommand(ThrowingCommand())
Expand Down Expand Up @@ -124,61 +113,3 @@ class Runner extends CommandRunner<int> {
Future<void> main(List<String> arguments) async {
exitCode = await Runner().run(arguments);
}

class _LoggingAnalytics extends AnalyticsMock {
_LoggingAnalytics() {
onSend.listen((event) {
stderr.writeln('[analytics]${json.encode(event)}');
});
}

@override
bool get firstRun => false;

@override
Future sendScreenView(String viewName, {Map<String, String>? parameters}) {
parameters ??= <String, String>{};
parameters['viewName'] = viewName;
return _log('screenView', parameters);
}

@override
Future sendEvent(
String category,
String action, {
String? label,
int? value,
Map<String, String>? parameters,
}) {
parameters ??= <String, String>{};
return _log(
'event',
{'category': category, 'action': action, 'label': label, 'value': value}
..addAll(parameters),
);
}

@override
Future sendSocial(String network, String action, String target) =>
_log('social', {'network': network, 'action': action, 'target': target});

@override
Future sendTiming(
String variableName,
int time, {
String? category,
String? label,
}) {
return _log('timing', {
'variableName': variableName,
'time': time,
'category': category,
'label': label,
});
}

Future<void> _log(String hitType, Map message) async {
final encoded = json.encode({'hitType': hitType, 'message': message});
stderr.writeln('[analytics]: $encoded');
}
}

0 comments on commit 90ef5f9

Please sign in to comment.