-
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: error reporting with logs (#45)
* feat: add ability to get logs file from ui * test: add unit test for log line parsing in logs_provider * refactor: update all logs to obfuscate sensitive information * feat: generate dynamic zip file name for logs export * feat: enhance logging in audiobook player and provider for better debugging * refactor: extract user display logic into UserBar widget for offline access of settings and logs * feat: add About section with app metadata and source code link in YouPage
- Loading branch information
Showing
44 changed files
with
861 additions
and
176 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 |
---|---|---|
@@ -1,28 +1,28 @@ | ||
// does the initial setup of the storage | ||
|
||
import 'dart:io'; | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:hive/hive.dart'; | ||
import 'package:path/path.dart' as p; | ||
import 'package:path_provider/path_provider.dart'; | ||
import 'package:vaani/main.dart'; | ||
import 'package:vaani/settings/constants.dart'; | ||
|
||
import 'register_models.dart'; | ||
|
||
// does the initial setup of the storage | ||
Future initStorage() async { | ||
final dir = await getApplicationDocumentsDirectory(); | ||
|
||
// use vaani as the directory for hive | ||
final storageDir = Directory(p.join( | ||
dir.path, | ||
final storageDir = Directory( | ||
p.join( | ||
dir.path, | ||
AppMetadata.appNameLowerCase, | ||
), | ||
); | ||
await storageDir.create(recursive: true); | ||
|
||
Hive.defaultDirectory = storageDir.path; | ||
debugPrint('Hive storage directory init: ${Hive.defaultDirectory}'); | ||
appLogger.config('Hive storage directory init: ${Hive.defaultDirectory}'); | ||
|
||
await registerModels(); | ||
} |
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
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
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,36 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:flutter/foundation.dart'; | ||
import 'package:logging/logging.dart'; | ||
import 'package:logging_appenders/logging_appenders.dart'; | ||
import 'package:path_provider/path_provider.dart'; | ||
import 'package:vaani/shared/extensions/duration_format.dart'; | ||
|
||
Future<String> getLoggingFilePath() async { | ||
final Directory directory = await getApplicationDocumentsDirectory(); | ||
return '${directory.path}/vaani.log'; | ||
} | ||
|
||
Future<void> initLogging() async { | ||
final formatter = const DefaultLogRecordFormatter(); | ||
if (kReleaseMode) { | ||
Logger.root.level = Level.INFO; // is also the default | ||
// Write to a file | ||
RotatingFileAppender( | ||
baseFilePath: await getLoggingFilePath(), | ||
formatter: formatter, | ||
).attachToLogger(Logger.root); | ||
} else { | ||
Logger.root.level = Level.FINE; // Capture all logs | ||
RotatingFileAppender( | ||
baseFilePath: await getLoggingFilePath(), | ||
formatter: formatter, | ||
).attachToLogger(Logger.root); | ||
Logger.root.onRecord.listen((record) { | ||
// Print log records to the console | ||
debugPrint( | ||
'${record.loggerName}: ${record.level.name}: ${record.time.time}: ${record.message}', | ||
); | ||
}); | ||
} | ||
} |
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,76 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:archive/archive_io.dart'; | ||
import 'package:logging/logging.dart'; | ||
import 'package:path_provider/path_provider.dart'; | ||
import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||
import 'package:vaani/features/logging/core/logger.dart'; | ||
|
||
part 'logs_provider.g.dart'; | ||
|
||
@riverpod | ||
class Logs extends _$Logs { | ||
@override | ||
Future<List<LogRecord>> build() async { | ||
final path = await getLoggingFilePath(); | ||
final file = File(path); | ||
if (!file.existsSync()) { | ||
return []; | ||
} | ||
final lines = await file.readAsLines(); | ||
return lines.map(parseLogLine).toList(); | ||
} | ||
|
||
Future<void> clear() async { | ||
final path = await getLoggingFilePath(); | ||
final file = File(path); | ||
await file.writeAsString(''); | ||
state = AsyncData([]); | ||
} | ||
|
||
Future<String> getZipFilePath() async { | ||
var encoder = ZipFileEncoder(); | ||
encoder.create(await generateZipFilePath()); | ||
encoder.addFile(File(await getLoggingFilePath())); | ||
encoder.close(); | ||
return encoder.zipPath; | ||
} | ||
} | ||
|
||
Future<String> generateZipFilePath() async { | ||
Directory appDocDirectory = await getTemporaryDirectory(); | ||
return '${appDocDirectory.path}/${generateZipFileName()}'; | ||
} | ||
|
||
String generateZipFileName() { | ||
return 'vaani-${DateTime.now().toIso8601String()}.zip'; | ||
} | ||
|
||
Level parseLevel(String level) { | ||
return Level.LEVELS | ||
.firstWhere((l) => l.name == level, orElse: () => Level.ALL); | ||
} | ||
|
||
LogRecord parseLogLine(String line) { | ||
// 2024-10-03 00:48:58.012400 INFO GoRouter - getting location for name: "logs" | ||
|
||
final RegExp logLineRegExp = RegExp( | ||
r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{6}) (\w+) (\w+) - (.+)', | ||
); | ||
|
||
final match = logLineRegExp.firstMatch(line); | ||
if (match == null) { | ||
// return as is | ||
return LogRecord(Level.ALL, line, 'Unknown'); | ||
} | ||
|
||
final timeString = match.group(1)!; | ||
final levelString = match.group(2)!; | ||
final loggerName = match.group(3)!; | ||
final message = match.group(4)!; | ||
|
||
final time = DateTime.parse(timeString); | ||
final level = parseLevel(levelString); | ||
|
||
return LogRecord(level, message, loggerName, time); | ||
} |
Oops, something went wrong.