Skip to content

Commit

Permalink
Merge branch 'main' into feat/no-ref/search-and-filter
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexsunon authored May 23, 2024
2 parents 0027519 + 681ac15 commit dd1a4f7
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 35 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ jobs:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.19.2'
channel: 'stable'
channel: stable
flutter-version: 3.22.0
- run: flutter --version
- name: Dart Apply Fixes (if this fails, run `dart fix --apply` locally)
run: dart fix --apply; git diff --exit-code
Expand Down
38 changes: 19 additions & 19 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,34 +95,34 @@ packages:
dependency: transitive
description:
name: intl
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev"
source: hosted
version: "0.18.1"
version: "0.19.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.1"
lints:
dependency: transitive
description:
Expand All @@ -135,17 +135,17 @@ packages:
dependency: transitive
description:
name: logger
sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac"
sha256: af05cc8714f356fd1f3888fb6741cbe9fbe25cdb6eedbab80e1a6db21047d4a4
url: "https://pub.dev"
source: hosted
version: "2.0.2+1"
version: "2.3.0"
logman:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.0.14"
version: "0.0.17"
matcher:
dependency: transitive
description:
Expand All @@ -166,10 +166,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
version: "1.12.0"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -227,10 +227,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
version: "0.7.0"
typed_data:
dependency: transitive
description:
Expand All @@ -251,10 +251,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "13.0.0"
version: "14.2.1"
sdks:
dart: ">=3.2.0 <4.0.0"
flutter: ">=1.17.0"
dart: ">=3.3.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
142 changes: 139 additions & 3 deletions lib/src/logman.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,136 @@
import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:logger/logger.dart';
import 'package:logman/logman.dart';
import 'package:logman/src/presentation/presentation.dart';

/// A logging utility class for Flutter applications.
/// It supports various types of logs including simple logs, navigation, and network logs.
/// This class uses the Singleton pattern to ensure a single instance is used throughout the application.
/// It supports various types of logs including simple logs, navigation,
/// and network logs.
///
/// This class uses the Singleton pattern to ensure a single instance
/// is used throughout the application.
class Logman {
/// Logger instance for internal logging.
///
/// This logger is used to log errors, warnings, and general information
/// within the `Logman` class.
late final Logger _logger;

/// Private constructor for `Logman`, implementing the Singleton pattern.
///
/// This constructor initializes the internal logger and starts the rotation
/// timer for log maintenance. It should be called only once and is not
/// meant to be used directly. Access the singleton instance via `Logman.instance`.
Logman._internal() {
_logger = Logger();
_startRotationTimer();
}

/// Whether logs should be printed to the console.
///
/// If `true`, logs are printed to the console using the internal logger.
/// This can be toggled to disable console logging for production.
bool printLogs = true;

/// Maximum duration for which logs should be retained in memory.
///
/// Any log older than this duration will be removed during log rotation.
Duration? maxLogLifetime;

/// Maximum number of logs that should be retained in memory.
///
/// If the number of logs exceeds this count, older logs will be removed
/// during log rotation.
int? maxLogCount;

/// Timer instance used for scheduling periodic log rotations.
///
/// This timer triggers `_rotateRecords` at the interval defined by `rotationInterval`.
Timer? _rotationTimer;

/// Duration between consecutive log rotation executions.
///
/// This interval defines how often `_rotateRecords` is called to remove
/// outdated logs and control the total log count.
Duration rotationInterval = const Duration(seconds: 30);

/// The single public instance of Logman.
static final Logman instance = Logman._internal();

/// Stores the list of log records currently retained in memory.
///
/// This is a `ValueNotifier` that notifies listeners whenever the log
/// records are updated. The logs are retained in a list, which is managed
/// through log rotation methods like `_rotateRecords`.
/// Notes:
/// - The list of log records is constrained by `maxLogLifetime` and `maxLogCount`,
/// meaning older or excessive logs are removed during log rotation.
/// - Use `ValueNotifier<List<LogmanRecord>>` to efficiently notify listeners
/// of changes to the logs.
final _records = ValueNotifier(<LogmanRecord>[]);

/// Gets the current list of log records.
ValueNotifier<List<LogmanRecord>> get records => _records;

void _addRecord(LogmanRecord record) =>
/// Starts a periodic timer that triggers log rotation at a specified interval.
///
/// The method cancels any existing timer before starting a new one, ensuring that
/// only one timer is running. The timer invokes `_rotateRecords` at each interval
/// to enforce log retention policies, such as `maxLogLifetime` and `maxLogCount`.
void _startRotationTimer() {
_rotationTimer?.cancel(); // Cancel any existing timer
_rotationTimer = Timer.periodic(rotationInterval, (timer) {
_rotateRecords();
});
}

/// Adds a new log record to the log list.
///
/// This method appends a new log record to `_records`. It also explicitly calls
/// `_rotateRecords` to ensure that the log list adheres to the defined log
/// retention policies (like `maxLogLifetime` and `maxLogCount`).
///
/// Parameters:
/// - `record`: The `LogmanRecord` instance representing the new log entry to add.
void _addRecord(LogmanRecord record) {
try {
_records.value = [..._records.value, record];
_rotateRecords();
} catch (e) {
_logger.e(e.toString());
}
}

/// Rotates the log records by enforcing the maximum log lifetime and count.
///
/// This method performs the following operations:
/// 1. Filters the existing log records to retain only those that were created
/// within the defined `maxLogLifetime`.
/// 2. Trims the list of remaining records to ensure that it does not exceed
/// the `maxLogCount` limit, keeping only the most recent records.
///
/// The resulting list of filtered records replaces the current log record list,
/// thus effectively managing memory usage.
void _rotateRecords() {
final now = DateTime.now();
var newRecords = _records.value;

// Check if maxLogLifetime is not null before filtering by dateTime difference
if (maxLogLifetime != null) {
newRecords = newRecords.where((record) {
return now.difference(record.dateTime) < maxLogLifetime!;
}).toList();
}

// Check if maxLogCount is not null before limiting the number of records
if (maxLogCount != null && newRecords.length > maxLogCount!) {
newRecords = newRecords.sublist(newRecords.length - maxLogCount!);
}

_records.value = newRecords;
}

/// Records a simple log message.
void info(String message) {
Expand Down Expand Up @@ -93,16 +199,41 @@ class Logman {
///
/// [button] is optional, the default button will be displayed if
/// it's not giving
///
/// [debugPage] is also optional, you can see an example of this
/// in the example app
///
/// [printLogs] is optional and true by default, if set to false,
/// logs will not be printed
///
/// [showOverlay] is optional and true by default, if set to false,
/// the overlay will not be displayed
///
/// [maxLogLifetime] is optional, it defines the maximum lifetime
/// of a single log record
///
/// [maxLogCount] is optional, it defines the maximum number of
/// log records to keep
void attachOverlay({
required BuildContext context,
Widget? button,
Widget? debugPage,
bool printLogs = true,
bool showOverlay = true,
Duration? maxLogLifetime,
int? maxLogCount,
}) {
this.printLogs = printLogs;
if (maxLogLifetime != null) {
this.maxLogLifetime = maxLogLifetime;

if (maxLogLifetime < rotationInterval) {
rotationInterval = maxLogLifetime;
_startRotationTimer();
}
}

if (maxLogCount != null) this.maxLogCount = maxLogCount;

if (!showOverlay) return;

Expand All @@ -118,4 +249,9 @@ class Logman {
void removeOverlay() {
return LogmanOverlay.removeOverlay();
}

/// Stops the log rotation timer.
void stopTimer() {
_rotationTimer?.cancel();
}
}
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: logman
description: A simple yet powerful logging package for Flutter apps with an integrated UI and an optional debug page.
version: 0.0.14
version: 0.0.17
homepage: https://github.com/Sorcel-Tech/logman.dart

environment:
Expand All @@ -10,8 +10,8 @@ environment:
dependencies:
flutter:
sdk: flutter
intl: ^0.18.1
logger: ^2.0.2+1
intl: ^0.19.0
logger: ^2.3.0

dev_dependencies:
flutter_lints: ^2.0.0
Expand Down
Loading

0 comments on commit dd1a4f7

Please sign in to comment.