isolates library

Logging from background isolates into the main isolate's root logger.

Two mechanisms for two situations:

  • LogSpool, LogSpoolSink, LogSpoolReceiver: the background isolate writes entries as files into a spool directory, the main isolate picks them up. For engine-started isolates (FCM handler, WorkManager) or ones that outlive the main isolate: the spool does not depend on whether a main isolate exists or its port is alive, and only the main isolate writes the store. The port here is only a "file appeared" notification.
  • IsolateLogSink, IsolateLogReceiver: entries go through a SendPort without persistence. For an isolate the sender owns and whose port it received at spawn: a worker the main isolate started logs into the main root, whose store stays in the main isolate with the viewer. A dead port loses entries silently, so this does not suit foreign isolates.

Separate from log_trail.dart because dart:isolate and dart:io are unavailable on web.

Classes

IsolateLogReceiver
Receives entries through a port (IsolateLogSink): each entry is passed to sink, usually the root logger's sink (RootLogger.asSink).
IsolateLogSink
Sink that passes entries to another isolate through port (IsolateLogReceiver.sendPort) without persisting them. There they go through the root logger alongside its own entries: same threshold, processors, sinks and store.
LogSpool
Spool of background-isolate entries: a directory where isolates started by the engine (FCM handler, WorkManager) or by the app write entry files (LogSpoolSink), and the main isolate picks them up (importInto, LogSpoolReceiver) and runs them through its root logger alongside its own entries.
LogSpoolReceiver
Receives entries from spool in the main isolate: imports into sink (usually RootLogger.asSink) on creation, on every notification to sendPort from LogSpoolSink, and on importNow.
LogSpoolSink
Background-isolate sink that writes entries to spool.