Cherry-pick: [Inspector V2] Fix inspector analytics  (#8684)
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart
index 33d7161..e7d2721 100644
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart
+++ b/packages/devtools_app/lib/src/screens/inspector/inspector_controller.dart
@@ -23,6 +23,9 @@
 import 'package:vm_service/vm_service.dart';
 
 import '../../service/service_extensions.dart' as extensions;
+import '../../shared/analytics/analytics.dart' as ga;
+import '../../shared/analytics/constants.dart' as gac;
+import '../../shared/analytics/metrics.dart';
 import '../../shared/console/eval/inspector_tree.dart';
 import '../../shared/console/primitives/simple_items.dart';
 import '../../shared/diagnostics/diagnostics_node.dart';
@@ -665,6 +668,13 @@
       subtreeRoot = newSelection;
 
       applyNewSelection(newSelection, detailsSelection, true);
+
+      // Send an event that a widget was selected on the device.
+      ga.select(
+        gac.inspector,
+        gac.onDeviceSelection,
+        screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
+      );
     } catch (error, st) {
       if (selectionGroups.next == group) {
         _log.shout(error, error, st);
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart
index 8497e43..8192136 100644
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart
+++ b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart
@@ -13,6 +13,7 @@
 import '../../service/service_extensions.dart' as extensions;
 import '../../shared/analytics/analytics.dart' as ga;
 import '../../shared/analytics/constants.dart' as gac;
+import '../../shared/analytics/metrics.dart';
 import '../../shared/common_widgets.dart';
 import '../../shared/console/eval/inspector_tree.dart';
 import '../../shared/error_badge_manager.dart';
@@ -265,7 +266,11 @@
   }
 
   void _refreshInspector() {
-    ga.select(gac.inspector, gac.refresh);
+    ga.select(
+      gac.inspector,
+      gac.refresh,
+      screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
+    );
     unawaited(
       blockWhileInProgress(() async {
         // If the user is force refreshing the inspector before the first load has
@@ -274,13 +279,11 @@
         if (!controller.firstInspectorTreeLoadCompleted) {
           // We do not want to complete this timing operation because the force
           // refresh will skew the results.
-          ga.cancelTimingOperation(
-            InspectorScreen.id,
-            gac.pageReady,
-          );
+          ga.cancelTimingOperation(InspectorScreen.id, gac.pageReady);
           ga.select(
             gac.inspector,
             gac.refreshEmptyTree,
+            screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
           );
           controller.firstInspectorTreeLoadCompleted = true;
         }
diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart
index 3da2d24..9154696 100644
--- a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart
+++ b/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart
@@ -445,6 +445,7 @@
     ga.select(
       gac.inspector,
       gac.treeNodeSelection,
+      screenMetricsProvider: () => InspectorScreenMetrics.legacy(),
     );
     expandPath(node);
   }
@@ -1004,7 +1005,14 @@
     if (!controller.firstInspectorTreeLoadCompleted && widget.isSummaryTree) {
       final screenId = widget.screenId;
       if (screenId != null) {
-        ga.timeEnd(screenId, gac.pageReady);
+        ga.timeEnd(
+          screenId,
+          gac.pageReady,
+          screenMetricsProvider:
+              () => InspectorScreenMetrics.legacy(
+                rowCount: treeControllerLocal.numRows,
+              ),
+        );
         unawaited(
           serviceConnection.sendDwdsEvent(
             screen: screenId,
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart
index bebba01..8657e85 100644
--- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_controller.dart
@@ -25,6 +25,7 @@
 import '../../service/service_extensions.dart' as extensions;
 import '../../shared/analytics/analytics.dart' as ga;
 import '../../shared/analytics/constants.dart' as gac;
+import '../../shared/analytics/metrics.dart';
 import '../../shared/console/eval/inspector_tree_v2.dart';
 import '../../shared/console/primitives/simple_items.dart';
 import '../../shared/diagnostics/diagnostics_node.dart';
@@ -379,7 +380,11 @@
       // We do not want to complete this timing operation because the force
       // refresh will skew the results.
       ga.cancelTimingOperation(InspectorScreen.id, gac.pageReady);
-      ga.select(gac.inspector, gac.refreshEmptyTree);
+      ga.select(
+        gac.inspector,
+        gac.refreshEmptyTree,
+        screenMetricsProvider: () => InspectorScreenMetrics.v2(),
+      );
       firstInspectorTreeLoadCompleted = true;
     }
     await onForceRefresh();
@@ -645,6 +650,13 @@
       subtreeRoot = newSelection;
 
       applyNewSelection(newSelection);
+
+      // Send an event that a widget was selected on the device.
+      ga.select(
+        gac.inspector,
+        gac.onDeviceSelection,
+        screenMetricsProvider: () => InspectorScreenMetrics.v2(),
+      );
     } catch (error, st) {
       if (selectionGroups.next == group) {
         _log.shout(error, error, st);
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart
index afcb40a..63f532e 100644
--- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_screen_body.dart
@@ -11,6 +11,7 @@
 
 import '../../shared/analytics/analytics.dart' as ga;
 import '../../shared/analytics/constants.dart' as gac;
+import '../../shared/analytics/metrics.dart';
 import '../../shared/common_widgets.dart';
 import '../../shared/console/eval/inspector_tree_v2.dart';
 import '../../shared/error_badge_manager.dart';
@@ -210,7 +211,11 @@
   }
 
   void _refreshInspector() {
-    ga.select(gac.inspector, gac.refresh);
+    ga.select(
+      gac.inspector,
+      gac.refresh,
+      screenMetricsProvider: () => InspectorScreenMetrics.v2(),
+    );
     unawaited(
       blockWhileInProgress(() async {
         await controller.refreshInspector();
diff --git a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart
index 8768df2..0528ed3 100644
--- a/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_v2/inspector_tree_controller.dart
@@ -549,6 +549,7 @@
     ga.select(
       gac.inspector,
       gac.treeNodeSelection,
+      screenMetricsProvider: () => InspectorScreenMetrics.v2(),
     );
     final diagnostic = node?.diagnostic;
     if (diagnostic != null && diagnostic.groupIsHidden) {
@@ -1140,7 +1141,12 @@
         if (!controller.firstInspectorTreeLoadCompleted) {
           final screenId = widget.screenId;
           if (screenId != null) {
-            ga.timeEnd(screenId, gac.pageReady);
+            ga.timeEnd(
+              screenId,
+              gac.pageReady,
+              screenMetricsProvider:
+                  () => InspectorScreenMetrics.v2(rowCount: rows.length),
+            );
             unawaited(
               serviceConnection.sendDwdsEvent(
                 screen: screenId,
diff --git a/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart b/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart
index 1cd77d5..775b077 100644
--- a/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart
+++ b/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart
@@ -67,7 +67,8 @@
 
     // NOTE: Do not reorder any of these. Order here must match the order in the
     // Google Analytics console.
-
+    // IMPORTANT! Only string and int values are supported. All other value
+    // types will be ignored in GA4.
     String? user_app, // dimension1 (flutter or web)
     String? user_build, // dimension2 (debug or profile)
     String? user_platform, // dimension3 (android/ios/fuchsia/linux/mac/windows)
@@ -115,7 +116,7 @@
     String? android_app_id, //metric13
     String? ios_bundle_id, //metric14
     // Inspector screen metrics. See [InspectorScreenMetrics].
-    bool? is_v2_inspector, // metric15
+    String? is_v2_inspector, // metric15
   });
 
   factory GtagEventDevTools._create({
@@ -197,7 +198,9 @@
           : null,
       // [InspectorScreenMetrics]
       is_v2_inspector:
-          screenMetrics is InspectorScreenMetrics ? screenMetrics.isV2 : null,
+          screenMetrics is InspectorScreenMetrics
+              ? screenMetrics.isV2.toString()
+              : null,
     );
   }
 
@@ -233,7 +236,7 @@
   external int? get inspector_tree_controller_id;
   external String? get android_app_id;
   external String? get ios_bundle_id;
-  external bool? get is_v2_inspector;
+  external String? get is_v2_inspector;
 }
 
 extension type GtagExceptionDevTools._(JSObject _) implements GtagException {
@@ -244,7 +247,8 @@
 
     // NOTE: Do not reorder any of these. Order here must match the order in the
     // Google Analytics console.
-
+    // IMPORTANT! Only string and int values are supported. All other value
+    // types will be ignored in GA4.
     String? user_app, // dimension1 (flutter or web)
     String? user_build, // dimension2 (debug or profile)
     String? user_platform, // dimension3 (android or ios)
@@ -291,7 +295,7 @@
     String? android_app_id, //metric13
     String? ios_bundle_id, //metric14
     // Inspector screen metrics. See [InspectorScreenMetrics].
-    bool? is_v2_inspector, // metric15
+    String? is_v2_inspector, // metric15
   });
 
   factory GtagExceptionDevTools._create(
@@ -365,7 +369,9 @@
           : null,
       // [InspectorScreenMetrics]
       is_v2_inspector:
-          screenMetrics is InspectorScreenMetrics ? screenMetrics.isV2 : null,
+          screenMetrics is InspectorScreenMetrics
+              ? screenMetrics.isV2.toString()
+              : null,
     );
   }
 
@@ -1033,7 +1039,7 @@
   final int? rootSetCount;
   final int? rowCount;
   final int? inspectorTreeControllerId;
-  final bool? isV2Inspector;
+  final String? isV2Inspector;
 
   // [DeepLinkScreenMetrics]
   final String? androidAppId;
diff --git a/packages/devtools_app/lib/src/shared/analytics/constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants.dart
index ee2fa75..355c162 100644
--- a/packages/devtools_app/lib/src/shared/analytics/constants.dart
+++ b/packages/devtools_app/lib/src/shared/analytics/constants.dart
@@ -83,6 +83,7 @@
 const enableOnDeviceInspector = 'enableOnDeviceInspector';
 const showOnDeviceInspector = 'showInspector';
 const treeNodeSelection = 'treeNodeSelection';
+const onDeviceSelection = 'onDeviceSelection';
 const inspectorSettings = 'inspectorSettings';
 const loggingSettings = 'loggingSettings';
 const refreshPubRoots = 'refreshPubRoots';
@@ -122,6 +123,8 @@
 const verboseLogging = 'verboseLogging';
 const inspectorHoverEvalMode = 'inspectorHoverEvalMode';
 const inspectorV2Enabled = 'inspectorV2Enabled';
+const inspectorAutoRefreshEnabled = 'inspectorAutoRefreshEnabled';
+const inspectorV2Docs = 'inspectorV2Docs';
 const clearLogs = 'clearLogs';
 const copyLogs = 'copyLogs';
 
diff --git a/packages/devtools_app/lib/src/shared/analytics/metrics.dart b/packages/devtools_app/lib/src/shared/analytics/metrics.dart
index 2b0e6b1..8d3b716 100644
--- a/packages/devtools_app/lib/src/shared/analytics/metrics.dart
+++ b/packages/devtools_app/lib/src/shared/analytics/metrics.dart
@@ -64,15 +64,15 @@
 
 class InspectorScreenMetrics extends ScreenAnalyticsMetrics {
   InspectorScreenMetrics.legacy({
-    required this.rootSetCount,
-    required this.rowCount,
-    required this.inspectorTreeControllerId,
+    this.rootSetCount,
+    this.rowCount,
+    this.inspectorTreeControllerId,
   }) : isV2 = false;
 
   InspectorScreenMetrics.v2({
-    required this.rootSetCount,
-    required this.rowCount,
-    required this.inspectorTreeControllerId,
+    this.rootSetCount,
+    this.rowCount,
+    this.inspectorTreeControllerId,
   }) : isV2 = true;
 
   static const summaryTreeGaId = 0;