LogSpoolSink class final

Background-isolate sink that writes entries to spool.

Entries accepted since the last batch end go out as one file at batch end (LogSink.endBatch, reported by the root after each dispatch), on LogSink.flush and on LogSink.close. The file is written synchronously with fsync: a background isolate often exits right after its work (Isolate.run, FCM handler), and the entry must be on disk before the call that logged it returns.

How many entries share a file is decided by the background root's dispatch: with LogDispatchPolicy.synchronous each entry is dispatched in the logger call and goes out in its own file at once, which is the most reliable for an isolate that may be killed at any moment; with regular dispatch the entries of one event-loop turn share a file (at most LogDispatchPolicy.queueLimit per file: a fuller queue is dispatched in the call), and await logger.close() at the end of the work flushes the rest.

After writing a file, a notification is sent to notify (the main isolate's LogSpoolReceiver port; in Flutter it is looked up by name via lookupIsolateLogPort) so the main isolate picks the file up now rather than at next startup. The notification is only a signal: if the port is missing, closed, or its isolate has exited, the file is still imported later.

A write failure (no space, directory unavailable) goes to diagnostics and the batch is lost: there is nowhere to retry.

Future<void> onBackgroundMessage(RemoteMessage message) async {
  final logger = RootLogger(
    sinks: [LogSpoolSink(LogSpool(spoolDirectory), notify: lookupIsolateLogPort())],
    dispatch: LogDispatchPolicy.synchronous,
  )..finishStartup();
  logger.child(tags: {'fcm'}).log('Message received');
}
Inheritance

Constructors

LogSpoolSink(LogSpool spool, {SendPort? notify})

Properties

diagnostics → DiagnosticReporter
Where the sink reports its own failures. Set by the logger on attach (attach); before that, DiagnosticReporter.console.
no setterinherited
hashCode → int
The hash code for this object.
no setterinherited
isClosed → bool
Whether close has been called: from then on add throws.
no setterinherited
name → String
Sink name in library messages: in diagnostics (LogDiagnostic) and in the dropped-entries warnings that go into the log. Defaults to the class name, but in an --obfuscate build that is unreadable (minified:aB); the library's sinks return a constant string, and a custom sink should do the same.
no setteroverride
notify → SendPort?
Where to announce a new file; null means do not announce.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
spool → LogSpool
final

Methods

add(LogEntry entry) → void
Accepts an entry (onAdd). Throws StateError after close: logging into a closed sink is a shutdown-order bug, better seen than silently sent to a closed store. The RootLogger fan-out catches such errors and reports them to diagnostics.
inherited
attach(DiagnosticReporter diagnostics) → void
Tells the sink where to send reports of its own failures (diagnostics). Called by the logger on attach (RootLogger.addSink and the sinks from the root constructor); wrappers pass the channel to their inner sinks (onAttach). A repeated call replaces the channel: a sink reattached to another logger reports to it.
inherited
close() → Future<void>
Shuts the sink down: no new entries are accepted, then onClose delivers the accepted ones and releases resources. A repeated call closes nothing again and returns the result of the first.
inherited
endBatch() → void
Signals that a batch of entries has ended (onBatchEnd): RootLogger calls it after every queue dispatch, including dispatch inside the logger call (a fatal entry, flush, close). A sink that writes in batches (LogStoreSink) hands over what it accumulated here: everything the root dispatched at once goes as one batch, and a fatal entry goes together with what accumulated before it, before log returns. Does nothing after close.
inherited
flush() → Future<void>
Waits until accepted entries reach their destination (for example are persisted to the store) without closing the sink (onFlush). After close, waits for the closing to complete, which delivers everything accepted.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
onAdd(LogEntry entry) → void
Handles an accepted entry. Called only before close.
override
onAttach(DiagnosticReporter diagnostics) → void
Called from attach: pass diagnostics to inner sinks. Does nothing by default; DelegatingSink passes it to inner.
inherited
onBatchEnd() → void
Called from endBatch. Does nothing by default: for sinks that handle each entry in onAdd; wrappers (DelegatingSink) pass the end of batch to inner.
override
onClose() → Future<void>
Delivers accepted entries and releases resources (for example closes the store). Called once. Does nothing by default.
override
onFlush() → Future<void>
Waits for accepted entries to be delivered. Does nothing by default: for sinks that deliver entries immediately in onAdd.
override
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited