-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add flutterfire_tracker * chore: fix Trackable class interface declaration. * chore: refactor error tracking to use multiple trackers * feat: add user ID tracking and clearing methods to Trackable interface and Tracker class * test: update test
- Loading branch information
Showing
11 changed files
with
638 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ lerp | |
ltrb | ||
LTWH | ||
mockito | ||
mocktail | ||
nullsafety | ||
Podfile | ||
postbootstrap | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Miscellaneous | ||
*.class | ||
*.log | ||
*.pyc | ||
*.swp | ||
.DS_Store | ||
.atom/ | ||
.buildlog/ | ||
.history | ||
.svn/ | ||
migrate_working_dir/ | ||
|
||
# IntelliJ related | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.idea/ | ||
|
||
# The .vscode folder contains launch configuration and tasks you configure in | ||
# VS Code which you may wish to be included in version control, so this line | ||
# is commented out by default. | ||
#.vscode/ | ||
|
||
# Flutter/Dart/Pub related | ||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. | ||
/pubspec.lock | ||
**/doc/api/ | ||
.dart_tool/ | ||
.packages | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: "d211f42860350d914a5ad8102f9ec32764dc6d06" | ||
channel: "stable" | ||
|
||
project_type: package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## 0.1.0 | ||
|
||
* initial release. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<!-- | ||
This README describes the package. If you publish this package to pub.dev, | ||
this README's contents appear on the landing page for your package. | ||
For information about how to write a good package README, see the guide for | ||
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages). | ||
For general information about developing packages, see the Dart guide for | ||
[creating packages](https://dart.dev/guides/libraries/create-library-packages) | ||
and the Flutter guide for | ||
[developing packages and plugins](https://flutter.dev/developing-packages). | ||
--> | ||
|
||
TODO: Put a short description of the package here that helps potential users | ||
know whether this package might be useful for them. | ||
|
||
## Features | ||
|
||
TODO: List what your package can do. Maybe include images, gifs, or videos. | ||
|
||
## Getting started | ||
|
||
TODO: List prerequisites and provide or point to information on how to | ||
start using the package. | ||
|
||
## Usage | ||
|
||
TODO: Include short and useful examples for package users. Add longer examples | ||
to `/example` folder. | ||
|
||
```dart | ||
const like = 'sample'; | ||
``` | ||
|
||
## Additional information | ||
|
||
TODO: Tell users more about the package: where to find more information, how to | ||
contribute to the package, how to file issues, what response they can expect | ||
from the package authors, and more. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include: package:altive_lints/altive_lints.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/// Abstract class that defines the interface for tracking events and errors. | ||
/// | ||
/// Implementations of this class can send tracking information to various | ||
/// analytics and monitoring services. This class should be implemented | ||
/// by any service that wants to handle the application's tracking data, | ||
/// such as events and errors. | ||
abstract interface class Trackable { | ||
/// Tracks an error. | ||
/// | ||
/// Use this method to record errors that occur in the application. | ||
/// You can mark an error as fatal by setting [fatal] to true. | ||
/// | ||
/// Parameters: | ||
/// [error] - The error object that was caught. | ||
/// [stackTrace] - The stack trace associated with the error. | ||
/// [fatal] - A flag to indicate if the error is fatal. Defaults to false. | ||
Future<void> trackError( | ||
dynamic error, | ||
StackTrace? stackTrace, { | ||
bool fatal = false, | ||
}); | ||
|
||
/// Tracks an event. | ||
/// | ||
/// This method allows for logging of custom events within the application. | ||
/// Events can be anything from user actions to system events. | ||
/// | ||
/// Parameters: | ||
/// [name] - The name of the event to track. | ||
/// [parameters] - Additional parameters or context to log with the event. | ||
/// This is optional and can be null. | ||
Future<void> trackEvent( | ||
String name, { | ||
Map<String, Object?>? parameters, | ||
}); | ||
|
||
/// Sets the user ID. | ||
/// | ||
/// This method allows for setting the user ID for the current user. | ||
/// This is useful for associating events with a specific user. | ||
/// | ||
/// Parameters: | ||
/// [userId] - The user ID to set. | ||
Future<void> setUserId(String userId); | ||
|
||
/// Clears the user ID. | ||
/// | ||
/// This method allows for clearing the user ID for the current user. | ||
/// This is useful for dissociating events with a specific user. | ||
Future<void> clearUserId(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
import 'dart:async'; | ||
import 'dart:isolate'; | ||
|
||
import 'package:firebase_analytics/firebase_analytics.dart'; | ||
import 'package:firebase_crashlytics/firebase_crashlytics.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
import 'trackable.dart'; | ||
|
||
/// A class that wraps a package for sending events to Analytics. | ||
/// Its role is to "send necessary events to Analytics." | ||
/// | ||
/// It exposes methods for sending analytic events and for configuration. | ||
class Tracker { | ||
Tracker({ | ||
FirebaseCrashlytics? crashlytics, | ||
FirebaseAnalytics? analytics, | ||
List<Trackable> trackers = const [], | ||
}) : _crashlytics = crashlytics ?? FirebaseCrashlytics.instance, | ||
_analytics = analytics ?? FirebaseAnalytics.instance, | ||
_trackers = trackers; | ||
|
||
final FirebaseCrashlytics _crashlytics; | ||
|
||
final FirebaseAnalytics _analytics; | ||
|
||
final List<Trackable> _trackers; | ||
|
||
/// A callback for logging errors caught by the Flutter framework. | ||
/// | ||
/// Usage example: | ||
/// ```dart | ||
/// FlutterError.onError = tracker.onFlutterError; | ||
/// ``` | ||
/// | ||
Future<void> onFlutterError( | ||
FlutterErrorDetails flutterErrorDetails, { | ||
bool fatal = false, | ||
}) async { | ||
FlutterError.presentError(flutterErrorDetails); | ||
await _crashlytics.recordFlutterError(flutterErrorDetails, fatal: fatal); | ||
} | ||
|
||
/// A callback to log asynchronous errors | ||
/// that are not caught by the Flutter framework. | ||
/// | ||
/// | ||
/// Usage example: | ||
/// ```dart | ||
/// PlatformDispatcher.instance.onError = tracker.onPlatformError; | ||
/// ``` | ||
bool onPlatformError(Object error, StackTrace stack) { | ||
unawaited(_crashlytics.recordError(error, stack, fatal: true)); | ||
for (final tracker in _trackers) { | ||
unawaited(tracker.trackError(error, stack, fatal: true)); | ||
} | ||
return true; | ||
} | ||
|
||
/// A listener to register with [Isolate.current] | ||
/// to record errors outside of Flutter. | ||
/// | ||
/// Usage example: | ||
/// ```dart | ||
/// Isolate.current.addErrorListener( | ||
/// tracker.isolateErrorListener() | ||
/// ); | ||
/// ``` | ||
SendPort isolateErrorListener() { | ||
return RawReceivePort((List<dynamic> pair) async { | ||
final errorAndStacktrace = pair; | ||
await Future.wait([ | ||
_crashlytics.recordError( | ||
errorAndStacktrace.first, | ||
errorAndStacktrace.last as StackTrace, | ||
fatal: true, | ||
), | ||
..._trackers.map( | ||
(tracker) => tracker.trackError( | ||
errorAndStacktrace.first, | ||
errorAndStacktrace.last as StackTrace, | ||
fatal: true, | ||
), | ||
), | ||
]); | ||
}).sendPort; | ||
} | ||
|
||
/// Record a Dart or native error that caused the application to crash. | ||
Future<void> recordError( | ||
Object exception, | ||
StackTrace stack, { | ||
bool fatal = false, | ||
}) async { | ||
await Future.wait([ | ||
_crashlytics.recordError( | ||
exception, | ||
stack, | ||
fatal: fatal, | ||
), | ||
..._trackers.map( | ||
(tracker) => tracker.trackError( | ||
exception, | ||
stack, | ||
fatal: fatal, | ||
), | ||
), | ||
]); | ||
} | ||
|
||
/// Set the user ID. | ||
Future<void> setUserId(String userId) async { | ||
await Future.wait([ | ||
_crashlytics.setUserIdentifier(userId), | ||
_analytics.setUserId(id: userId), | ||
..._trackers.map((tracker) => tracker.setUserId(userId)), | ||
]); | ||
} | ||
|
||
/// Clear the set user ID. | ||
Future<void> clearUserId() async { | ||
await Future.wait([ | ||
_crashlytics.setUserIdentifier(''), | ||
_analytics.setUserId(), | ||
..._trackers.map((tracker) => tracker.clearUserId()), | ||
]); | ||
} | ||
|
||
/// Set the user's properties. | ||
Future<void> setUserProperties(Map<String, String?> properties) async { | ||
for (final property in properties.entries) { | ||
await _analytics.setUserProperty( | ||
name: property.key, | ||
value: property.value, | ||
); | ||
} | ||
} | ||
|
||
/// Returns a list of NavigatorObservers to register with Navigator. | ||
/// Use [nameExtractor] to set the parameter value to send. | ||
List<NavigatorObserver> navigatorObservers({ | ||
required String? Function(RouteSettings) nameExtractor, | ||
}) { | ||
return [ | ||
// Returns a NavigatorObserver of FirebaseAnalytics. | ||
FirebaseAnalyticsObserver( | ||
analytics: _analytics, | ||
nameExtractor: nameExtractor, | ||
), | ||
]; | ||
} | ||
|
||
/// Send an event to Analytics. | ||
Future<void> logEvent( | ||
String eventName, { | ||
Map<String, Object?>? parameters, | ||
}) async { | ||
await Future.wait([ | ||
_analytics.logEvent( | ||
name: eventName, | ||
parameters: parameters, | ||
), | ||
..._trackers.map( | ||
(tracker) => tracker.trackEvent( | ||
eventName, | ||
parameters: parameters, | ||
), | ||
), | ||
]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/// flutterfire_tracker with FlutterFire Analytics and Crashlytics. | ||
library flutterfire_tracker; | ||
|
||
export 'src/trackable.dart'; | ||
export 'src/tracker.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: flutterfire_tracker | ||
description: flutterfire_tracker with FlutterFire Analytics and Crashlytics. | ||
publish_to: "none" | ||
version: 0.1.0 | ||
|
||
environment: | ||
sdk: ^3.0.0 | ||
|
||
dependencies: | ||
firebase_analytics: ^10.6.3 | ||
firebase_crashlytics: ^3.4.3 | ||
flutter: | ||
sdk: flutter | ||
|
||
dev_dependencies: | ||
altive_lints: ^1.8.1 | ||
flutter_test: | ||
sdk: flutter | ||
mocktail: ^1.0.1 |
Oops, something went wrong.