Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(generator): Add ParseErrorLogger #694

Merged

Conversation

Sadhorsephile
Copy link
Contributor

Reincarnation of #680 with fixed unit tests

Problem

Sometimes, the back-end changes the response structure unexpectedly. For example, our app expects this:

 {
    "id": "0",
    "name": "Name"
 }

but we get this instead:

{
    "id": 0,
    "name": "Name"
 }

Logging these discrepancies would be really useful. To make the logs as helpful as possible, we need to capture:

  • Request details (path, URI, params, etc.);
  • Parsing error details (we can use CheckedFromJsonException from json_serializable).

The most logical place for such logging is within the client.

Solution

Let's introduce a new entity - ParseErrorLogger :

import 'package:dio/dio.dart';

/// Base class for logging errors that occur during parsing of response data.
abstract class ParseErrorLogger {
  /// Logs an error that occurred during parsing of response data.
  /// 
  /// - [error] is the error that occurred.
  /// - [stackTrace] is the stack trace of the error.
  /// - [options] are the options that were used to make the request.
  void logError(Object error, StackTrace stackTrace, RequestOptions options);
}

This entity can be injected into our client:

import 'package:dio/dio.dart';
import 'package:retrofit/retrofit.dart';

part 'rest_client.g.dart';

@RestApi()
abstract class RestClient {
  /// API creation factory using [Dio].
  factory RestClient(
    Dio dio, {
    String baseUrl,
    ParseErrorLogger? errorLogger,
  }) = _RestClient;

  @GET('')
  Future<SomeDto> someRequest();
}

And this entity will be called if parsing fails.

For example, this is rest_client.g.dart. As shown in the After example, errorLogger is called if there are any issues with parsing:

Before After
  @override
  Future<SomeDto> someRequest() async {
    const _extra = <String, dynamic>{};
    final queryParameters = <String, dynamic>{};
    final _headers = <String, dynamic>{};
    final Map<String, dynamic>? _data = null;
    final _result = await _dio.fetch<Map<String, dynamic>>(_setStreamType<SomeDto>(Options(
      method: 'GET',
      headers: _headers,
      extra: _extra,
    )
        .compose(
          _dio.options,
          '',
          queryParameters: queryParameters,
          data: _data,
        )
        .copyWith(
            baseUrl: _combineBaseUrls(
          _dio.options.baseUrl,
          baseUrl,
        ))));
    final value = SomeDto.fromJson(_result.data!);
    return value;
  }
  @override
  Future<SomeDto> someRequest() async {
    final _extra = <String, dynamic>{};
    final queryParameters = <String, dynamic>{};
    final _headers = <String, dynamic>{};
    const Map<String, dynamic>? _data = null;
    final options = _setStreamType<SomeDto>(Options(
      method: 'GET',
      headers: _headers,
      extra: _extra,
    )
        .compose(
          _dio.options,
          '',
          queryParameters: queryParameters,
          data: _data,
        )
        .copyWith(
            baseUrl: _combineBaseUrls(
          _dio.options.baseUrl,
          baseUrl,
        )));
    final _result = await _dio.fetch<Map<String, dynamic>>(options);
    late SomeDto value;
    try {
      value = SomeDto.fromJson(_result.data!);
    } on Object catch (e, s) {
      errorLogger?.logError(e, s, options);
      rethrow;
    }
    return value;
  }

@Sadhorsephile
Copy link
Contributor Author

@trevorwang Hi! I fixed unit tests and now PR is ready to be merged

@trevorwang trevorwang merged commit 426e6d8 into trevorwang:master Aug 13, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants