improved Logging (8.2)

appointment_merge
Faiz Hashmi 3 months ago
parent 675441894a
commit 2288192975

@ -24,7 +24,6 @@ class AppStrings {
static String dataLogsFileName = "data_logs.txt"; static String dataLogsFileName = "data_logs.txt";
static String errorLogsFileName = "error_logs.txt"; static String errorLogsFileName = "error_logs.txt";
static String openAppNativeFunctionName = "reopenApp"; static String openAppNativeFunctionName = "reopenApp";
} }
@ -107,7 +106,8 @@ class AppConstants {
static String testIP = '12.4.5.1'; // projectID.QlineType.ScreenType.AnyNumber (1 to 10) static String testIP = '12.4.5.1'; // projectID.QlineType.ScreenType.AnyNumber (1 to 10)
static int thresholdForListUI = 3; static int thresholdForListUI = 3;
static double currentBuildVersion = 8.1; static double currentBuildVersion = 8.2;
static double clearLogsHoursThreshold = 48;
} }
class ApiConstants { class ApiConstants {
@ -144,6 +144,7 @@ class ApiConstants {
class CacheConstants { class CacheConstants {
static String lastTimeUpdated = "lastTimeUpdated"; static String lastTimeUpdated = "lastTimeUpdated";
static String logLastCleared = "log_last_cleared";
} }
// calling for pharmacy // calling for pharmacy

@ -49,14 +49,14 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
); );
List<GlobalConfigurationsModel> globalConfigurationsModel = List.generate(genericModel.data.length, (index) => GlobalConfigurationsModel.fromJson(json: genericModel.data[index])); List<GlobalConfigurationsModel> globalConfigurationsModel = List.generate(genericModel.data.length, (index) => GlobalConfigurationsModel.fromJson(json: genericModel.data[index]));
if (globalConfigurationsModel.isNotEmpty) { if (globalConfigurationsModel.isNotEmpty) {
loggerService.logToFile(globalConfigurationsModel.toString(), type: LogTypeEnum.data); loggerService.logToFile(message: globalConfigurationsModel.toString(), type: LogTypeEnum.data, source: "getGlobalScreenConfigurations-> screen_details_repo.dart");
return globalConfigurationsModel.first; return globalConfigurationsModel.first;
} }
return null; return null;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "getGlobalScreenConfigurations-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }
@ -82,7 +82,7 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
return genericModel; return genericModel;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "createTestTickets-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }
@ -109,7 +109,7 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
return genericRespModel; return genericRespModel;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "createTicketFromKiosk-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }
@ -132,7 +132,7 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
return null; return null;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "getWeatherDetailsByCity-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }
@ -156,7 +156,7 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
return null; return null;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "getPrayerDetailsByLatLong-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }
@ -179,7 +179,7 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
return null; return null;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "getRssFeedDetailsByLanguageID-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }
@ -201,7 +201,7 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
return genericModel; return genericModel;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "acknowledgeTicket-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }
@ -225,7 +225,7 @@ class ScreenDetailsRepoImp implements ScreenDetailsRepo {
return genericModel; return genericModel;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "acknowledgeTicketForAppointment-> screen_details_repo.dart", type: LogTypeEnum.error);
InfoComponents.showToast(e.toString()); InfoComponents.showToast(e.toString());
return null; return null;
} }

@ -57,11 +57,12 @@ class SignalrRepoImp implements SignalrRepo {
// Attempt to reconnect with limit and delay // Attempt to reconnect with limit and delay
if (reconnectAttempts < maxReconnectAttempts) { if (reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++; reconnectAttempts++;
loggerService.logToFile("SignalR reconnect attempt #$reconnectAttempts", type: LogTypeEnum.data); loggerService.logToFile(message: "SignalR reconnect attempt #$reconnectAttempts", source: "startHubConnection -> signalR_repo.dart", type: LogTypeEnum.data);
await Future.delayed(reconnectDelay); await Future.delayed(reconnectDelay);
try { try {
await connection!.start(); await connection!.start();
loggerService.logToFile("SignalR reconnected after disconnect", type: LogTypeEnum.data); loggerService.logToFile(message: "SignalR reconnected after disconnect", source: "startHubConnection -> signalR_repo.dart", type: LogTypeEnum.data);
reconnectAttempts = 0; // Reset on success reconnectAttempts = 0; // Reset on success
} catch (e) { } catch (e) {
loggerService.logError("Reconnect failed: $e"); loggerService.logError("Reconnect failed: $e");
@ -89,7 +90,7 @@ class SignalrRepoImp implements SignalrRepo {
return true; return true;
} catch (e) { } catch (e) {
loggerService.logError(e.toString()); loggerService.logError(e.toString());
loggerService.logToFile(e.toString(), type: LogTypeEnum.error); loggerService.logToFile(message: e.toString(), source: "startHubConnection -> signalR_repo.dart", type: LogTypeEnum.error);
return false; return false;
} }
} }

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:hmg_qline/constants/app_constants.dart'; import 'package:hmg_qline/constants/app_constants.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -5,6 +7,10 @@ abstract class CacheService {
Future<DateTime?> getLastTimeUpdatedFromCache(); Future<DateTime?> getLastTimeUpdatedFromCache();
Future<void> setLastTimeUpdatedInCache({required String lasTimeUpdated}); Future<void> setLastTimeUpdatedInCache({required String lasTimeUpdated});
Future<void> setLastTimeLogsCleared({required int lastTimeCleared});
Future<DateTime?> getLastTimeLogsCleared();
} }
class CacheServiceImp implements CacheService { class CacheServiceImp implements CacheService {
@ -14,10 +20,8 @@ class CacheServiceImp implements CacheService {
@override @override
Future<DateTime?> getLastTimeUpdatedFromCache() async { Future<DateTime?> getLastTimeUpdatedFromCache() async {
final SharedPreferences prefs = await SharedPreferences.getInstance(); if (preferencesInstance.containsKey(CacheConstants.lastTimeUpdated)) {
String? lastTimeUpdated = preferencesInstance.getString(CacheConstants.lastTimeUpdated);
if (prefs.containsKey(CacheConstants.lastTimeUpdated)) {
String? lastTimeUpdated = prefs.getString(CacheConstants.lastTimeUpdated);
DateTime currentLastTimeUpdated = DateTime.fromMillisecondsSinceEpoch(int.parse(lastTimeUpdated!)); DateTime currentLastTimeUpdated = DateTime.fromMillisecondsSinceEpoch(int.parse(lastTimeUpdated!));
return currentLastTimeUpdated; return currentLastTimeUpdated;
} else { } else {
@ -29,4 +33,20 @@ class CacheServiceImp implements CacheService {
Future<void> setLastTimeUpdatedInCache({required String lasTimeUpdated}) async { Future<void> setLastTimeUpdatedInCache({required String lasTimeUpdated}) async {
await preferencesInstance.setString(CacheConstants.lastTimeUpdated, lasTimeUpdated); await preferencesInstance.setString(CacheConstants.lastTimeUpdated, lasTimeUpdated);
} }
@override
Future<DateTime?> getLastTimeLogsCleared() async {
if (preferencesInstance.containsKey(CacheConstants.lastTimeUpdated)) {
String? lastTimeUpdated = preferencesInstance.getString(CacheConstants.lastTimeUpdated);
DateTime currentLastTimeUpdated = DateTime.fromMillisecondsSinceEpoch(int.parse(lastTimeUpdated!));
return currentLastTimeUpdated;
} else {
return null;
}
}
@override
Future<void> setLastTimeLogsCleared({required int lastTimeCleared}) async {
await preferencesInstance.setInt(CacheConstants.lastTimeUpdated, lastTimeCleared);
}
} }

@ -1,12 +1,15 @@
import 'dart:io'; import 'dart:io';
import 'package:hmg_qline/config/dependency_injection.dart';
import 'package:hmg_qline/constants/app_constants.dart'; import 'package:hmg_qline/constants/app_constants.dart';
import 'package:hmg_qline/services/cache_service.dart';
import 'package:hmg_qline/utilities/enums.dart'; import 'package:hmg_qline/utilities/enums.dart';
import 'package:hmg_qline/view_models/screen_config_view_model.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
abstract class LoggerService { abstract class LoggerService {
Future<void> logToFile(String message, {LogTypeEnum type = LogTypeEnum.data}); Future<void> logToFile({required String message, required LogTypeEnum type, required String source});
Future<void> clearLogs(); Future<void> clearLogs();
@ -21,10 +24,10 @@ class LoggerServiceImp implements LoggerService {
LoggerServiceImp({required this.logger}); LoggerServiceImp({required this.logger});
@override @override
Future<void> logToFile(String message, {LogTypeEnum type = LogTypeEnum.data}) async { Future<void> logToFile({required String message, required LogTypeEnum type, required String source}) async {
try { try {
final timestamp = DateFormat('yyyy-MM-dd hh:mm:ss a').format(DateTime.now()); final timestamp = DateFormat('yyyy-MM-dd hh:mm:ss a').format(DateTime.now());
final formattedMessage = "[$timestamp] ${type.name.toUpperCase()}: $message"; final formattedMessage = "[$timestamp] [SOURCE: $source] ${type.name.toUpperCase()}: $message";
final dir = await getApplicationDocumentsDirectory(); final dir = await getApplicationDocumentsDirectory();
final logDir = Directory('${dir.path}/logs'); final logDir = Directory('${dir.path}/logs');
@ -35,9 +38,18 @@ class LoggerServiceImp implements LoggerService {
final logFileName = type == LogTypeEnum.error ? AppStrings.errorLogsFileName : AppStrings.dataLogsFileName; final logFileName = type == LogTypeEnum.error ? AppStrings.errorLogsFileName : AppStrings.dataLogsFileName;
final file = File('${logDir.path}/$logFileName'); final file = File('${logDir.path}/$logFileName');
ScreenConfigViewModel screenConfigViewModel = getIt.get<ScreenConfigViewModel>();
CacheService cacheService = getIt.get<CacheService>();
final lastLogsClearedAt = screenConfigViewModel.lastTimeLogsCleared;
final now = DateTime.now();
if (lastLogsClearedAt != null && now.difference(lastLogsClearedAt).inHours >= AppConstants.clearLogsHoursThreshold) {
await file.writeAsString('');
getIt.get<ScreenConfigViewModel>().lastTimeLogsCleared = now;
cacheService.setLastTimeLogsCleared(lastTimeCleared: now.millisecondsSinceEpoch);
}
await file.writeAsString("$formattedMessage\n", mode: FileMode.append); await file.writeAsString("$formattedMessage\n", mode: FileMode.append);
} catch (e) { } catch (e) {
logger.i('Logging failed: $e'); logger.e('Logging failed: $e');
} }
} }

@ -22,7 +22,7 @@ class NativeMethodChannelServiceImp implements NativeMethodChannelService {
await platform.invokeMethod(AppStrings.openAppNativeFunctionName); await platform.invokeMethod(AppStrings.openAppNativeFunctionName);
} catch (e) { } catch (e) {
loggerService.logError("Error launching app: $e"); loggerService.logError("Error launching app: $e");
loggerService.logToFile("Error launching app: $e", type: LogTypeEnum.error); loggerService.logToFile(message: "Error launching app: $e", source: "reopenApp -> native_method_handler.dart ", type: LogTypeEnum.error);
} }
} }
@ -32,7 +32,7 @@ class NativeMethodChannelServiceImp implements NativeMethodChannelService {
await Restart.restartApp(); await Restart.restartApp();
} catch (e) { } catch (e) {
loggerService.logError("Error restarting App : $e"); loggerService.logError("Error restarting App : $e");
loggerService.logToFile("Error restarting App : $e", type: LogTypeEnum.error); loggerService.logToFile(message: "Error restarting app: $e", source: "restartApp -> native_method_handler.dart ", type: LogTypeEnum.error);
} }
} }
} }

@ -58,7 +58,7 @@ class QueuingViewModel extends ChangeNotifier {
} }
Future<void> onHubConfigCall(var response) async { Future<void> onHubConfigCall(var response) async {
loggerService.logToFile(response.toString(), type: LogTypeEnum.data); loggerService.logToFile(message: response.toString(), source: "onHubConfigCall -> queueing_view_model.dart ", type: LogTypeEnum.data);
if (response != null && response.isNotEmpty) { if (response != null && response.isNotEmpty) {
var data = response.first['data']; var data = response.first['data'];
@ -76,7 +76,7 @@ class QueuingViewModel extends ChangeNotifier {
} }
Future<void> onHubTicketCall(List<Object?>? response) async { Future<void> onHubTicketCall(List<Object?>? response) async {
loggerService.logToFile(response.toString(), type: LogTypeEnum.data); loggerService.logToFile(message: response.toString(), source: "onHubTicketCall -> queueing_view_model.dart ", type: LogTypeEnum.data);
log("onHubTicketCall: $response"); log("onHubTicketCall: $response");
@ -89,7 +89,7 @@ class QueuingViewModel extends ChangeNotifier {
Future<void> onHubReconnected(var response) async { Future<void> onHubReconnected(var response) async {
log("onHubConnected: $response"); log("onHubConnected: $response");
loggerService.logToFile("onHubConnected", type: LogTypeEnum.data); loggerService.logToFile(message: response.toString(), source: "onHubReconnected -> queueing_view_model.dart ", type: LogTypeEnum.data);
ScreenConfigViewModel screenConfigViewModel = getIt.get<ScreenConfigViewModel>(); ScreenConfigViewModel screenConfigViewModel = getIt.get<ScreenConfigViewModel>();
screenConfigViewModel.updateIsHubConnected(true); screenConfigViewModel.updateIsHubConnected(true);
@ -98,7 +98,7 @@ class QueuingViewModel extends ChangeNotifier {
Future<void> onHubDisconnected(var response) async { Future<void> onHubDisconnected(var response) async {
log("onHubDisconnected: $response"); log("onHubDisconnected: $response");
loggerService.logToFile("onHubDisconnected", type: LogTypeEnum.data); loggerService.logToFile(message: response.toString(), source: "onHubDisconnected -> queueing_view_model.dart ", type: LogTypeEnum.data);
ScreenConfigViewModel screenConfigViewModel = getIt.get<ScreenConfigViewModel>(); ScreenConfigViewModel screenConfigViewModel = getIt.get<ScreenConfigViewModel>();
screenConfigViewModel.updateIsHubConnected(false); screenConfigViewModel.updateIsHubConnected(false);

@ -43,16 +43,17 @@ class ScreenConfigViewModel extends ChangeNotifier {
Future<void> initializeScreenConfigVM() async { Future<void> initializeScreenConfigVM() async {
await getGlobalConfigurationsByIP(); await getGlobalConfigurationsByIP();
await getLastTimeUpdatedFromCache(); await getLastTimeUpdatedFromCache();
await getLastTimeLogsClearedFromCache();
listenNetworkConnectivity(); listenNetworkConnectivity();
getTheWidgetsConfigurationsEveryMidnight(); getTheWidgetsConfigurationsEveryMidnight();
} }
Future<void> onAppResumed() async { Future<void> onAppResumed() async {
loggerService.logToFile("[didChangeAppLifecycleState] : [onAppResumed]", type: LogTypeEnum.data); loggerService.logToFile(message: "[didChangeAppLifecycleState] : [onAppResumed]", source: "onAppResumed -> screen_config_view_model.dart", type: LogTypeEnum.data);
} }
Future<void> onAppPaused() async { Future<void> onAppPaused() async {
loggerService.logToFile("[didChangeAppLifecycleState] : [onAppPaused]", type: LogTypeEnum.data); loggerService.logToFile(message: "[didChangeAppLifecycleState] : [onAppPaused]", source: "onAppPaused -> screen_config_view_model.dart", type: LogTypeEnum.data);
// nativeMethodChannelService.reopenApp(); // nativeMethodChannelService.reopenApp();
nativeMethodChannelService.restartApp(); nativeMethodChannelService.restartApp();
@ -343,6 +344,15 @@ class ScreenConfigViewModel extends ChangeNotifier {
} }
} }
DateTime? lastTimeLogsCleared = DateTime.now();
Future<void> getLastTimeLogsClearedFromCache() async {
lastTimeLogsCleared = await cacheService.getLastTimeLogsCleared();
if (lastTimeLogsCleared == null) {
await cacheService.setLastTimeLogsCleared(lastTimeCleared: DateTime.now().millisecondsSinceEpoch).whenComplete(() => lastTimeLogsCleared = DateTime.now());
}
}
// *************************** KIOSK FUNCTIONS ************************* // *************************** KIOSK FUNCTIONS *************************
KioskScreenStateEnums kioskScreenStateEnum = KioskScreenStateEnums.languageState; KioskScreenStateEnums kioskScreenStateEnum = KioskScreenStateEnums.languageState;

Loading…
Cancel
Save