Skip to content

Commit 44f8a84

Browse files
feat: Add logging to Bloc, Navigation and API calls.
feat: Add logging to Bloc, Navigation and API calls.
2 parents 2bb35a5 + f2e27d1 commit 44f8a84

8 files changed

Lines changed: 134 additions & 33 deletions

File tree

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
import 'dart:developer';
2+
13
import 'package:dio/dio.dart';
24
import 'package:flutter/foundation.dart';
5+
import 'package:get/get.dart' as nav;
36

47
import '../../config/config.dart';
8+
import '../../constants/routes.dart';
9+
import '../../constants/strings.dart';
510
import '../local/storage_service.dart';
611

712
class ApiService {
@@ -19,32 +24,29 @@ class ApiService {
1924
Map<String, dynamic>? headers,
2025
Map<String, dynamic>? query,
2126
}) async {
27+
log('[API] [GET] >> $endpoint');
2228
Response? response;
2329
try {
2430
response = await _channel.get(
2531
(baseUrl ?? Environment.baseUrl) + endpoint,
2632
queryParameters: query,
2733
options: Options(
28-
validateStatus: (status) {
29-
return status! < 500;
30-
},
34+
validateStatus: _validate,
3135
headers: headers,
3236
),
3337
);
34-
return {
35-
'status_code': response.statusCode ?? 0,
36-
'data': response.data ?? 'null',
37-
};
3838
} on Exception catch (exception, stacktrace) {
3939
debugPrint(
4040
'ERROR: Failed during a GET request.\n'
4141
'Endpoint: $endpoint\nQuery: $query\n'
4242
'Exception: $exception\nStacktrace: $stacktrace',
4343
);
44+
rethrow;
4445
}
46+
log('[API] [GET] << received ${response.statusCode} from $endpoint');
4547
return {
46-
'status_code': response?.statusCode ?? 0,
47-
'data': response?.data ?? 'null',
48+
'status_code': response.statusCode ?? 0,
49+
'data': response.data ?? 'null',
4850
};
4951
}
5052

@@ -54,32 +56,29 @@ class ApiService {
5456
Map<String, dynamic>? headers,
5557
Map<String, dynamic>? data,
5658
}) async {
59+
log('[API] [POST] >> $endpoint');
5760
Response? response;
5861
try {
5962
response = await _channel.post(
6063
Environment.baseUrl + endpoint,
6164
data: data,
6265
options: Options(
63-
validateStatus: (status) {
64-
return status! < 500;
65-
},
66+
validateStatus: _validate,
6667
headers: headers,
6768
),
6869
);
69-
return {
70-
'status_code': response.statusCode ?? 0,
71-
'data': response.data ?? 'null',
72-
};
7370
} on Exception catch (exception, stacktrace) {
7471
debugPrint(
7572
'ERROR: Failed during a POST request.\n'
7673
'Endpoint: $endpoint\nData: $data\n'
7774
'Exception: $exception\nStacktrace: $stacktrace',
7875
);
76+
rethrow;
7977
}
78+
log('[API] [POST] << received ${response.statusCode} from $endpoint');
8079
return {
81-
'status_code': response?.statusCode ?? 0,
82-
'data': response?.data ?? 'null',
80+
'status_code': response.statusCode ?? 0,
81+
'data': response.data ?? 'null',
8382
};
8483
}
8584

@@ -89,32 +88,29 @@ class ApiService {
8988
Map<String, dynamic>? headers,
9089
Map<String, dynamic>? data,
9190
}) async {
91+
log('[API] [PUT] >> $endpoint');
9292
Response? response;
9393
try {
9494
response = await _channel.put(
9595
Environment.baseUrl + endpoint,
9696
data: data,
9797
options: Options(
98-
validateStatus: (status) {
99-
return status! < 500;
100-
},
98+
validateStatus: _validate,
10199
headers: headers,
102100
),
103101
);
104-
return {
105-
'status_code': response.statusCode ?? 0,
106-
'data': response.data ?? 'null',
107-
};
108102
} on Exception catch (exception, stacktrace) {
109103
debugPrint(
110104
'ERROR: Failed during a PUT request.\n'
111105
'Endpoint: $endpoint\nData: $data\n'
112106
'Exception: $exception\nStacktrace: $stacktrace',
113107
);
108+
rethrow;
114109
}
110+
log('[API] [PUT] << received ${response.statusCode} from $endpoint');
115111
return {
116-
'status_code': response?.statusCode ?? 0,
117-
'data': response?.data ?? 'null',
112+
'status_code': response.statusCode ?? 0,
113+
'data': response.data ?? 'null',
118114
};
119115
}
120116

@@ -123,4 +119,12 @@ class ApiService {
123119
final token = StorageService.authToken;
124120
headers.addAll({'authorization': token});
125121
}
122+
123+
static bool _validate(int? status) {
124+
if (status == 401) {
125+
StorageService.delete(AppStrings.authTokenKey);
126+
nav.Get.offAllNamed(AppRoutes.login);
127+
}
128+
return status! < 500;
129+
}
126130
}

lib/main_development.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
77
import 'package:path_provider/path_provider.dart';
88

99
import 'data/constants/strings.dart';
10+
import 'presentation/core/bloc_observer.dart';
1011
import 'presentation/core/main_app.dart';
1112

1213
Future<void> main() async {
@@ -16,10 +17,11 @@ Future<void> main() async {
1617
await _initHive();
1718
final hydratedStorage = await _initHydratedBloc();
1819

19-
// Zone for Hydrated Bloc.
20-
HydratedBlocOverrides.runZoned(
20+
// Zone for Hydrated Bloc and AppBlocObserver.
21+
await HydratedBlocOverrides.runZoned(
2122
() async => runApp(await Codephile.run()),
2223
storage: hydratedStorage,
24+
blocObserver: AppBlocObserver(),
2325
);
2426
}
2527

lib/main_production.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'package:sentry_flutter/sentry_flutter.dart';
1313

1414
import 'data/config/config.dart';
1515
import 'data/constants/strings.dart';
16+
import 'presentation/core/bloc_observer.dart';
1617
import 'presentation/core/main_app.dart';
1718

1819
void main() {
@@ -28,10 +29,11 @@ void main() {
2829
await _initHive();
2930
final hydratedStorage = await _initHydratedBloc();
3031

31-
// Zone for Hydrated Bloc.
32-
HydratedBlocOverrides.runZoned(
32+
// Zone for Hydrated Bloc and AppBlocObserver.
33+
await HydratedBlocOverrides.runZoned(
3334
() async => runApp(await Codephile.run()),
3435
storage: hydratedStorage,
36+
blocObserver: AppBlocObserver(),
3537
);
3638
},
3739
_onError,
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'dart:developer';
2+
3+
import 'package:flutter/foundation.dart';
4+
import 'package:flutter_bloc/flutter_bloc.dart';
5+
import 'package:sentry_flutter/sentry_flutter.dart';
6+
7+
class AppBlocObserver extends BlocObserver {
8+
@override
9+
void onCreate(BlocBase bloc) {
10+
log(
11+
'[BLOC] [CREATE] ${bloc.runtimeType}',
12+
);
13+
super.onCreate(bloc);
14+
}
15+
16+
@override
17+
void onEvent(Bloc bloc, Object? event) {
18+
super.onEvent(bloc, event);
19+
log(
20+
'[BLOC] [EVENT] ${bloc.runtimeType} $event',
21+
);
22+
}
23+
24+
@override
25+
void onChange(BlocBase bloc, Change change) {
26+
super.onChange(bloc, change);
27+
log(
28+
'[BLOC] [CHANGE] ${bloc.runtimeType} '
29+
'{ currentState: ${change.currentState}, '
30+
'nextState: ${change.nextState} }',
31+
);
32+
}
33+
34+
@override
35+
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
36+
if (kDebugMode) {
37+
log(
38+
'[BLOC] [ERROR] ${bloc.runtimeType}\n'
39+
'Error: $error\n'
40+
'Stacktrace: $stackTrace',
41+
);
42+
} else {
43+
Sentry.captureException(
44+
error,
45+
stackTrace: stackTrace,
46+
hint: bloc.runtimeType.toString(),
47+
);
48+
}
49+
super.onError(bloc, error, stackTrace);
50+
}
51+
52+
@override
53+
void onClose(BlocBase bloc) {
54+
log(
55+
'[BLOC] [CLOSE] ${bloc.runtimeType}',
56+
);
57+
super.onClose(bloc);
58+
}
59+
}

lib/presentation/core/main_app.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
22
import 'package:get/get.dart';
33
import 'package:sentry_flutter/sentry_flutter.dart';
44

5-
import 'router.dart';
6-
75
import '../../data/services/local/storage_service.dart';
86
import '../../data/services/remote/api_service.dart';
7+
import 'navigation_observer.dart';
8+
import 'router.dart';
99

1010
class Codephile extends StatelessWidget {
1111
const Codephile({Key? key}) : super(key: key);
@@ -17,6 +17,7 @@ class Codephile extends StatelessWidget {
1717
// home: const SplashScreen(),
1818
navigatorObservers: <NavigatorObserver>[
1919
SentryNavigatorObserver(),
20+
AppNavigationObserver(),
2021
],
2122
onGenerateRoute: AppRouter.generateRoute,
2223
title: 'Codephile',
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'dart:developer';
2+
3+
import 'package:flutter/material.dart';
4+
5+
class AppNavigationObserver extends NavigatorObserver {
6+
@override
7+
void didPush(Route route, Route? previousRoute) {
8+
log('[NAV] [PUSH] { from ${previousRoute?.settings.name} to ${route.settings.name} }');
9+
}
10+
11+
@override
12+
void didReplace({Route? newRoute, Route? oldRoute}) {
13+
log('[NAV] [REPLACE] { from ${oldRoute?.settings.name} to ${newRoute?.settings.name} }');
14+
}
15+
16+
@override
17+
void didRemove(Route route, Route? previousRoute) {
18+
log('[NAV] [REMOVE] { from ${route.settings.name} to ${previousRoute?.settings.name} }');
19+
}
20+
21+
@override
22+
void didPop(Route route, Route? previousRoute) {
23+
log('[NAV] [POP] { from ${route.settings.name} to ${previousRoute?.settings.name} }');
24+
}
25+
}

pubspec.lock

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@ packages:
176176
url: "https://pub.dartlang.org"
177177
source: hosted
178178
version: "4.0.4"
179+
equatable:
180+
dependency: "direct main"
181+
description:
182+
name: equatable
183+
url: "https://pub.dartlang.org"
184+
source: hosted
185+
version: "2.0.3"
179186
fake_async:
180187
dependency: transitive
181188
description:

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ environment:
1010

1111
dependencies:
1212
dio: ^4.0.4
13+
equatable: ^2.0.3
1314
firebase_core: ^1.11.0
1415
firebase_crashlytics: ^2.4.5
1516
firebase_messaging: ^11.2.5

0 commit comments

Comments
 (0)