Skip to content

Commit

Permalink
Implement logging
Browse files Browse the repository at this point in the history
  • Loading branch information
lockieRichter committed Mar 19, 2024
1 parent a68fffd commit d3fe7f4
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 19 deletions.
6 changes: 6 additions & 0 deletions ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-FIRDebugEnabled"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
Expand Down
13 changes: 13 additions & 0 deletions lib/src/data/logging/debug_logger.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:dantex/src/data/logging/event.dart';
import 'package:dantex/src/data/logging/logger.dart';

class DebugLogger extends DanteLogger {
@override
void trackEvent(DanteTrackingEvent event) {
String message = 'Event: ${event.name}';
if (event.props.isNotEmpty) {
message += ' - ${event.props}';
}
d(message);
}
}
143 changes: 143 additions & 0 deletions lib/src/data/logging/event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
abstract class DanteTrackingEvent {
final String name;
final Map<String, Object?> props;

DanteTrackingEvent(this.name, {this.props = const {}});
}

class AuthenticationSource {
final String name;

AuthenticationSource(this.name);
}

class LoginSource {
final String name;

LoginSource(this.name);
}

class OpenTermsOfServices extends DanteTrackingEvent {
OpenTermsOfServices() : super('open_terms_of_services');
}

class ResetPasswordSuccess extends DanteTrackingEvent {
ResetPasswordSuccess() : super('reset_password_success');
}

class ResetPasswordFailed extends DanteTrackingEvent {
ResetPasswordFailed() : super('reset_password_failed');
}

class ReportLoginProblem extends DanteTrackingEvent {
ReportLoginProblem() : super('report_login_problem');
}

class OpenLogin extends DanteTrackingEvent {
OpenLogin(LoginSource source)
: super('open_login', props: {'source': source.name});
}

class Login extends DanteTrackingEvent {
Login(AuthenticationSource source)
: super('app_login', props: {'source': source.name});
}

class SignUp extends DanteTrackingEvent {
SignUp(AuthenticationSource source)
: super('app_signup', props: {'source': source.name});
}

class Logout extends DanteTrackingEvent {
Logout(AuthenticationSource source)
: super('app_logout', props: {'source': source.name});
}

class AnonymousUpgrade extends DanteTrackingEvent {
AnonymousUpgrade() : super('anonymous_upgrade');
}

class UpdateMailPasswordSuccess extends DanteTrackingEvent {
UpdateMailPasswordSuccess() : super('update_mail_password_success');
}

class UpdateMailPasswordFailure extends DanteTrackingEvent {
UpdateMailPasswordFailure() : super('update_mail_password_failure');
}

class UserNameChanged extends DanteTrackingEvent {
UserNameChanged() : super('user_name_changed');
}

class UserImageChanged extends DanteTrackingEvent {
UserImageChanged() : super('user_image_changed');
}

class BackupMadeEvent extends DanteTrackingEvent {
BackupMadeEvent(String backupProvider)
: super(
'backup_made',
props: {'backup_provider': backupProvider},
);
}

class InterestedInOnlineStorageEvent extends DanteTrackingEvent {
InterestedInOnlineStorageEvent() : super('interested_in_online_storage');
}

class StartImport extends DanteTrackingEvent {
StartImport(String importer)
: super(
'start_import',
props: {'importer_name': importer},
);
}

class OpenBackupFile extends DanteTrackingEvent {
OpenBackupFile(String providerAcronym)
: super(
'open_backup_file',
props: {'backup_provider': providerAcronym},
);
}

class TrackingStateChanged extends DanteTrackingEvent {
TrackingStateChanged(bool state)
: super('tracking_state_changed', props: {'state': state});
}

class PickRandomBook extends DanteTrackingEvent {
PickRandomBook(int booksInBacklog)
: super(
'pick_random_book',
props: {'backlog_count': booksInBacklog},
);
}

class AddSuggestionToWishlist extends DanteTrackingEvent {
AddSuggestionToWishlist(
String suggestionId,
String bookTitle,
String suggester,
) : super(
'add_suggestion_to_wishlist',
props: {
'suggestion_id': suggestionId,
'suggestion_book': bookTitle,
'suggestion_suggester': suggester,
},
);
}

class SuggestBook extends DanteTrackingEvent {
SuggestBook(String title)
: super('suggest_book', props: {'book_title': title});
}

class OpenAdFreeMediumArticle extends DanteTrackingEvent {
OpenAdFreeMediumArticle() : super('open_ad_free_medium_article');
}

class DisableRandomBookInteraction extends DanteTrackingEvent {
DisableRandomBookInteraction() : super('disable_random_book_interaction');
}
18 changes: 18 additions & 0 deletions lib/src/data/logging/firebase_logger.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'dart:async';

import 'package:dantex/src/data/logging/event.dart';
import 'package:dantex/src/data/logging/logger.dart';
import 'package:firebase_analytics/firebase_analytics.dart';

class FirebaseLogger extends DanteLogger {
@override
void trackEvent(DanteTrackingEvent event) {
// Log the event in the background.
unawaited(
FirebaseAnalytics.instance.logEvent(
name: event.name,
parameters: event.props,
),
);
}
}
20 changes: 20 additions & 0 deletions lib/src/data/logging/logger.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:dantex/src/data/logging/error_only_filter.dart';
import 'package:dantex/src/data/logging/event.dart';
import 'package:dantex/src/data/logging/firebase_log_output.dart';
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';

abstract class DanteLogger extends Logger {
DanteLogger()
: super(
filter: kDebugMode ? DevelopmentFilter() : ErrorOnlyFilter(),
printer: PrettyPrinter(
methodCount: 0,
printTime: true,
),
// Use Firebase logging only for production
output: kDebugMode ? ConsoleOutput() : FirebaseLogOutput(),
);

void trackEvent(DanteTrackingEvent event);
}
21 changes: 10 additions & 11 deletions lib/src/providers/service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import 'package:dantex/src/data/bookdownload/default_book_downloader.dart';
import 'package:dantex/src/data/bookdownload/entity/book_suggestion.dart';
import 'package:dantex/src/data/isbn/barcode_isbn_scanner_service.dart';
import 'package:dantex/src/data/isbn/isbn_scanner_service.dart';
import 'package:dantex/src/data/logging/error_only_filter.dart';
import 'package:dantex/src/data/logging/firebase_log_output.dart';
import 'package:dantex/src/data/logging/debug_logger.dart';
import 'package:dantex/src/data/logging/firebase_logger.dart';
import 'package:dantex/src/data/logging/logger.dart';
import 'package:dantex/src/data/recommendations/book_recommendation.dart';
import 'package:dantex/src/data/recommendations/recommendations.dart';
import 'package:dantex/src/data/search/search.dart';
Expand All @@ -24,7 +25,6 @@ import 'package:dantex/src/data/timeline/timeline.dart';
import 'package:dantex/src/providers/api.dart';
import 'package:dantex/src/providers/repository.dart';
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:shared_preferences/shared_preferences.dart';

Expand Down Expand Up @@ -70,14 +70,13 @@ SharedPreferences sharedPreferences(SharedPreferencesRef ref) =>
throw UnimplementedError();

@riverpod
Logger logger(LoggerRef ref) => Logger(
filter: kDebugMode ? DevelopmentFilter() : ErrorOnlyFilter(),
printer: PrettyPrinter(
printTime: true,
),
// Use Firebase logging only for production
output: kDebugMode ? ConsoleOutput() : FirebaseLogOutput(),
);
DanteLogger logger(LoggerRef ref) {
// If we are in dev mode, return debug tracker.
if (kDebugMode) {
return DebugLogger();
}
return FirebaseLogger();
}

@riverpod
Recommendations recommendations(RecommendationsRef ref) {
Expand Down
21 changes: 18 additions & 3 deletions lib/src/ui/login/email_login_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:dantex/src/data/authentication/entity/dante_user.dart';
import 'package:dantex/src/data/logging/event.dart' hide AuthenticationSource;
import 'package:dantex/src/providers/app_router.dart';
import 'package:dantex/src/providers/authentication.dart';
import 'package:dantex/src/providers/service.dart';
import 'package:dantex/src/ui/core/dante_components.dart';
import 'package:dantex/src/ui/core/platform_components.dart';
import 'package:easy_localization/easy_localization.dart';
Expand Down Expand Up @@ -174,6 +176,9 @@ class EmailLoginPageState extends ConsumerState<EmailLoginPage> {
email: _emailController.text,
password: _passwordController.text,
);
ref.read(loggerProvider).trackEvent(
OpenLogin(LoginSource('email')),
);
} on Exception catch (exception, stackTrace) {
setState(() {
_isLoading = false;
Expand Down Expand Up @@ -238,9 +243,19 @@ class EmailLoginPageState extends ConsumerState<EmailLoginPage> {
action: (_) async {
// Close the dialog.
Navigator.of(context).pop();
await ref
.read(authenticationRepositoryProvider)
.sendPasswordResetRequest(email: _emailController.text);
try {
await ref
.read(authenticationRepositoryProvider)
.sendPasswordResetRequest(email: _emailController.text);
ref.read(loggerProvider).trackEvent(ResetPasswordSuccess());
} catch (e, s) {
ref.read(loggerProvider).e(
'Failed to reset password',
error: e,
stackTrace: s,
);
ref.read(loggerProvider).trackEvent(ResetPasswordFailed());
}
// Navigate back to the login page.
if (context.mounted) {
context.pushReplacement(DanteRoute.login.navigationUrl);
Expand Down
8 changes: 8 additions & 0 deletions lib/src/ui/login/login_page.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'dart:async';

import 'package:dantex/src/data/logging/event.dart';
import 'package:dantex/src/providers/app_router.dart';
import 'package:dantex/src/providers/authentication.dart';
import 'package:dantex/src/providers/service.dart';
import 'package:dantex/src/ui/core/dante_components.dart';
import 'package:dantex/src/ui/core/platform_components.dart';
import 'package:easy_localization/easy_localization.dart';
Expand Down Expand Up @@ -73,6 +75,9 @@ class LoginPageState extends ConsumerState<LoginPage> {
await ref
.read(authenticationRepositoryProvider)
.loginWithGoogle();
ref.read(loggerProvider).trackEvent(
OpenLogin(LoginSource('google')),
);
} on Exception catch (exception, stackTrace) {
_loginErrorReceived(exception, stackTrace);
}
Expand Down Expand Up @@ -186,6 +191,9 @@ class LoginPageState extends ConsumerState<LoginPage> {
await ref
.read(authenticationRepositoryProvider)
.loginAnonymously();
ref.read(loggerProvider).trackEvent(
OpenLogin(LoginSource('email')),
);
} on Exception catch (exception, stackTrace) {
_loginErrorReceived(exception, stackTrace);
}
Expand Down
24 changes: 21 additions & 3 deletions lib/src/ui/profile/change_password_bottom_sheet.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:dantex/src/data/logging/event.dart';
import 'package:dantex/src/providers/authentication.dart';
import 'package:dantex/src/providers/service.dart';
import 'package:dantex/src/ui/core/dante_components.dart';
import 'package:dantex/src/ui/core/handle.dart';
import 'package:easy_localization/easy_localization.dart';
Expand Down Expand Up @@ -57,9 +59,25 @@ class ChangePasswordBottomSheetState
onPressed: () async {
if (_isValidPassword()) {
Navigator.of(context).pop();
await ref
.read(authenticationRepositoryProvider)
.updateMailPassword(password: _passwordController.text);
try {
await ref
.read(authenticationRepositoryProvider)
.updateMailPassword(
password: _passwordController.text,
);
ref
.read(loggerProvider)
.trackEvent(UpdateMailPasswordSuccess());
} catch (e, s) {
ref.read(loggerProvider).e(
'Failed to reset password',
error: e,
stackTrace: s,
);
ref
.read(loggerProvider)
.trackEvent(UpdateMailPasswordFailure());
}
}
},
),
Expand Down
8 changes: 6 additions & 2 deletions lib/src/ui/settings/settings_page.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'package:dantex/src/data/book/book_sort_strategy.dart';
import 'package:dantex/src/data/logging/event.dart';
import 'package:dantex/src/data/settings/settings_repository.dart';
import 'package:dantex/src/providers/app_router.dart';
import 'package:dantex/src/providers/authentication.dart';
import 'package:dantex/src/providers/repository.dart';
import 'package:dantex/src/providers/service.dart';
import 'package:dantex/src/ui/core/themed_app_bar.dart';
import 'package:dantex/src/ui/settings/single_choice_dialog.dart';
import 'package:dantex/src/util/url_launcher.dart';
Expand Down Expand Up @@ -157,8 +159,10 @@ class SettingsPage extends ConsumerWidget {
SettingsTile(
title: Text('settings.data_privacy.terms_and_conditions'.tr()),
leading: const Icon(Icons.verified_user_outlined),
onPressed: (context) async =>
tryLaunchUrl('https://dantebooks.com/#/terms'),
onPressed: (context) async {
ref.read(loggerProvider).trackEvent(OpenTermsOfServices());
return tryLaunchUrl('https://dantebooks.com/#/terms');
},
),
],
),
Expand Down

0 comments on commit d3fe7f4

Please sign in to comment.