diff --git a/src/Collections/TerminusCollection.php b/src/Collections/TerminusCollection.php index da2ffb2ea..33130314b 100644 --- a/src/Collections/TerminusCollection.php +++ b/src/Collections/TerminusCollection.php @@ -9,15 +9,18 @@ use Pantheon\Terminus\Models\TerminusModel; use Pantheon\Terminus\Request\RequestAwareInterface; use Pantheon\Terminus\Request\RequestAwareTrait; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; /** * Class TerminusCollection * @package Pantheon\Terminus\Collections */ -abstract class TerminusCollection implements ContainerAwareInterface, RequestAwareInterface +abstract class TerminusCollection implements ContainerAwareInterface, RequestAwareInterface, LoggerAwareInterface { use ContainerAwareTrait; use RequestAwareTrait; + use LoggerAwareTrait; /** * @var array @@ -91,6 +94,34 @@ public function all() public function fetch() { foreach ($this->getData() as $id => $model_data) { + if (!is_object($model_data)) { + // This should always be an object, however occasionally it is returning as a string + // We need more information about what it is and to handle the error + $model_data_str = print_r($model_data, true); + $error_maxlength = 250; + if (is_string($model_data_str) && strlen($model_data_str) > $error_maxlength) { + $model_data_str = substr($model_data_str, 0, $error_maxlength) . ' ...'; + } + $error_message = "Fetch failed {file}:{line} \$model_data expected as object but returned as {type}."; + $error_message .= "\nUnexpected value: {model_data_str}"; + $trace = debug_backtrace(); + $context = [ + 'file' => $trace[0]['file'], + 'line' => $trace[0]['line'], + 'type' => gettype($model_data), + 'model_data_str' => $model_data_str + ]; + + // verbose logging for debugging + $this->logger->debug($error_message, $context); + + // less information for more user-facing messages, but a problem has occurred and we're skipping this + // item so we should still surface a user-facing message + $this->logger->warning("Model data missing for {id}", ['id' => $id,]); + + // skip this item since it lacks useful data + continue; + } if (!isset($model_data->id)) { $model_data->id = $id; } diff --git a/src/Request/Request.php b/src/Request/Request.php index b045fd13b..b2525b8df 100755 --- a/src/Request/Request.php +++ b/src/Request/Request.php @@ -244,12 +244,21 @@ private function createRetryDecider(): callable } } + // Response can be null if there is a network disconnect. Get a different error message in that case. + if (is_object($response) && is_object($response->getBody()) && $response->getBody()->getContents() !== '') { + $error = $response->getBody()->getContents(); + } elseif (null !== $exception && '' != $exception->getMessage()) { + $error = $exception->getMessage(); + } else { + $error = "Undefined"; + } + $this->logger->error( "HTTP request {method} {uri} has failed with error {error}.", [ 'method' => $request->getMethod(), 'uri' => $request->getUri(), - 'error' => $response->getBody()->getContents(), + 'error' => $error, ] );