observeAsync<T> function
Future<T>
observeAsync<T>(
- Future<
T> operation(), { - void onSuccess(
- Duration elapsed,
- T result
- void onError(
- Duration elapsed,
- Object error,
- StackTrace stackTrace
Runs the async operation, measures its wall-clock duration, and reports
the outcome through the optional hooks, then returns the result (or rethrows
the operation's error after onError).
onSuccess receives the elapsed time and the result; onError receives the
elapsed time, the error, and its stack trace. The error is always rethrown
so the wrapper is transparent to callers.
Example:
await observeAsync(
() => repository.load(id),
onSuccess: (d, _) => log('load ok in ${d.inMilliseconds}ms'),
onError: (d, e, _) => log('load failed in ${d.inMilliseconds}ms: $e'),
);
Audited: 2026-06-12 11:26 EDT
Implementation
Future<T> observeAsync<T>(
Future<T> Function() operation, {
void Function(Duration elapsed, T result)? onSuccess,
void Function(Duration elapsed, Object error, StackTrace stackTrace)? onError,
}) async {
final Stopwatch stopwatch = Stopwatch()..start();
try {
final T result = await operation();
stopwatch.stop();
onSuccess?.call(stopwatch.elapsed, result);
return result;
} on Object catch (error, stackTrace) {
// Catch-all is intentional: an observability wrapper must time and report
// EVERY failure mode, then rethrow so it never changes the control flow.
stopwatch.stop();
onError?.call(stopwatch.elapsed, error, stackTrace);
rethrow;
}
}