diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 9a1ec45f2..3eafb3580 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -10,6 +10,7 @@ See the [Migration Guide][] for the complete breaking changes list.** - Fixes boundary inconsistency in `FormData.clone()`. - Support `FileAccessMode` in `Dio.download` and `Dio.downloadUri` to change download file opening mode - Fix `ListParam` equality by using the `DeepCollectionEquality`. +- Enables configuring the logging details of `DioException` globally and locally. ## 5.7.0 diff --git a/dio/lib/src/dio_exception.dart b/dio/lib/src/dio_exception.dart index 69aac43d0..6dcdc375c 100644 --- a/dio/lib/src/dio_exception.dart +++ b/dio/lib/src/dio_exception.dart @@ -1,5 +1,6 @@ import 'options.dart'; import 'response.dart'; +import 'utils.dart' show warningLog; /// Deprecated in favor of [DioExceptionType] and will be removed in future major versions. @Deprecated('Use DioExceptionType instead. This will be removed in 6.0.0') @@ -205,6 +206,14 @@ class DioException implements Exception { /// The error message that throws a [DioException]. final String? message; + /// Users can customize the content of [toString] when thrown. + static DioExceptionReadableStringBuilder readableStringBuilder = + defaultDioExceptionReadableStringBuilder; + + /// Each exception can be override with a customized builder or fallback to + /// the default [DioException.readableStringBuilder]. + DioExceptionReadableStringBuilder? stringBuilder; + /// Generate a new [DioException] by combining given values and original values. DioException copyWith({ RequestOptions? requestOptions, @@ -226,11 +235,12 @@ class DioException implements Exception { @override String toString() { - String msg = 'DioException [${type.toPrettyDescription()}]: $message'; - if (error != null) { - msg += '\nError: $error'; + try { + return stringBuilder?.call(this) ?? readableStringBuilder(this); + } catch (e, s) { + warningLog(e, s); + return defaultDioExceptionReadableStringBuilder(this); } - return msg; } /// Because of [ValidateStatus] we need to consider all status codes when @@ -278,3 +288,20 @@ class DioException implements Exception { return buffer.toString(); } } + +/// The readable string builder's signature of +/// [DioException.readableStringBuilder]. +typedef DioExceptionReadableStringBuilder = String Function(DioException e); + +/// The default implementation of building a readable string of [DioException]. +String defaultDioExceptionReadableStringBuilder(DioException e) { + final buffer = StringBuffer( + 'DioException [${e.type.toPrettyDescription()}]: ' + '${e.message}', + ); + if (e.error != null) { + buffer.writeln(); + buffer.write('Error: ${e.error}'); + } + return buffer.toString(); +} diff --git a/dio/lib/src/utils.dart b/dio/lib/src/utils.dart index 06d5aa94e..1a2e1d801 100644 --- a/dio/lib/src/utils.dart +++ b/dio/lib/src/utils.dart @@ -154,10 +154,10 @@ Map caseInsensitiveKeyMap([Map? value]) { } // TODO(Alex): Provide a configurable property on the Dio class once https://github.com/cfug/dio/discussions/1982 has made some progress. -void warningLog(String message, StackTrace stackTrace) { +void warningLog(Object message, StackTrace stackTrace) { if (!kReleaseMode) { dev.log( - message, + message.toString(), level: 900, name: '🔔 Dio', stackTrace: stackTrace, diff --git a/dio/test/exception_test.dart b/dio/test/exception_test.dart index bfc0f95d7..740ceb5dc 100644 --- a/dio/test/exception_test.dart +++ b/dio/test/exception_test.dart @@ -52,4 +52,34 @@ void main() { }, testOn: '!browser', ); + + test('DioExceptionReadableStringBuilder', () { + final requestOptions = RequestOptions(path: 'just/a/test', method: 'POST'); + final exception = DioException( + requestOptions: requestOptions, + response: Response(requestOptions: requestOptions), + error: 'test', + message: 'test message', + stackTrace: StackTrace.current, + ); + DioException.readableStringBuilder = (e) => 'Hey, Dio throws an exception: ' + '${e.requestOptions.path}, ' + '${e.requestOptions.method}, ' + '${e.type}, ' + '${e.error}, ' + '${e.stackTrace}, ' + '${e.message}'; + expect( + exception.toString(), + 'Hey, Dio throws an exception: ' + 'just/a/test, ' + 'POST, ' + 'DioExceptionType.unknown, ' + 'test, ' + '${exception.stackTrace}, ' + 'test message', + ); + exception.stringBuilder = (e) => 'Locally override: ${e.message}'; + expect(exception.toString(), 'Locally override: test message'); + }); }