Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(331)

Unified Diff: packages/usage/lib/src/usage_impl.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « packages/usage/example/ga.dart ('k') | packages/usage/lib/src/usage_impl_html.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/usage/lib/src/usage_impl.dart
diff --git a/packages/usage/lib/src/usage_impl.dart b/packages/usage/lib/src/usage_impl.dart
index 307b6ba5a39434adb830aa3a456378c56518f8ea..df529e38b6e5090a01ea4471003f866ea1e909e8 100644
--- a/packages/usage/lib/src/usage_impl.dart
+++ b/packages/usage/lib/src/usage_impl.dart
@@ -2,15 +2,11 @@
// 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.
-library usage_impl;
-
import 'dart:async';
import 'dart:math' as math;
-import 'uuid.dart';
import '../usage.dart';
-
-final int _MAX_EXCEPTION_LENGTH = 100;
+import '../uuid/uuid.dart';
String postEncode(Map<String, dynamic> map) {
// &foo=bar
@@ -21,11 +17,11 @@ String postEncode(Map<String, dynamic> map) {
}
/**
- * A throttling algorithim. This models the throttling after a bucket with
+ * A throttling algorithm. This models the throttling after a bucket with
* water dripping into it at the rate of 1 drop per second. If the bucket has
* water when an operation is requested, 1 drop of water is removed and the
- * operation is performed. If not the operation is skipped. This algorithim
- * lets operations be peformed in bursts without throttling, but holds the
+ * operation is performed. If not the operation is skipped. This algorithm
+ * lets operations be performed in bursts without throttling, but holds the
* overall average rate of operations to 1 per second.
*/
class ThrottlingBucket {
@@ -60,11 +56,16 @@ class ThrottlingBucket {
}
}
-abstract class AnalyticsImpl extends Analytics {
- static const String _GA_URL = 'https://www.google-analytics.com/collect';
+class AnalyticsImpl implements Analytics {
+ static const String _defaultAnalyticsUrl =
+ 'https://www.google-analytics.com/collect';
- /// Tracking ID / Property ID.
+ @override
final String trackingId;
+ @override
+ final String applicationName;
+ @override
+ final String applicationVersion;
final PersistentProperties properties;
final PostHandler postHandler;
@@ -74,60 +75,100 @@ abstract class AnalyticsImpl extends Analytics {
final List<Future> _futures = [];
+ @override
+ AnalyticsOpt analyticsOpt = AnalyticsOpt.optOut;
+
+ String _url;
+
+ StreamController<Map<String, dynamic>> _sendController =
+ new StreamController.broadcast(sync: true);
+
AnalyticsImpl(this.trackingId, this.properties, this.postHandler,
- {String applicationName, String applicationVersion}) {
+ {this.applicationName, this.applicationVersion, String analyticsUrl}) {
assert(trackingId != null);
if (applicationName != null) setSessionValue('an', applicationName);
if (applicationVersion != null) setSessionValue('av', applicationVersion);
+
+ _url = analyticsUrl ?? _defaultAnalyticsUrl;
}
- bool get optIn => properties['optIn'] == true;
+ bool _firstRun;
+
+ @override
+ bool get firstRun {
+ if (_firstRun == null) {
+ _firstRun = properties['firstRun'] == null;
+
+ if (properties['firstRun'] != false) {
+ properties['firstRun'] = false;
+ }
+ }
+
+ return _firstRun;
+ }
- set optIn(bool value) {
- properties['optIn'] = value;
+ @override
+ bool get enabled {
+ bool optIn = analyticsOpt == AnalyticsOpt.optIn;
+ return optIn
+ ? properties['enabled'] == true
+ : properties['enabled'] != false;
}
- bool get hasSetOptIn => properties['optIn'] != null;
+ @override
+ set enabled(bool value) {
+ properties['enabled'] = value;
+ }
- Future sendScreenView(String viewName) {
+ @override
+ Future sendScreenView(String viewName, {Map<String, String> parameters}) {
Map<String, dynamic> args = {'cd': viewName};
+ if (parameters != null) {
+ args.addAll(parameters);
+ }
return _sendPayload('screenview', args);
}
- Future sendEvent(String category, String action, {String label, int value}) {
- if (!optIn) return new Future.value();
-
+ @override
+ Future sendEvent(String category, String action,
+ {String label, int value, Map<String, String> parameters}) {
Map<String, dynamic> args = {'ec': category, 'ea': action};
if (label != null) args['el'] = label;
if (value != null) args['ev'] = value;
+ if (parameters != null) {
+ args.addAll(parameters);
+ }
return _sendPayload('event', args);
}
+ @override
Future sendSocial(String network, String action, String target) {
- if (!optIn) return new Future.value();
-
Map<String, dynamic> args = {'sn': network, 'sa': action, 'st': target};
return _sendPayload('social', args);
}
- Future sendTiming(String variableName, int time, {String category,
- String label}) {
- if (!optIn) return new Future.value();
-
+ @override
+ Future sendTiming(String variableName, int time,
+ {String category, String label}) {
Map<String, dynamic> args = {'utv': variableName, 'utt': time};
if (label != null) args['utl'] = label;
if (category != null) args['utc'] = category;
return _sendPayload('timing', args);
}
- AnalyticsTimer startTimer(String variableName, {String category, String label}) {
- return new AnalyticsTimer(this,
- variableName, category: category, label: label);
+ @override
+ AnalyticsTimer startTimer(String variableName,
+ {String category, String label}) {
+ return new AnalyticsTimer(this, variableName,
+ category: category, label: label);
}
+ @override
Future sendException(String description, {bool fatal}) {
- if (!optIn) return new Future.value();
+ // We trim exceptions to a max length; google analytics will apply it's own
+ // truncation, likely around 150 chars or so.
+ const int maxExceptionLength = 1000;
// In order to ensure that the client of this API is not sending any PII
// data, we strip out any stack trace that may reference a path on the
@@ -136,8 +177,10 @@ abstract class AnalyticsImpl extends Analytics {
description = description.substring(0, description.indexOf('file:/'));
}
- if (description != null && description.length > _MAX_EXCEPTION_LENGTH) {
- description = description.substring(0, _MAX_EXCEPTION_LENGTH);
+ description = description.replaceAll('\n', '; ');
+
+ if (description.length > maxExceptionLength) {
+ description = description.substring(0, maxExceptionLength);
}
Map<String, dynamic> args = {'exd': description};
@@ -145,6 +188,10 @@ abstract class AnalyticsImpl extends Analytics {
return _sendPayload('exception', args);
}
+ @override
+ dynamic getSessionValue(String param) => _variableMap[param];
+
+ @override
void setSessionValue(String param, dynamic value) {
if (value == null) {
_variableMap.remove(param);
@@ -153,6 +200,10 @@ abstract class AnalyticsImpl extends Analytics {
}
}
+ @override
+ Stream<Map<String, dynamic>> get onSend => _sendController.stream;
+
+ @override
Future waitForLastPing({Duration timeout}) {
Future f = Future.wait(_futures).catchError((e) => null);
@@ -163,33 +214,43 @@ abstract class AnalyticsImpl extends Analytics {
return f;
}
+ @override
+ void close() => postHandler.close();
+
+ @override
+ String get clientId => properties['clientId'] ??= new Uuid().generateV4();
+
/**
- * Anonymous Client ID. The value of this field should be a random UUID v4.
+ * Send raw data to analytics. Callers should generally use one of the typed
+ * methods (`sendScreenView`, `sendEvent`, ...).
+ *
+ * Valid values for [hitType] are: 'pageview', 'screenview', 'event',
+ * 'transaction', 'item', 'social', 'exception', and 'timing'.
*/
- String get _clientId => properties['clientId'];
-
- void _initClientId() {
- if (_clientId == null) {
- properties['clientId'] = new Uuid().generateV4();
- }
+ Future sendRaw(String hitType, Map<String, dynamic> args) {
+ return _sendPayload(hitType, args);
}
- // Valid values for [hitType] are: 'pageview', 'screenview', 'event',
- // 'transaction', 'item', 'social', 'exception', and 'timing'.
+ /**
+ * Valid values for [hitType] are: 'pageview', 'screenview', 'event',
+ * 'transaction', 'item', 'social', 'exception', and 'timing'.
+ */
Future _sendPayload(String hitType, Map<String, dynamic> args) {
- if (_bucket.removeDrop()) {
- _initClientId();
+ if (!enabled) return new Future.value();
+ if (_bucket.removeDrop()) {
_variableMap.forEach((key, value) {
args[key] = value;
});
args['v'] = '1'; // protocol version
args['tid'] = trackingId;
- args['cid'] = _clientId;
+ args['cid'] = clientId;
args['t'] = hitType;
- return _recordFuture(postHandler.sendPost(_GA_URL, args));
+ _sendController.add(args);
+
+ return _recordFuture(postHandler.sendPost(_url, args));
} else {
return new Future.value();
}
@@ -206,7 +267,7 @@ abstract class AnalyticsImpl extends Analytics {
* of these injected into it. There are default implementations for `dart:io`
* and `dart:html` clients.
*
- * The [name] paramater is used to uniquely store these properties on disk /
+ * The [name] parameter is used to uniquely store these properties on disk /
* persistent storage.
*/
abstract class PersistentProperties {
@@ -214,8 +275,12 @@ abstract class PersistentProperties {
PersistentProperties(this.name);
- dynamic operator[](String key);
- void operator[]=(String key, dynamic value);
+ dynamic operator [](String key);
+ void operator []=(String key, dynamic value);
+
+ /// Re-read settings from the backing store. This may be a no-op on some
+ /// platforms.
+ void syncSettings();
}
/**
@@ -229,4 +294,7 @@ abstract class PersistentProperties {
*/
abstract class PostHandler {
Future sendPost(String url, Map<String, dynamic> parameters);
+
+ /// Free any used resources.
+ void close();
}
« no previous file with comments | « packages/usage/example/ga.dart ('k') | packages/usage/lib/src/usage_impl_html.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698