Merge pull request #92 from dart-lang/usage_3.0
Usage 3.0
diff --git a/changelog.md b/changelog.md
index 68d72da..71df07c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -5,6 +5,8 @@
- removed the Flutter specific entry-point; Flutter apps can now use the
regular `dart:io` entrypoint (AnalyticsIO)
- moved the uuid library from `lib/src/` to `lib/uuid/`
+- fixed an issue with reporting the user language for the dart:io provider
+- send additional lines for reported exceptions
## 2.2.2
- adjust the Flutter usage client to Flutter API changes
diff --git a/example/ga.dart b/example/ga.dart
index 3dfada1..bf0807e 100644
--- a/example/ga.dart
+++ b/example/ga.dart
@@ -23,7 +23,8 @@
await ga.sendScreenView('home');
await ga.sendScreenView('files');
- await ga.sendException('foo exception, line 123:56');
+ await ga
+ .sendException('foo error:\n${sanitizeStacktrace(StackTrace.current)}');
await ga.sendTiming('writeDuration', 123);
await ga.sendEvent('create', 'consoleapp', label: 'Console App');
print('pinged ${ua}');
diff --git a/lib/src/usage_impl.dart b/lib/src/usage_impl.dart
index 5953a74..105fe36 100644
--- a/lib/src/usage_impl.dart
+++ b/lib/src/usage_impl.dart
@@ -8,8 +8,6 @@
import '../usage.dart';
import '../uuid/uuid.dart';
-final int _MAX_EXCEPTION_LENGTH = 100;
-
String postEncode(Map<String, dynamic> map) {
// &foo=bar
return map.keys.map((key) {
@@ -157,6 +155,10 @@
}
Future sendException(String description, {bool fatal}) {
+ // 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
// user's drive (file:/...).
@@ -164,8 +166,10 @@
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};
diff --git a/lib/src/usage_impl_html.dart b/lib/src/usage_impl_html.dart
index c227906..7752fe5 100644
--- a/lib/src/usage_impl_html.dart
+++ b/lib/src/usage_impl_html.dart
@@ -8,6 +8,10 @@
import 'usage_impl.dart';
+/// An interface to a Google Analytics session, suitable for use in web apps.
+///
+/// [analyticsUrl] is an optional replacement for the default Google Analytics
+/// URL (`https://www.google-analytics.com/collect`).
class AnalyticsHtml extends AnalyticsImpl {
AnalyticsHtml(
String trackingId, String applicationName, String applicationVersion,
diff --git a/lib/src/usage_impl_io.dart b/lib/src/usage_impl_io.dart
index c062732..fe5cc44 100644
--- a/lib/src/usage_impl_io.dart
+++ b/lib/src/usage_impl_io.dart
@@ -10,11 +10,14 @@
import 'usage_impl.dart';
-/// Create a new Analytics instance.
+/// An interface to a Google Analytics session, suitable for use in command-line
+/// applications.
///
/// `trackingId`, `applicationName`, and `applicationVersion` values should be supplied.
/// `analyticsUrl` is optional, and lets user's substitute their own analytics URL for
-/// the default. `documentDirectory` is where the analytics settings are stored. It
+/// the default.
+///
+/// `documentDirectory` is where the analytics settings are stored. It
/// defaults to the user home directory. For regular `dart:io` apps this doesn't need to
/// be supplied. For Flutter applications, you should pass in a value like
/// `PathProvider.getApplicationDocumentsDirectory()`.
@@ -29,7 +32,12 @@
new IOPostHandler(),
applicationName: applicationName,
applicationVersion: applicationVersion,
- analyticsUrl: analyticsUrl);
+ analyticsUrl: analyticsUrl) {
+ final String locale = getPlatformLocale();
+ if (locale != null) {
+ setSessionValue('ul', locale);
+ }
+ }
}
String _createUserAgent() {
@@ -136,9 +144,8 @@
int index = locale.indexOf('.');
if (index != null) locale = locale.substring(0, index);
- // Convert `en_US` to `en`.
- index = locale.indexOf('_');
- if (index != null) locale = locale.substring(0, index);
+ // Convert `en_US` to `en-us`.
+ locale = locale.replaceAll('_', '-').toLowerCase();
}
return locale;
diff --git a/lib/usage.dart b/lib/usage.dart
index 108200f..13f98d6 100644
--- a/lib/usage.dart
+++ b/lib/usage.dart
@@ -29,6 +29,9 @@
// Matches file:/, non-ws, /, non-ws, .dart
final RegExp _pathRegex = new RegExp(r'file:/\S+/(\S+\.dart)');
+// Match multiple tabs or spaces.
+final RegExp _tabOrSpaceRegex = new RegExp(r'[\t ]+');
+
/**
* An interface to a Google Analytics session. [AnalyticsHtml] and [AnalyticsIO]
* are concrete implementations of this interface. [AnalyticsMock] can be used
@@ -297,10 +300,7 @@
if (shorten) {
// Shorten the stacktrace up a bit.
- str = str
- .replaceAll('(package:', '(')
- .replaceAll('(dart:', '(')
- .replaceAll(new RegExp(r'\s+'), ' ');
+ str = str.replaceAll(_tabOrSpaceRegex, ' ');
}
return str;
diff --git a/lib/usage_html.dart b/lib/usage_html.dart
index 80247b1..569c1eb 100644
--- a/lib/usage_html.dart
+++ b/lib/usage_html.dart
@@ -2,42 +2,12 @@
// 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.
-/**
- * In order to use this library import the `usage_html.dart` file and
- * instantiate the [AnalyticsHtml] class.
- *
- * You'll need to provide a Google Analytics tracking ID, the application name,
- * and the application version.
- */
+/// In order to use this library import the `usage_html.dart` file and
+/// instantiate the [AnalyticsHtml] class.
+///
+/// You'll need to provide a Google Analytics tracking ID, the application name,
+/// and the application version.
library usage_html;
-import 'dart:html';
-
-import 'src/usage_impl.dart';
-import 'src/usage_impl_html.dart';
-
+export 'src/usage_impl_html.dart' show AnalyticsHtml;
export 'usage.dart';
-
-/**
- * An interface to a Google Analytics session, suitable for use in web apps.
- *
- * [analyticsUrl] is an optional replacement for the default Google Analytics
- * URL (`https://www.google-analytics.com/collect`).
- */
-class AnalyticsHtml extends AnalyticsImpl {
- AnalyticsHtml(
- String trackingId, String applicationName, String applicationVersion,
- {String analyticsUrl})
- : super(trackingId, new HtmlPersistentProperties(applicationName),
- new HtmlPostHandler(),
- applicationName: applicationName,
- applicationVersion: applicationVersion,
- analyticsUrl: analyticsUrl) {
- int screenWidth = window.screen.width;
- int screenHeight = window.screen.height;
-
- setSessionValue('sr', '${screenWidth}x$screenHeight');
- setSessionValue('sd', '${window.screen.pixelDepth}-bits');
- setSessionValue('ul', window.navigator.language);
- }
-}
diff --git a/lib/usage_io.dart b/lib/usage_io.dart
index 6a015e5..5e35e94 100644
--- a/lib/usage_io.dart
+++ b/lib/usage_io.dart
@@ -2,34 +2,12 @@
// 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.
-/**
- * In order to use this library import the `usage_io.dart` file and
- * instantiate the [AnalyticsIO] class.
- *
- * You'll need to provide a Google Analytics tracking ID, the application name,
- * and the application version.
- */
+/// In order to use this library import the `usage_io.dart` file and
+/// instantiate the [AnalyticsIO] class.
+///
+/// You'll need to provide a Google Analytics tracking ID, the application name,
+/// and the application version.
library usage_io;
-import 'src/usage_impl.dart';
-import 'src/usage_impl_io.dart';
-
+export 'src/usage_impl_io.dart' show AnalyticsIO;
export 'usage.dart';
-
-/**
- * An interface to a Google Analytics session, suitable for use in command-line
- * applications.
- *
- * [analyticsUrl] is an optional replacement for the default Google Analytics
- * URL (`https://www.google-analytics.com/collect`).
- */
-class AnalyticsIO extends AnalyticsImpl {
- AnalyticsIO(
- String trackingId, String applicationName, String applicationVersion,
- {String analyticsUrl})
- : super(trackingId, new IOPersistentProperties(applicationName),
- new IOPostHandler(),
- applicationName: applicationName,
- applicationVersion: applicationVersion,
- analyticsUrl: analyticsUrl);
-}
diff --git a/lib/uuid/uuid.dart b/lib/uuid/uuid.dart
index 5261c8f..eaafeb2 100644
--- a/lib/uuid/uuid.dart
+++ b/lib/uuid/uuid.dart
@@ -2,31 +2,25 @@
// 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.
-/**
- * A UUID generator library.
- */
+/// A UUID generator library.
library uuid;
import 'dart:math' show Random;
-/**
- * A UUID generator.
- *
- * This will generate unique IDs in the format:
- *
- * f47ac10b-58cc-4372-a567-0e02b2c3d479
- *
- * The generated uuids are 128 bit numbers encoded in a specific string format.
- * For more information, see
- * [en.wikipedia.org/wiki/Universally_unique_identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier).
- */
+/// A UUID generator.
+///
+/// This will generate unique IDs in the format:
+///
+/// f47ac10b-58cc-4372-a567-0e02b2c3d479
+///
+/// The generated uuids are 128 bit numbers encoded in a specific string format.
+/// For more information, see
+/// [en.wikipedia.org/wiki/Universally_unique_identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier).
class Uuid {
- Random _random = new Random();
+ final Random _random = new Random();
- /**
- * Generate a version 4 (random) uuid. This is a uuid scheme that only uses
- * random numbers as the source of the generated uuid.
- */
+ /// Generate a version 4 (random) uuid. This is a uuid scheme that only uses
+ /// random numbers as the source of the generated uuid.
String generateV4() {
// Generate xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx / 8-4-4-4-12.
int special = 8 + _random.nextInt(4);
diff --git a/test/hit_types_test.dart b/test/hit_types_test.dart
index ab78e38..7aab2d3 100644
--- a/test/hit_types_test.dart
+++ b/test/hit_types_test.dart
@@ -123,12 +123,5 @@
mock.sendException('foo bar (file:///Users/foobar/tmp/error.dart:3:13)');
expect(mock.last['exd'], 'foo bar (');
});
-
- test('long description trimmed', () {
- String str = '0123456789abcdefghijklmnopqrstuvwxyz';
- AnalyticsImplMock mock = createMock();
- mock.sendException(str + str + str + str + str);
- expect(mock.last['exd'].length, 100);
- });
});
}
diff --git a/test/usage_test.dart b/test/usage_test.dart
index c0e5664..8c4cedb 100644
--- a/test/usage_test.dart
+++ b/test/usage_test.dart
@@ -50,14 +50,14 @@
expect(
sanitizeStacktrace('foo (file:///Users/foo/tmp/error.dart:3:13)\n'
'bar (file:///Users/foo/tmp/error.dart:3:13)'),
- 'foo (error.dart:3:13) bar (error.dart:3:13)');
+ 'foo (error.dart:3:13)\nbar (error.dart:3:13)');
});
test('shorten 3', () {
expect(
sanitizeStacktrace('foo (package:foo/foo.dart:3:13)\n'
'bar (dart:async/schedule_microtask.dart:41)'),
- 'foo (foo/foo.dart:3:13) bar (async/schedule_microtask.dart:41)');
+ 'foo (package:foo/foo.dart:3:13)\nbar (dart:async/schedule_microtask.dart:41)');
});
});
}