This package is intended to be used on Dart and Flutter related tooling only.
It provides APIs to send events to Google Analytics using the Measurement Protocol.

## Usage

To get started using this package, import at the entrypoint dart file and
initialize with the required parameters.

The example file shows an end-to-end usage guide for using this package and
can be referred to here [unified_analytics_example.dart](example/unified_analytics_example.dart).

**IMPORTANT**: It is best practice to close the http client connection when finished
sending events, otherwise, you may notice that the dart process hangs on exit. The example below
shows how to handle closing the connection via `analytics.close()` method.

[Link to documentation for http client's close method](https://pub.dev/documentation/http/latest/http/Client-class.html)


## Opting In and Out of Analytics Collection

It will be important for each tool to expose a trivial method to
disabling or enabling analytics collection. Based on how the user interacts
with the tool, this can be done through the CLI, IDE, etc. The tool will
then pass a boolean to an API exposed by the package as shown below.

```dart
// Begin by initializing the class
final Analytics analytics = Analytics(...);

// The boolean below simulates the user deciding to opt-out
// of Analytics collection
final bool status = false;

// Call the method to pass the boolean
analytics.setTelemetry(status);
```

## Displaying Consent Message to Users

When a user first uses any tool with this package enabled, the tool using
this package will need to ensure that the user has seen the consent message.
The tool using this package should check with the `Analytics` instance
by invoking the `shouldShowMessage` getter. When this getter returns
`true`, this means that the user has not been enrolled into analytics
collection yet. It is at this point that the tool using this package will
invoke the `getConsentMessage` getter to return a string to share with the
user (each tool will have their own method of displaying the message
through cli stdout, popup modal, etc.). Once the message has been shown,
the tool using this package will need to confirm to the `Analytics` instance
that it has shown the message; it is at this point that the user has
officially been onboarded to analytics collection.



```dart
// Begin by initializing the class near the entrypoint
final Analytics analytics = Analytics(...);

// This conditional should always run; the first time it is run, this
// will return true since the consent message has never been shown
if (analytics.shouldShowMessage) {
  
  // Simulates displaying the message, this will vary from
  // client to client; ie. stdout, popup in IDE, etc.
  print(analytics.getConsentMessage);

  // After receiving confirmation that the message has been
  // displayed, invoking the below method will successfully
  // onboard the tool into the config file and allow for
  // events to be sent on the next creation of the analytics
  // instance
  analytics.clientShowedMessage();
}
```

## Checking User Opt-In Status

Some tools may need to know if the user has opted in for Analytics
collection in order to enable additional functionality. The example below
shows how to check the status.

```dart
// Begin by initializing the class
final Analytics analytics = Analytics(...);

// This getter will return a boolean showing the status;
// print statement used for trivial usage example
print('This user's status: ${analytics.telemetryEnabled}');  // true if opted-in
```

## Checking for New Versions of Consent Message

In the event that the package consent messaging needs has been updated, an
API has been exposed on an instance of `Analytics` that will notify the tool
using this package whether to display the message again.

```dart
// Begin by initializing the class
//
// This is assuming that the tool has already been onboarded
// and that the user has already seen the previous version of
// the consent message
final Analytics analytics = Analytics(...);


// Much like the first example, if there is a new version of
// the tools message that needs to be shown, use the same work
// workflow
if (analytics.shouldShowMessage) {
  
  // Simulates displaying the message, this will vary from
  // client to client; ie. stdout, popup in IDE, etc.
  print(analytics.getConsentMessage);

  // After receiving confirmation that the message has been
  // displayed, invoking the below method will successfully
  // onboard the tool into the config file and allow for
  // events to be sent on the next creation of the analytics
  // instance
  analytics.clientShowedMessage();
}
```

It is important to note events will not be sent if there is a new version of
the consent message.

## Developing Within `package:unified_analytics`

### Adding new data classes

#### User properties
In Google Analytics, new data fields can be collected as user properties 
or events. 

User properties are key-value pairs that can be used to segment users. For example, 
the Flutter channel used. To request that a new user property 
be added, file an issue [using this template](https://github.com/dart-lang/tools/issues/new?template=unified_analytics_user_property.yml). 

To add a new user property, add a new property to the `UserProperty` class 
in the [`user_property.dart` file](./lib/src/user_property.dart). 

#### Events
Events are actions that the user, or tool, performs. In Google Analytics, 
events can have associated data. This event data is stored 
in key-value pairs. 

To request new events, or event data, file an issue 
[using this template](https://github.com/dart-lang/tools/issues/new?template=unified_analytics_event.yml).

To add a new event, create a new field in the `DashEvent` enum (if necessary) in
the [`enums.dart` file](./lib/src/enums.dart). 

Then, add event data, create a new constructor for the `Event` class 
in the [`event.dart` file](./lib/src/event.dart).


### Testing event collection

When contributing to this package, if the developer needs to verify that
events have been sent, the developer should the use development constructor
so that the events being sent are not going into the production instance.

```dart
final Analytics analytics = Analytics.development(...);
```

Reach out to maintainers to get access to the test Google Analytics endpoint.

## Advanced Usage: Querying Locally Persisted Logs

This package enables  tools to persist the events that have been sent
to Google Analytics for logging by default. This can be very helpful if
tools would like to understand the user's activity level across all
related tooling. For example, if querying the locally persisted logs
shows that the user has not been active for N number of days, a tool that
works within an IDE can prompt the user with a survey to understand why their
level of activity has dropped.

The snippet below shows how to invoke the query and a sample response.

```dart
// Begin by initializing the class
final Analytics analytics = Analytics(...);

// Printing the query results returns json formatted
// string to view; data can also be accessed through
// [LogFileStats] getters
print(analytics.logFileStats());
```
Refer to the `LogFileStats` instance [variables](lib/src/log_handler.dart) for details on the result.

Explanation of the each key above

- startDateTime: the earliest event that was sent
- minsFromStartDateTime: the number of minutes elapsed since the earliest message
- endDateTime: the latest, most recent event that was sent
- minsFromEndDateTime: the number of minutes elapsed since the latest message
- sessionCount: count of sessions; sessions have a minimum time of 30 minutes
- flutterChannelCount: count of flutter channels (can be 0 if developer is a Dart dev only)
- toolCount: count of the Dart and Flutter tools sending analytics
- recordCount: count of the total number of events in the log file
- eventCount: counts each unique event and how many times they occurred in the log file

Note: You can test any changes to the `LogFileStats` during development by running:

```shell
dart run example/log_stats.dart
```