Skip to content

Commit 757e6c6

Browse files
committed
feat(logging): integrate AppDiagnostics for enhanced error reporting and performance tracking
- Added AppDiagnostics for centralized logging and error reporting using Sentry. - Updated various components to report exceptions and performance metrics to AppDiagnostics. - Refactored background tasks and view models to utilize AppDiagnostics for better observability. - Increased Java and Kotlin compatibility to version 17 in build.gradle files. - Introduced Sentry configuration for improved error tracking and performance monitoring. - Added tests for AppDiagnostics to ensure proper functionality of logging and error reporting.
1 parent 6a57c07 commit 757e6c6

16 files changed

Lines changed: 833 additions & 96 deletions

File tree

android/app/build.gradle

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,15 @@ android {
6969
}
7070

7171
compileOptions {
72-
sourceCompatibility JavaVersion.VERSION_1_8
73-
targetCompatibility JavaVersion.VERSION_1_8
72+
sourceCompatibility JavaVersion.VERSION_17
73+
targetCompatibility JavaVersion.VERSION_17
7474
coreLibraryDesugaringEnabled true
7575
}
7676

77+
kotlinOptions {
78+
jvmTarget = '17'
79+
}
80+
7781
signingConfigs {
7882
release {
7983
keyAlias keystoreProperties['keyAlias']

android/build.gradle

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -60,48 +60,6 @@ subprojects {
6060
}
6161
android.namespace = namespaceValue
6262
}
63-
64-
android.compileOptions {
65-
sourceCompatibility JavaVersion.VERSION_1_8
66-
targetCompatibility JavaVersion.VERSION_1_8
67-
}
68-
}
69-
70-
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
71-
kotlinOptions {
72-
jvmTarget = "1.8"
73-
}
74-
}
75-
76-
tasks.withType(JavaCompile).configureEach {
77-
sourceCompatibility = "1.8"
78-
targetCompatibility = "1.8"
79-
}
80-
81-
if (project.name == "in_app_review") {
82-
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
83-
kotlinOptions {
84-
jvmTarget = "11"
85-
}
86-
}
87-
88-
tasks.withType(JavaCompile).configureEach {
89-
sourceCompatibility = "11"
90-
targetCompatibility = "11"
91-
}
92-
}
93-
94-
if (project.name == "shared_preferences_android") {
95-
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
96-
kotlinOptions {
97-
jvmTarget = "17"
98-
}
99-
}
100-
101-
tasks.withType(JavaCompile).configureEach {
102-
sourceCompatibility = "17"
103-
targetCompatibility = "17"
104-
}
10563
}
10664
}
10765

lib/canteen/background/background_canteen_update.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:dualmate/canteen/business/canteen_provider.dart';
22
import 'package:dualmate/common/background/task_callback.dart';
33
import 'package:dualmate/common/background/work_scheduler_service.dart';
4+
import 'package:dualmate/common/logging/app_diagnostics.dart';
45
import 'package:dualmate/common/util/cancellation_token.dart';
56
import 'package:dualmate/common/util/date_utils.dart';
67

@@ -26,6 +27,15 @@ class BackgroundCanteenUpdate extends TaskCallback {
2627
print("Background canteen update failed");
2728
print(exception);
2829
print(trace);
30+
await AppDiagnostics.instance.reportCaughtException(
31+
exception,
32+
trace,
33+
message: 'Background canteen update failed',
34+
tags: {'feature': 'canteen'},
35+
contexts: {
36+
'canteen_update': {'task': name},
37+
},
38+
);
2939
print("Background canteen update status: failure");
3040
print(
3141
"Background canteen update next: retry in ${_retryInterval.inHours}h");

lib/common/appstart/app_initializer.dart

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:io';
33

44
import 'package:dualmate/canteen/business/canteen_provider.dart';
55
import 'package:dualmate/common/appstart/background_initialize.dart';
6+
import 'package:dualmate/common/logging/app_diagnostics.dart';
67
import 'package:dualmate/common/appstart/localization_initialize.dart';
78
import 'package:dualmate/common/appstart/notification_schedule_changed_initialize.dart';
89
import 'package:dualmate/common/appstart/notifications_initialize.dart';
@@ -85,10 +86,28 @@ Future<void> initializeAppBackground(bool isBackground) async {
8586
print("Background init: workmanager failed (${exception.runtimeType})");
8687
print(exception);
8788
print(trace);
89+
await AppDiagnostics.instance.reportCaughtException(
90+
exception,
91+
trace,
92+
message: 'Background init: workmanager failed',
93+
tags: {'feature': 'background'},
94+
contexts: {
95+
'background': {'phase': 'workmanager.setup'},
96+
},
97+
);
8898
} catch (error, trace) {
8999
print("Background init: workmanager failed");
90100
print(error);
91101
print(trace);
102+
await AppDiagnostics.instance.reportCaughtException(
103+
error,
104+
trace,
105+
message: 'Background init: workmanager failed',
106+
tags: {'feature': 'background'},
107+
contexts: {
108+
'background': {'phase': 'workmanager.setup'},
109+
},
110+
);
92111
}
93112

94113
try {
@@ -99,10 +118,28 @@ Future<void> initializeAppBackground(bool isBackground) async {
99118
print("Background init: schedule notify failed (${exception.runtimeType})");
100119
print(exception);
101120
print(trace);
121+
await AppDiagnostics.instance.reportCaughtException(
122+
exception,
123+
trace,
124+
message: 'Background init: schedule notify failed',
125+
tags: {'feature': 'notifications'},
126+
contexts: {
127+
'notifications': {'phase': 'schedule_changed.setup'},
128+
},
129+
);
102130
} catch (error, trace) {
103131
print("Background init: schedule notify failed");
104132
print(error);
105133
print(trace);
134+
await AppDiagnostics.instance.reportCaughtException(
135+
error,
136+
trace,
137+
message: 'Background init: schedule notify failed',
138+
tags: {'feature': 'notifications'},
139+
contexts: {
140+
'notifications': {'phase': 'schedule_changed.setup'},
141+
},
142+
);
106143
}
107144

108145
tz.initializeTimeZones();
@@ -176,11 +213,29 @@ Future<void> _prewarmCanteenIfStaleInBackground(
176213
print("Foreground canteen prewarm failed (${exception.runtimeType})");
177214
print(exception);
178215
print(trace);
216+
await AppDiagnostics.instance.reportCaughtException(
217+
exception,
218+
trace,
219+
message: 'Foreground canteen prewarm failed',
220+
tags: {'feature': 'canteen'},
221+
contexts: {
222+
'canteen': {'phase': 'foreground_prewarm'},
223+
},
224+
);
179225
// Swallowing here is intentional; we don't want to block startup.
180226
} catch (error, trace) {
181227
print("Foreground canteen prewarm failed");
182228
print(error);
183229
print(trace);
230+
await AppDiagnostics.instance.reportCaughtException(
231+
error,
232+
trace,
233+
message: 'Foreground canteen prewarm failed',
234+
tags: {'feature': 'canteen'},
235+
contexts: {
236+
'canteen': {'phase': 'foreground_prewarm'},
237+
},
238+
);
184239
// Swallowing here is intentional; we don't want to block startup.
185240
}
186241
}
@@ -202,11 +257,29 @@ Future<void> _setupCalendarSyncInBackground(Stopwatch stopwatch) async {
202257
"Foreground heavy init: calendar sync failed (${exception.runtimeType})");
203258
print(exception);
204259
print(trace);
260+
await AppDiagnostics.instance.reportCaughtException(
261+
exception,
262+
trace,
263+
message: 'Foreground heavy init: calendar sync failed',
264+
tags: {'feature': 'calendar'},
265+
contexts: {
266+
'calendar': {'phase': 'foreground_sync_setup'},
267+
},
268+
);
205269
// Swallowing here is intentional; we don't want to block startup.
206270
} catch (error, trace) {
207271
print("Foreground heavy init: calendar sync failed");
208272
print(error);
209273
print(trace);
274+
await AppDiagnostics.instance.reportCaughtException(
275+
error,
276+
trace,
277+
message: 'Foreground heavy init: calendar sync failed',
278+
tags: {'feature': 'calendar'},
279+
contexts: {
280+
'calendar': {'phase': 'foreground_sync_setup'},
281+
},
282+
);
210283
// Swallowing here is intentional; we don't want to block startup.
211284
}
212285
}

lib/common/background/background_work_scheduler.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import 'dart:ui';
22

33
import 'package:dualmate/common/appstart/app_initializer.dart';
4+
import 'package:dualmate/common/logging/app_diagnostics.dart';
5+
import 'package:dualmate/common/logging/sentry_configuration.dart';
46
import 'package:dualmate/common/background/task_callback.dart';
57
import 'package:dualmate/common/background/work_scheduler_service.dart';
68
import 'package:flutter/widgets.dart';
79
import 'package:kiwi/kiwi.dart';
10+
import 'package:sentry_flutter/sentry_flutter.dart';
811
import 'package:workmanager/workmanager.dart';
912

1013
///
@@ -111,6 +114,10 @@ class BackgroundWorkScheduler extends WorkSchedulerService {
111114
try {
112115
print("Background task started: $taskId with data: $inputData");
113116

117+
if (!Sentry.isEnabled) {
118+
await SentryFlutter.init(configureSentryOptions);
119+
}
120+
114121
await initializeApp(true);
115122

116123
WorkSchedulerService scheduler = KiwiContainer().resolve();
@@ -120,6 +127,18 @@ class BackgroundWorkScheduler extends WorkSchedulerService {
120127
print("Background task failed:");
121128
print(e);
122129
print(trace);
130+
await AppDiagnostics.instance.reportCaughtException(
131+
e,
132+
trace,
133+
message: 'Background task failed',
134+
tags: {'feature': 'background'},
135+
contexts: {
136+
'background_task': {
137+
'taskId': '$taskId',
138+
'inputData': inputData?.toString(),
139+
},
140+
},
141+
);
123142
return false;
124143
}
125144

lib/common/logging/analytics.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:dualmate/common/logging/app_diagnostics.dart';
12
import 'package:flutter/widgets.dart';
23

34
class Analytics {
@@ -18,11 +19,27 @@ class _PerfAwareNavigatorObserver extends NavigatorObserver {
1819
@override
1920
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
2021
super.didPush(route, previousRoute);
22+
AppDiagnostics.instance.recordNavigation(
23+
route.settings.name ?? route.runtimeType.toString(),
24+
data: {
25+
'type': 'didPush',
26+
'from': previousRoute?.settings.name,
27+
'to': route.settings.name,
28+
},
29+
);
2130
}
2231

2332
@override
2433
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
2534
super.didPop(route, previousRoute);
35+
AppDiagnostics.instance.recordNavigation(
36+
previousRoute?.settings.name ?? previousRoute.runtimeType.toString(),
37+
data: {
38+
'type': 'didPop',
39+
'from': route.settings.name,
40+
'to': previousRoute?.settings.name,
41+
},
42+
);
2643
}
2744
}
2845

0 commit comments

Comments
 (0)