[unified_analytics] Send `enabled_features` as an event parameter rather than a user property (#2007)

Fixes https://github.com/flutter/flutter/issues/147327.

**Summary.** The `Analytics` constructor accepts a list of "enabled features" for the current user of the whatever tool is in use ([src](https://github.com/dart-lang/tools/blob/3934675f1595ed2fee2297d7d1cc96beaaa50c9e/pkgs/unified_analytics/lib/src/analytics.dart#L39-L42)). For example, in the Flutter tool, this will be a comma-delimited list of `flutter config` items set to `true` (explicitly by the user). When any event is sent off to Google Analytics, this list will be included as a _user property_ with the key "enabled_features".

See the parent issue. This list is prone to getting truncated due to the low character limit of user property values. This PR instead sends them as event properties. This has a _much_ higher character limit of 500, which is hopefully sufficient (even if it is not, it would be a huge improvement over the current limit of 36, which makes collecting enabled features near-useless).

However, this creates a pitfall. If any new `Event` decides to include an `enabled_features` event property (and also passes a non-null argument for the `enabledFeatures` parameter in the `Analytics` constructor). There are a few ways handle this:

1. Do nothing. The likelihood of this happening is extremely low (but it will be quite confusing if it does happen).
2. Create an `Event._` constructor that throws an exception if the `eventData` map includes an entry with a key of `enabled_features`. Re-route all of the existing constructors to utilize this one. This working depends on newly added events following the pattern of using `Event._` instead of doing initialization themselves; but I suspect folks adding new events will naturally use the existing ones for inspiration, so this is fine to me.
3. Similar to 2, add this validation logic but instead do so in `generateRequestBody`. This keeps the validation logic much closer to the logic that inserts `enabled_features`, so it will make sense to first-time maintainers slightly more quickly. This also would require the least work to implement. The downside is that no exception would appear until `send` is called, and that exception would be thrown asynchronously.

I suspect 2 is probably the way to go, so I went ahead and implemented that. Let me know if you have a differing opinion. I made this is a separate commit, so it would be easy to revert.

---

<details>
  <summary>Contribution guidelines:</summary><br>

- See our [contributor guide](https://github.com/dart-lang/.github/blob/main/CONTRIBUTING.md) for general expectations for PRs.
- Larger or significant changes should be discussed in an issue before creating a PR.
- Contributions to our repos should follow the [Dart style guide](https://dart.dev/guides/language/effective-dart) and use `dart format`.
- Most changes should add an entry to the changelog and may need to [rev the pubspec package version](https://github.com/dart-lang/sdk/blob/main/docs/External-Package-Maintenance.md#making-a-change).
- Changes to packages require [corresponding tests](https://github.com/dart-lang/.github/blob/main/CONTRIBUTING.md#Testing).

Note that many Dart repos have a weekly cadence for reviewing PRs - please allow for some latency before initial review feedback.
</details>
8 files changed
tree: 7afadb0c3c0450f83c1a0cdce64c6ac5cbab3b2a
  1. .github/
  2. pkgs/
  3. tool/
  4. .gitignore
  5. CODEOWNERS
  6. CONTRIBUTING.md
  7. LICENSE
  8. README.md
README.md

Overview

This repository is home to tooling related Dart packages. Generally, this means packages published through the tools.dart.dev publisher that don't naturally belong to other topic monorepos (like dart-lang/build, dart-lang/test, or dart-lang/shelf).

Packages

PackageDescriptionIssuesVersion
bazel_workerProtocol and utilities to implement or invoke persistent bazel workers.issuespub package
benchmark_harnessThe official Dart project benchmark harness.issuespub package
boolean_selectorA flexible syntax for boolean expressions, based on a simplified version of Dart's expression syntax.issuespub package
browser_launcherProvides a standardized way to launch web browsers for testing and tools.issuespub package
cli_configA library to take config values from configuration files, CLI arguments, and environment variables.issuespub package
cli_utilA library to help in building Dart command-line apps.issuespub package
clockA fakeable wrapper for dart:core clock APIs.issuespub package
code_builderA fluent, builder-based library for generating valid Dart code.issuespub package
coverageCoverage data manipulation and formattingissuespub package
csslibA library for parsing and analyzing CSS (Cascading Style Sheets).issuespub package
extension_discoveryA convention and utilities for package extension discovery.issuespub package
fileA pluggable, mockable file system abstraction for Dart.issuespub package
file_testingTesting utilities for package:file.issuespub package
globA library to perform Bash-style file and directory globbing.issuespub package
graphsGraph algorithms that operate on graphs in any representation.issuespub package
htmlAPIs for parsing and manipulating HTML content outside the browser.issuespub package
ioUtilities for the Dart VM Runtime including support for ANSI colors, file copying, and standard exit code values.issuespub package
json_rpc_2Utilities to write a client or server using the JSON-RPC 2.0 spec.issuespub package
markdownA portable Markdown library written in Dart that can parse Markdown into HTML.issuespub package
mimeUtilities for handling media (MIME) types, including determining a type from a file extension and file contents.issuespub package
oauth2A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials.issuespub package
package_configSupport for reading and writing Dart Package Configuration files.issuespub package
poolManage a finite pool of resources. Useful for controlling concurrent file system or network requests.issuespub package
pub_semverVersions and version constraints implementing pub's versioning policy. This is very similar to vanilla semver, with a few corner cases.issuespub package
pubspec_parseSimple package for parsing pubspec.yaml files with a type-safe API and rich error reporting.issuespub package
source_map_stack_traceA package for applying source maps to stack traces.issuespub package
source_mapsA library to programmatically manipulate source map files.issuespub package
source_spanProvides a standard representation for source code locations and spans.issuespub package
sseProvides client and server functionality for setting up bi-directional communication through Server Sent Events (SSE) and corresponding POST requests.issuespub package
stack_traceA package for manipulating stack traces and printing them readably.issuespub package
stream_channelAn abstraction for two-way communication channels based on the Dart Stream class.issuespub package
stream_transformA collection of utilities to transform and manipulate streams.issuespub package
string_scannerA class for parsing strings using a sequence of patterns.issuespub package
term_glyphUseful Unicode glyphs and ASCII substitutes.issuespub package
test_reflective_loaderSupport for discovering tests and test suites using reflection.issuespub package
timingA simple package for tracking the performance of synchronous and asynchronous actions.issuespub package
unified_analyticsA package for logging analytics for all Dart and Flutter related tooling to Google Analytics.issuespub package
watcherA file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified.issuespub package
yamlA parser for YAML, a human-friendly data serialization standardissuespub package
yaml_editA library for YAML manipulation with comment and whitespace preservation.issuespub package

Publishing automation

For information about our publishing automation and release process, see https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

For additional information about contributing, see our contributing page.