|
21 | 21 | import android.view.LayoutInflater; |
22 | 22 | import android.view.View; |
23 | 23 | import android.view.ViewGroup; |
| 24 | +import android.widget.Toast; |
24 | 25 |
|
25 | 26 | import com.example.vu.android.MyApplication; |
26 | 27 | import org.jetbrains.annotations.NotNull; |
|
38 | 39 | import java.util.List; |
39 | 40 |
|
40 | 41 | import io.sentry.Attachment; |
| 42 | +import io.sentry.Breadcrumb; |
41 | 43 | import io.sentry.ISpan; |
42 | 44 | import io.sentry.ITransaction; |
43 | 45 | import io.sentry.Sentry; |
| 46 | +import io.sentry.SentryLevel; |
44 | 47 | import io.sentry.SpanStatus; |
45 | 48 |
|
46 | 49 | import okhttp3.Call; |
@@ -362,32 +365,38 @@ public void checkout() { |
362 | 365 |
|
363 | 366 | @Override |
364 | 367 | public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { |
365 | | - progressDialog.dismiss(); |
366 | 368 | boolean success = response.isSuccessful(); |
| 369 | + int statusCode = response.code(); |
367 | 370 | response.close(); |
368 | | - if (!success) { |
369 | | - Log.w("checkout", "response failed"); |
370 | | - runOnUiThread(new Runnable() { |
371 | | - @Override |
372 | | - public void run() { |
373 | | - progressDialog.dismiss(); |
374 | | - |
375 | | - processDeliveryItem(checkoutTransaction); |
376 | | - |
| 371 | + runOnUiThread(new Runnable() { |
| 372 | + @Override |
| 373 | + public void run() { |
| 374 | + progressDialog.dismiss(); |
| 375 | + if (success) { |
| 376 | + processDeliveryItem(checkoutTransaction, selectedStoreItems); |
| 377 | + checkoutTransaction.finish(SpanStatus.OK); |
| 378 | + } else { |
| 379 | + Log.w("checkout", "response failed with HTTP " + statusCode); |
| 380 | + reportCheckoutFailure("Checkout request failed with HTTP " + statusCode); |
377 | 381 | checkoutTransaction.finish(SpanStatus.INTERNAL_ERROR); |
378 | 382 | } |
379 | | - }); |
380 | | - } |
| 383 | + } |
| 384 | + }); |
381 | 385 | } |
382 | 386 |
|
383 | 387 | @Override |
384 | 388 | public void onFailure(@NotNull Call call, @NotNull IOException e) { |
385 | | - progressDialog.dismiss(); |
| 389 | + Log.e("checkout", "checkout failed", e); |
386 | 390 | Sentry.captureException(e); |
387 | 391 |
|
388 | | - processDeliveryItem(checkoutTransaction); |
389 | | - checkoutTransaction.finish(SpanStatus.INTERNAL_ERROR); |
390 | | - Log.e("checkout", "checkout failed"); |
| 392 | + runOnUiThread(new Runnable() { |
| 393 | + @Override |
| 394 | + public void run() { |
| 395 | + progressDialog.dismiss(); |
| 396 | + reportCheckoutFailure("Checkout request failed: " + e.getMessage()); |
| 397 | + checkoutTransaction.finish(SpanStatus.INTERNAL_ERROR); |
| 398 | + } |
| 399 | + }); |
391 | 400 | } |
392 | 401 | }); |
393 | 402 | Log.i("checkout", "<<< checkout"); |
@@ -430,22 +439,46 @@ private JSONObject buildJSONPostData(List<StoreItem> selectedStoreItems) { |
430 | 439 | return postBody; |
431 | 440 | } |
432 | 441 |
|
433 | | - private void processDeliveryItem(ITransaction checkoutTransaction) { |
| 442 | + /** |
| 443 | + * Notifies the user that the checkout could not be completed and leaves a breadcrumb with the |
| 444 | + * actual reason, so the failure can be diagnosed without reporting a misleading error. |
| 445 | + */ |
| 446 | + private void reportCheckoutFailure(String reason) { |
| 447 | + Breadcrumb breadcrumb = new Breadcrumb(); |
| 448 | + breadcrumb.setCategory("checkout"); |
| 449 | + breadcrumb.setMessage(reason); |
| 450 | + breadcrumb.setLevel(SentryLevel.ERROR); |
| 451 | + Sentry.addBreadcrumb(breadcrumb); |
| 452 | + |
| 453 | + Sentry.metrics().count("checkout.failed"); |
| 454 | + |
| 455 | + Toast.makeText(MyApplication.appContext, R.string.checkout_failed, Toast.LENGTH_LONG).show(); |
| 456 | + } |
| 457 | + |
| 458 | + /** |
| 459 | + * Starts the delivery workflow for the items that were successfully checked out. |
| 460 | + */ |
| 461 | + private void processDeliveryItem(ITransaction checkoutTransaction, List<StoreItem> deliveryItems) { |
434 | 462 | Log.i("processDeliveryItem", "processDeliveryItem >>>"); |
435 | 463 | ISpan processDeliverySpan = checkoutTransaction.startChild("task", "process delivery"); |
436 | 464 |
|
437 | 465 | try { |
438 | | - throw new MainFragment.BackendAPIException("Failed to init delivery workflow"); |
| 466 | + if (deliveryItems.isEmpty()) { |
| 467 | + throw new MainFragment.BackendAPIException("Failed to init delivery workflow: no items to deliver"); |
| 468 | + } |
| 469 | + |
| 470 | + for (StoreItem item : deliveryItems) { |
| 471 | + Log.d("processDeliveryItem", "scheduling delivery for " + item.getName() |
| 472 | + + " (qty " + item.getQuantity() + ")"); |
| 473 | + } |
| 474 | + processDeliverySpan.setStatus(SpanStatus.OK); |
439 | 475 | } catch (Exception e) { |
440 | 476 | Log.e("processDeliveryItem", e.getMessage()); |
441 | 477 | processDeliverySpan.setThrowable(e); |
442 | 478 | processDeliverySpan.setStatus(SpanStatus.INTERNAL_ERROR); |
443 | 479 | Sentry.captureException(e); |
444 | 480 | } |
445 | 481 |
|
446 | | - if (processDeliverySpan.getStatus() != SpanStatus.INTERNAL_ERROR) { |
447 | | - processDeliverySpan.setStatus(SpanStatus.OK); |
448 | | - } |
449 | 482 | processDeliverySpan.finish(); |
450 | 483 | Log.i("processDeliveryItem", "<<< processDeliveryItem"); |
451 | 484 | } |
|
0 commit comments