Skip to content

Commit fad5a66

Browse files
bwilkersonCommit Bot
authored and
Commit Bot
committed
Use a JSON encoding for percentile data being sent to analytics
Change-Id: Ie96f81e9cdc7585a5027db7b44f7f39cb7e763b8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/247240 Reviewed-by: Phil Quitslund <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 7a8f742 commit fad5a66

File tree

4 files changed

+31
-38
lines changed

4 files changed

+31
-38
lines changed

pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,10 @@ class _PluginData {
210210
}
211211

212212
/// Return an encoding of the [usageCounts].
213-
Map<String, String> _encodeUsageCounts() {
214-
var encoded = <String, String>{};
213+
Map<String, Object> _encodeUsageCounts() {
214+
var encoded = <String, Object>{};
215215
for (var entry in usageCounts.entries) {
216-
encoded[entry.key] = entry.value.toAnalyticsString();
216+
encoded[entry.key] = entry.value.toJson();
217217
}
218218
return encoded;
219219
}

pkg/analysis_server/lib/src/analytics/percentile_calculator.dart

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:convert';
6+
57
/// An object used to calculate percentile-based analytics.
68
///
79
/// See https://en.wikipedia.org/wiki/Percentile.
@@ -52,18 +54,19 @@ class PercentileCalculator {
5254
}
5355

5456
/// Return a string that is suitable for sending to the analytics service.
55-
String toAnalyticsString() {
56-
var buffer = StringBuffer();
57-
buffer.write(_valueCount);
58-
buffer.write('[');
57+
String toAnalyticsString() => json.encode(toJson());
58+
59+
/// Return a map that can be encoded as JSON that represents the state of this
60+
/// calculator.
61+
Map<String, Object> toJson() {
62+
var percentiles = <int>[];
5963
for (var p = 5; p <= 100; p += 5) {
60-
if (p > 5) {
61-
buffer.write(', ');
62-
}
63-
buffer.write(percentile(p));
64+
percentiles.add(percentile(p));
6465
}
65-
buffer.write(']');
66-
return buffer.toString();
66+
return {
67+
'count': _valueCount,
68+
'percentiles': percentiles,
69+
};
6770
}
6871

6972
@override

pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:convert';
6+
57
import 'package:analysis_server/protocol/protocol.dart';
68
import 'package:analysis_server/src/analytics/google_analytics_manager.dart';
79
import 'package:analysis_server/src/analytics/percentile_calculator.dart';
@@ -89,11 +91,11 @@ class GoogleAnalyticsManagerTest {
8991
_MockPluginInfo('b'),
9092
]));
9193
manager.shutdown();
94+
var counts =
95+
'{"count":1,"percentiles":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}';
9296
analytics.assertEvents([
9397
_ExpectedEvent.session(parameters: {
94-
'plugins': '{"recordCount":1,"rootCounts":{"a":"1[0, 0, 0, 0, 0, 0, '
95-
'0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]","b":"1[0, 0, 0, 0, 0, '
96-
'0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"}}'
98+
'plugins': '{"recordCount":1,"rootCounts":{"a":$counts,"b":$counts}}'
9799
}),
98100
]);
99101
}
@@ -203,33 +205,21 @@ class _IsPercentiles extends Matcher {
203205

204206
@override
205207
bool matches(Object? item, Map matchState) {
206-
if (item is! String || !item.endsWith(']')) {
208+
if (item is! String) {
207209
return false;
208210
}
209-
var index = item.indexOf('[');
210-
var count = item.substring(0, index);
211-
if (!_isStringEncodedPositiveInt(count)) {
211+
var map = json.decode(item);
212+
if (map is! Map || map.length != 2) {
212213
return false;
213214
}
214-
var percentiles = item.substring(index + 1, item.length - 1).split(', ');
215-
if (percentiles.length != 20) {
215+
if (map['count'] is! int) {
216216
return false;
217217
}
218-
for (var percentile in percentiles) {
219-
if (!_isStringEncodedPositiveInt(percentile)) {
220-
return false;
221-
}
222-
}
223-
return true;
224-
}
225-
226-
bool _isStringEncodedPositiveInt(String item) {
227-
try {
228-
var value = int.parse(item);
229-
return value >= 0;
230-
} catch (exception) {
218+
var percentiles = map['percentiles'];
219+
if (percentiles is! List || percentiles.length != 20) {
231220
return false;
232221
}
222+
return !percentiles.any((element) => element is! int);
233223
}
234224
}
235225

pkg/analysis_server/test/src/analytics/percentile_calculator_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@ class PercentileCalculatorTest {
2222
}
2323
calculator.clear();
2424
expect(calculator.toAnalyticsString(),
25-
'0[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]');
25+
'{"count":0,"percentiles":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}');
2626
}
2727

2828
void test_toAnalyticsString_empty() {
2929
expect(calculator.toAnalyticsString(),
30-
'0[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]');
30+
'{"count":0,"percentiles":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}');
3131
}
3232

3333
void test_toAnalyticsString_evenDistribution() {
3434
for (int i = 1; i <= 100; i++) {
3535
calculator.addValue(i);
3636
}
3737
expect(calculator.toAnalyticsString(),
38-
'100[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]');
38+
'{"count":100,"percentiles":[5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100]}');
3939
}
4040
}

0 commit comments

Comments
 (0)