handle method
Processes a batch of buffered logs.
Logs added to retryBuffer are placed back at the front of the queue
and retried with the next batch.
Important
retryBuffer is the only way to keep a log. A throwing handle —
synchronously or through its future — does not retry the batch: the
error is routed to onError or the current zone, and every log not
already handed back is dropped. Wrap the failing work in a
try/catch and retryBuffer.addAll(logs) there.
Implementation
@override
Future<void> handle(List<Log> logs, List<Log> retryBuffer) async {
List<Log>? persistedLogs;
try {
await ready;
persistedLogs = [
for (final log in logs)
if (log.level >= minLevel) log,
];
if (_disabled) {
retryBuffer.addAll(persistedLogs);
return;
}
final encodedLogs = <_EncodedLog>[];
for (final log in persistedLogs) {
try {
encodedLogs.add((log: log, line: _codec.encode(log)));
} on Object catch (error, stackTrace) {
// A failure encoding one log (a throwing toString and the like)
// must not lose its neighbours in the batch.
_report(error, stackTrace);
encodedLogs.add((log: log, line: _encodeFallback(log, error)));
}
}
if (encodedLogs.isNotEmpty) {
final failure = await _write(encodedLogs);
if (failure != null) {
_rememberDurabilityFailure(failure.error, failure.stackTrace);
retryBuffer.addAll(failure.uncommittedLogs);
_report(failure.error, failure.stackTrace);
await _recoverAfterWriteError();
}
}
} on Object catch (error, stackTrace) {
_rememberDurabilityFailure(error, stackTrace);
if (retryBuffer.isEmpty && persistedLogs != null) {
retryBuffer.addAll(persistedLogs);
}
_report(error, stackTrace);
}
}