diff --git a/pkgs/unified_analytics/CHANGELOG.md b/pkgs/unified_analytics/CHANGELOG.md index bee8205e5..018127d7a 100644 --- a/pkgs/unified_analytics/CHANGELOG.md +++ b/pkgs/unified_analytics/CHANGELOG.md @@ -1,3 +1,12 @@ +## 7.0.0 +- Added a required parameter `screen` to the `Event.devtoolsEvent` constructor. +- Added an optional parameter `additionalMetrics` to the `Event.devtoolsEvent` constructor. +- Added `CustomMetrics` class for unified_analytics clients to define custom event metrics. +- Removed parameters `uiDurationMicros`, `rasterDurationMicros`, `shaderCompilationDurationMicros`, +`traceEventCount`, `cpuSampleCount`, `cpuStackDepth`, `heapDiffObjectsBefore`, `heapDiffObjectsAfter`, +`heapObjectsTotal`, `rootSetCount`, `rowCount`, `inspectorTreeControllerId`, `androidAppId`, `iosBundleId` +from the `Event.devtoolsEvent` constructor. + ## 6.1.5 - Remove any `data` entries with a null value in the `Event.exception` constructor. diff --git a/pkgs/unified_analytics/lib/src/constants.dart b/pkgs/unified_analytics/lib/src/constants.dart index 8982ee576..ec4822b62 100644 --- a/pkgs/unified_analytics/lib/src/constants.dart +++ b/pkgs/unified_analytics/lib/src/constants.dart @@ -87,7 +87,7 @@ const int kMaxLogFileSize = 25 * (1 << 20); const String kLogFileName = 'dart-flutter-telemetry.log'; /// The current version of the package, should be in line with pubspec version. -const String kPackageVersion = '6.1.5'; +const String kPackageVersion = '7.0.0'; /// The minimum length for a session. const int kSessionDurationMinutes = 30; diff --git a/pkgs/unified_analytics/lib/src/event.dart b/pkgs/unified_analytics/lib/src/event.dart index 0b5450d6e..cf6f84f99 100644 --- a/pkgs/unified_analytics/lib/src/event.dart +++ b/pkgs/unified_analytics/lib/src/event.dart @@ -356,9 +356,17 @@ final class Event { if (exitCode != null) 'exitCode': exitCode, }; - /// Event that is sent from devtools for various different actions as + /// Event that is sent from DevTools for various different actions as /// indicated by the [eventCategory]. + /// + /// The optional parameters in the parameter list contain metadata that is + /// sent with each event, when available. + /// + /// [additionalMetrics] may contain any additional data for the event being + /// sent. This often looks like metrics that are unique to the event or to a + /// specific screen. Event.devtoolsEvent({ + required String screen, required String eventCategory, required String label, required int value, @@ -379,32 +387,10 @@ final class Event { String? isEmbedded, String? ideLaunchedFeature, String? isWasm, - - // PerformanceScreenMetrics - int? uiDurationMicros, - int? rasterDurationMicros, - int? shaderCompilationDurationMicros, - int? traceEventCount, - - // ProfilerScreenMetrics - int? cpuSampleCount, - int? cpuStackDepth, - - // MemoryScreenMetrics - int? heapDiffObjectsBefore, - int? heapDiffObjectsAfter, - int? heapObjectsTotal, - - // InspectorScreenMetrics - int? rootSetCount, - int? rowCount, - int? inspectorTreeControllerId, - - // DeepLinkScreenMetrics - String? androidAppId, - String? iosBundleId, + CustomMetrics? additionalMetrics, }) : eventName = DashEvent.devtoolsEvent, eventData = { + 'screen': screen, 'eventCategory': eventCategory, 'label': label, 'value': value, @@ -425,34 +411,7 @@ final class Event { if (ideLaunchedFeature != null) 'ideLaunchedFeature': ideLaunchedFeature, if (isWasm != null) 'isWasm': isWasm, - - // PerformanceScreenMetrics - if (uiDurationMicros != null) 'uiDurationMicros': uiDurationMicros, - if (rasterDurationMicros != null) - 'rasterDurationMicros': rasterDurationMicros, - if (shaderCompilationDurationMicros != null) - 'shaderCompilationDurationMicros': shaderCompilationDurationMicros, - if (traceEventCount != null) 'traceEventCount': traceEventCount, - - // ProfilerScreenMetrics - if (cpuSampleCount != null) 'cpuSampleCount': cpuSampleCount, - if (cpuStackDepth != null) 'cpuStackDepth': cpuStackDepth, - - // MemoryScreenMetrics - if (heapDiffObjectsBefore != null) - 'heapDiffObjectsBefore': heapDiffObjectsBefore, - if (heapDiffObjectsAfter != null) - 'heapDiffObjectsAfter': heapDiffObjectsAfter, - if (heapObjectsTotal != null) 'heapObjectsTotal': heapObjectsTotal, - - // InspectorScreenMetrics - if (rootSetCount != null) 'rootSetCount': rootSetCount, - if (rowCount != null) 'rowCount': rowCount, - if (inspectorTreeControllerId != null) - 'inspectorTreeControllerId': inspectorTreeControllerId, - // DeepLinkScreenMetrics - if (androidAppId != null) 'androidAppId': androidAppId, - if (iosBundleId != null) 'iosBundleId': iosBundleId, + if (additionalMetrics != null) ...additionalMetrics.toMap(), }; /// Event that contains the results for a specific doctor validator. @@ -887,3 +846,15 @@ final class Event { } } } + +/// A base class for custom metrics that will be defined by a unified_analytics +/// client. +/// +/// This base type can be used as a parameter in any event constructor that +/// allows custom metrics to be added by a unified_analytics client. +abstract base class CustomMetrics { + /// Converts the custom metrics data to a [Map] object. + /// + /// This must be a JSON encodable [Map]. + Map toMap(); +} diff --git a/pkgs/unified_analytics/lib/unified_analytics.dart b/pkgs/unified_analytics/lib/unified_analytics.dart index 7cc4562b9..bd8e17ae9 100644 --- a/pkgs/unified_analytics/lib/unified_analytics.dart +++ b/pkgs/unified_analytics/lib/unified_analytics.dart @@ -5,7 +5,7 @@ export 'src/analytics.dart' show Analytics, FakeAnalytics, NoOpAnalytics; export 'src/config_handler.dart' show ToolInfo; export 'src/enums.dart' show DashTool; -export 'src/event.dart' show Event; +export 'src/event.dart' show CustomMetrics, Event; export 'src/log_handler.dart' show LogFileStats; export 'src/survey_handler.dart' show Survey, SurveyButton, SurveyHandler; export 'src/utils.dart' show parseDartSDKVersion; diff --git a/pkgs/unified_analytics/pubspec.yaml b/pkgs/unified_analytics/pubspec.yaml index 5ee0e4260..4a52c6873 100644 --- a/pkgs/unified_analytics/pubspec.yaml +++ b/pkgs/unified_analytics/pubspec.yaml @@ -5,7 +5,7 @@ description: >- # LINT.IfChange # When updating this, keep the version consistent with the changelog and the # value in lib/src/constants.dart. -version: 6.1.5 +version: 7.0.0 # LINT.ThenChange(lib/src/constants.dart) repository: https://github.com/dart-lang/tools/tree/main/pkgs/unified_analytics issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics diff --git a/pkgs/unified_analytics/test/event_test.dart b/pkgs/unified_analytics/test/event_test.dart index 2809af965..70b0959bd 100644 --- a/pkgs/unified_analytics/test/event_test.dart +++ b/pkgs/unified_analytics/test/event_test.dart @@ -6,6 +6,7 @@ import 'dart:mirrors'; import 'package:test/test.dart'; import 'package:unified_analytics/src/enums.dart'; +import 'package:unified_analytics/src/event.dart'; import 'package:unified_analytics/unified_analytics.dart'; void main() { @@ -559,6 +560,7 @@ void main() { test('Event.devtoolsEvent constructed', () { Event generateEvent() => Event.devtoolsEvent( + screen: 'screen', eventCategory: 'eventCategory', label: 'label', value: 1, @@ -575,25 +577,17 @@ void main() { isEmbedded: 'isEmbedded', ideLaunchedFeature: 'ideLaunchedFeature', isWasm: 'true', - uiDurationMicros: 123, - rasterDurationMicros: 123, - shaderCompilationDurationMicros: 123, - traceEventCount: 123, - cpuSampleCount: 123, - cpuStackDepth: 123, - heapDiffObjectsBefore: 123, - heapDiffObjectsAfter: 123, - heapObjectsTotal: 123, - rootSetCount: 123, - rowCount: 123, - inspectorTreeControllerId: 123, - androidAppId: 'androidAppId', - iosBundleId: 'iosBundleId', + additionalMetrics: _TestMetrics( + stringField: 'test', + intField: 100, + boolField: false, + ), ); final constructedEvent = generateEvent(); expect(generateEvent, returnsNormally); + expect(constructedEvent.eventData['screen'], 'screen'); expect(constructedEvent.eventData['eventCategory'], 'eventCategory'); expect(constructedEvent.eventData['label'], 'label'); expect(constructedEvent.eventData['value'], 1); @@ -609,24 +603,15 @@ void main() { expect(constructedEvent.eventData['isExternalBuild'], 'isExternalBuild'); expect(constructedEvent.eventData['isEmbedded'], 'isEmbedded'); expect( - constructedEvent.eventData['ideLaunchedFeature'], 'ideLaunchedFeature'); + constructedEvent.eventData['ideLaunchedFeature'], + 'ideLaunchedFeature', + ); expect(constructedEvent.eventData['isWasm'], 'true'); - - expect(constructedEvent.eventData['uiDurationMicros'], 123); - expect(constructedEvent.eventData['rasterDurationMicros'], 123); - expect(constructedEvent.eventData['shaderCompilationDurationMicros'], 123); - expect(constructedEvent.eventData['traceEventCount'], 123); - expect(constructedEvent.eventData['cpuSampleCount'], 123); - expect(constructedEvent.eventData['cpuStackDepth'], 123); - expect(constructedEvent.eventData['heapDiffObjectsBefore'], 123); - expect(constructedEvent.eventData['heapDiffObjectsAfter'], 123); - expect(constructedEvent.eventData['heapObjectsTotal'], 123); - expect(constructedEvent.eventData['rootSetCount'], 123); - expect(constructedEvent.eventData['rowCount'], 123); - expect(constructedEvent.eventData['inspectorTreeControllerId'], 123); - expect(constructedEvent.eventData['androidAppId'], 'androidAppId'); - expect(constructedEvent.eventData['iosBundleId'], 'iosBundleId'); - expect(constructedEvent.eventData.length, 30); + expect(constructedEvent.eventData['stringField'], 'test'); + expect(constructedEvent.eventData['intField'], 100); + expect(constructedEvent.eventData['boolField'], false); + expect(constructedEvent.eventData.containsKey('nullableField'), false); + expect(constructedEvent.eventData.length, 20); }); test('Confirm all constructors were checked', () { @@ -700,3 +685,22 @@ void main() { expect(eventConstructed, isNull); }); } + +final class _TestMetrics extends CustomMetrics { + _TestMetrics({ + required this.stringField, + required this.intField, + required this.boolField, + }); + + final String stringField; + final int intField; + final bool boolField; + + @override + Map toMap() => { + 'stringField': stringField, + 'intField': intField, + 'boolField': boolField, + }; +}