SDITools / adobeanalyticsr

R Client for Adobe Analytics API v2.0
Other
18 stars 9 forks source link

Combine request functions and handle errors better #134

Closed charlie-gallagher closed 2 years ago

charlie-gallagher commented 2 years ago

Summary

Refactored aw_call_data and aw_call_api into a single function. I also add a function called handle_api_errors(), which is a more useful error handler for 206 errors, and a more verbose handler of 400 type errors.

Comparison

Old Behavior

The old errors were less verbose, and incorrect metrics and dimensions were not explicitly reported.

Only the first component error was caught

For 206 errors, only the first component was reported:

aw_freeform_table(
  metrics = c("vsiits", "visitors"),                    # visits misspelled
  dimensions = c("Page"),                               # page mis-capitalized
  segmentId = c("all_Visits", "first_visit"),           # Two invalid segment IDs
  check_components = FALSE
)
## Error in aw_call_data(req_path = "reports/ranked", body = req, debug = debug, : 
##    The error code is unauthorized_segment - User does not have access to the requested segmentId: first_visit

Other errors were vague

API errors went through httr::stop_for_status(), and they were usually vague.

aw_freeform_table(
  segmentId = c(myseg = "all_Visits")     # In master, named segments form invalid JSON
)
## Error in aw_call_data(req_path = "reports/ranked", body = req, debug = debug, : 
##   Bad Request (HTTP 400).

By setting debug = TRUE, you could view the whole error message, but it will be surrounded by a lot of unnecessary text.

New Behavior

The error handling is more complex, but also more useful. For 206 errors, when multiple errors are thrown for a single request (e.g., you have two metrics with ID typos) all errors are reported. Error messages are matched to the offending components, removing guesswork.

Multiple component errors are handled together

aw_freeform_table(
  metrics = c("vsiits", "visitors"),                    # visits misspelled
  dimensions = c("Page"),                               # page mis-capitalized
  segmentId = c("all_Visits", "first_visit"),           # Two invalid segment IDs
  check_components = FALSE
)
## Error in handle_api_errors(resp = req, body = body) : 
## unauthorized_segment: User does not have access to the requested segmentId: first_visit
## unauthorized_segment: User does not have access to the requested segmentId: all_Visits
## unauthorized_dimension_global: User does not have access to the global dimension for this request: variables/Page

Sometimes with multiple errors, as here, the API doesn't return all of the errors. Notice that the API didn't say anything about the misspelled metric. This is the API, though -- handle_api_errors is displaying all of the errors it receives. When the metric error is the only error, it is caught as expected:

aw_freeform_table(
  metrics = c("vsiits", "visitors"),                    # visits misspelled
  check_components = FALSE
)

## Error in handle_api_errors(resp = req, body = body) : 
##    unauthorized_metric: User does not have access to the requested metric: metrics/vsiits

Invalid JSON errors (usually our fault) are handled verbosely

aw_freeform_table(
  segmentId = c(myseg = "all_Visits")     # In master, named segments form invalid JSON
)

## Error in handle_api_errors(resp = req, body = body) : 
## errorCode: invalid_json_input
## errorDescription: Invalid JSON. At least one field format is not recognized or
##   cannot be parsed. - Error caused by exceptionMessage=Cannot deserialize value
##   of type `[Lcom.adobe.analytics.modules.reports.model.ReportFilter;` from Object
##   value (token `JsonToken.START_OBJECT`)
##   at [Source:
##   (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream);
##   line: 1, column: 58] (through reference chain:
##   com.adobe.analytics.modules.reports.model.RankedRequest["globalFilters"])

Errors without extra message info fall through to httr::stop_for_status()

aw_call_api(
  "reports/ranked",
  body = "I am a malformed body",
  company_id = "audiag5"
)

## Error in aw_call_api("reports/ranked", body = "I am a malformed body", : 
##   Unsupported Media Type (HTTP 415).

Checklist