@@ -75,6 +75,7 @@ namespace {
7575 QByteArray rawResponse;
7676 QJsonValue json{QJsonValue::Undefined};
7777 std::optional<ApiError> error;
78+ QList<ApiExchange> exchanges;
7879 };
7980
8081 struct RequestTask {
@@ -87,6 +88,7 @@ namespace {
8788 SynthesisCategory category{SynthesisCategory::None};
8889 ApiVersion apiVersion{ApiVersion::V1 };
8990 int attempt{};
91+ QList<ApiExchange> exchanges;
9092 std::function<bool ()> isCanceled;
9193 std::function<void ()> reportStarted;
9294 std::function<void (const RawResponse &)> reportResponse;
@@ -239,6 +241,7 @@ namespace {
239241 QPointer<QNetworkReply> reply;
240242 QPointer<QTimer> timeoutTimer;
241243 QPointer<QTimer> retryTimer;
244+ QDateTime attemptStartedAt;
242245 bool timedOut{};
243246 };
244247
@@ -364,6 +367,7 @@ namespace {
364367 }
365368
366369 active.timedOut = false ;
370+ active.attemptStartedAt = QDateTime::currentDateTimeUtc ();
367371 auto request = networkRequest (*task);
368372 qCDebug (lcDsspApiClient) << " Sending DSSP API request"
369373 << " requestId=" << task->id
@@ -426,6 +430,7 @@ namespace {
426430 .toString ()
427431 .trimmed ();
428432 const auto retryAfter = reply->rawHeader (QByteArrayLiteral (" Retry-After" ));
433+ const auto url = reply->url ();
429434 const auto body = reply->readAll ();
430435 const auto rawJson = parseJsonBestEffort (body);
431436 reply->deleteLater ();
@@ -504,6 +509,23 @@ namespace {
504509 }
505510 }
506511
512+ ApiExchange exchange;
513+ exchange.requestId = task->id ;
514+ exchange.serviceInstanceId = task->service .id ;
515+ exchange.method = task->method ;
516+ exchange.url = url;
517+ exchange.attempt = task->attempt + 1 ;
518+ exchange.httpStatusCode = status;
519+ exchange.networkErrorCode = static_cast <int >(networkError);
520+ exchange.startedAt = active.attemptStartedAt ;
521+ exchange.finishedAt = QDateTime::currentDateTimeUtc ();
522+ exchange.requestBody = task->body ;
523+ exchange.responseBody = body;
524+ if (response.error )
525+ exchange.errorMessage = response.error ->message ;
526+ task->exchanges .append (std::move (exchange));
527+ response.exchanges = task->exchanges ;
528+
507529 const bool retryable = response.error
508530 && ((response.error ->isNetworkError ()
509531 && isRetryableNetworkError (static_cast <QNetworkReply::NetworkError>(
@@ -701,21 +723,24 @@ class ApiClient::Private {
701723
702724 ApiResult<T> result;
703725 if (response.error ) {
704- result = ApiResult<T>::failure (*response.error );
726+ result = ApiResult<T>::failure (*response.error , response. exchanges );
705727 } else {
706728 T value;
707729 QString parseError;
708730 if (!T::fromJson (response.json , value, &parseError)) {
709731 ApiError error;
710732 error.kind = ApiError::ResponseError;
711733 error.httpStatusCode = response.httpStatusCode ;
712- error.message = QObject::tr (" The synthesis service returned data that does not match the DSSP schema: %1." )
734+ error.message = QObject::tr (" The synthesis service returned data that does not match the DSSP schema: %1." )
713735 .arg (parseError);
714736 error.rawResponse = response.rawResponse ;
715737 error.rawJsonResponse = response.json ;
716- result = ApiResult<T>::failure (std::move (error));
738+ auto exchanges = response.exchanges ;
739+ if (!exchanges.isEmpty ())
740+ exchanges.last ().errorMessage = error.message ;
741+ result = ApiResult<T>::failure (std::move (error), std::move (exchanges));
717742 } else {
718- result = ApiResult<T>::success (std::move (value));
743+ result = ApiResult<T>::success (std::move (value), response. exchanges );
719744 }
720745 }
721746 futureInterface->reportResult (std::move (result));
0 commit comments