flex_logger_isolate
Log from Dart isolates to the main isolate’s FlexLogger so all observers (console, file, Sentry) see worker logs.
Contents
Features
- Isolate → main – Log from worker isolates; messages forwarded to main isolate's FlexLogger
- All Log Levels - Support for debug, info, success, warning, error, and critical logs
- logCustom – From isolates, level/message/error/stackTrace are sent and appear as Isolate*Log on main
- Provider pattern – IsolateLoggerProvider; optional extension so you don't pass the provider around
- Cleanup – Call disposeIsolate when done; Finalizer closes ports and logs a warning if forgotten
- Output – Isolate logs use
tagin formattedTitle (e.g.worker-1DEBUG)
Installation
Add this to your package's pubspec.yaml file:
dependencies:
flex_logger: ^1.0.0
flex_logger_isolate: ^1.0.0
Then run:
flutter pub get
Usage
Basic Setup
Add IsolateLoggerProvider to FlexLogger, then use the extension so you don't need to pass the provider around:
import 'dart:isolate';
import 'package:flex_logger/flex_logger.dart';
import 'package:flex_logger_isolate/flex_logger_isolate.dart';
import 'package:flex_logger_console/flex_logger_console.dart';
void main() async {
FlexLogger.instance.configure(
providers: [
ConsoleLoggerProvider(),
IsolateLoggerProvider(),
],
);
await FlexLogger.instance.initialize();
final sendPort = FlexLogger.instance.initializeIsolate('worker-1');
await Isolate.spawn(workerEntryPoint, sendPort);
// When worker is done
FlexLogger.instance.disposeIsolate('worker-1');
}
void workerEntryPoint(SendPort sendPort) {
final logger = IsolateLogger(tag: 'worker-1', sendPort: sendPort);
logger.info('Worker started');
try {
performHeavyComputation();
logger.success('Computation completed');
} catch (e, st) {
logger.error('Computation failed', e, st);
}
}
Advanced Usage
Multiple Isolates
for (int i = 0; i < 4; i++) {
final sendPort = FlexLogger.instance.initializeIsolate('worker-$i');
await Isolate.spawn(workerEntryPoint, sendPort);
}
void workerEntryPoint(SendPort sendPort) {
// Pass tag via a record/list if you need dynamic id; here use a fixed tag for simplicity
final logger = IsolateLogger(tag: 'worker', sendPort: sendPort);
logger.info('Worker started');
}
// When done: FlexLogger.instance.disposeIsolate('worker-$i') for each
logCustom from isolate
IsolateLogger.logCustom(FlexLog) sends the log's level, message, error, and stackTrace to the main isolate. The main side receives an Isolate*Log (e.g. IsolateInfoLog), not the custom type, because only simple data crosses the isolate boundary.
void workerEntryPoint(SendPort sendPort) {
final logger = IsolateLogger(tag: 'processor', sendPort: sendPort);
logger.logCustom(SomeCustomFlexLog('Processed 1000 records')); // Main sees IsolateInfoLog with same message/level
}
Monitoring active isolates
final provider = FlexLogger.instance.getProvider<IsolateLoggerProvider>();
if (provider != null) {
FlexLogger.instance.info('Active isolates: ${provider.activeIsolateCount}');
for (final id in provider.activeIsolateIds) {
FlexLogger.instance.debug('Active isolate: $id');
}
}
API Reference
IsolateLoggerProvider
Implements LoggerProvider. Creates one ReceivePort per isolate; logs received are forwarded with FlexLogger.instance.logCustom(...).
SendPort initializeIsolate(String isolateId); // returns SendPort to pass to Isolate.spawn
void disposeIsolate(String isolateId);
int get activeIsolateCount;
List<String> get activeIsolateIds;
Or use the extension on FlexLogger: FlexLogger.instance.initializeIsolate(id), FlexLogger.instance.disposeIsolate(id).
IsolateLogger
Logger for use inside worker isolates. Implements Logger.
IsolateLogger({
required String tag, // isolate identifier (e.g. 'worker-1')
required SendPort sendPort,
});
// Standard Logger methods
void debug(String message, [Object? error, StackTrace? stackTrace]);
void info(String message, [Object? error, StackTrace? stackTrace]);
void success(String message, [Object? error, StackTrace? stackTrace]);
void warning(String message, [Object? error, StackTrace? stackTrace]);
void error(String message, [Object? error, StackTrace? stackTrace]);
void critical(String message, [Object? error, StackTrace? stackTrace]);
void log(String message, { FlexLogLevel level = FlexLogLevel.info, Object? error, StackTrace? stackTrace });
void logCustom(FlexLog log); // sends level/message/error/stackTrace; main receives Isolate*Log
How it works
- Main isolate:
IsolateLoggerProvidercreates aReceivePortper isolate and returns itsSendPort. - Spawn: You pass that
SendPortto the worker viaIsolate.spawn(entryPoint, sendPort). - Worker:
IsolateLogger(tag: 'worker-1', sendPort: sendPort)sendsIsolateLogmessages (e.g.IsolateInfoLog) over the port. - Main: The provider receives messages and forwards them with
FlexLogger.instance.logCustom(message). - Observers: All configured observers (console, file, Sentry, etc.) see the logs; filtering is done there.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Libraries
- flex_logger_isolate
- Isolate logging integration for FlexLogger.