Improve oEmbed exception logging

Created on 14 May 2018, about 6 years ago
Updated 11 June 2024, 18 days ago

Problem/Motivation

There are several places in the oEmbed API that handle errors that may occur during the process of fetching or otherwise interacting with oEmbed resources, and these errors are either not logged at all, or logged in very general terms that will not help with troubleshooting. We should revisit these areas and improve the error handling.

This issue is spun off from #2831944-237: Implement media source plugin for remote video via oEmbed โ†’ , point #1.

Steps to reproduce

OEmbed errors occur in certain circumstances, such as when a use created a remote video media entity referring to a video which is restricted or otherwise not publicly accessible, or when the host of the video is not accessible.

Proposed resolution

- improve error messages logged so that the details of the failure can be better investigated
- improve feedback surfaced to the user (suggested in #28 here)

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

โœจ Feature request
Status

Needs work

Version

11.0 ๐Ÿ”ฅ

Component
Mediaย  โ†’

Last updated about 16 hours ago

Created by

๐Ÿ‡บ๐Ÿ‡ธUnited States phenaproxima Massachusetts

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States Kristen Pol Santa Cruz, CA, USA

    Can we also get another error message fixed with this patch?

    With this video https://www.youtube.com/watch?v=HmZKgaHa3Fg, I was getting this error:

    Could not retrieve the oEmbed resource.
    

    which doesn't have the exception message so isn't very helpful.

    This should be changed from:

        } catch (TransferException $e) {
          throw new ResourceException('Could not retrieve the oEmbed resource.', $url, [], $e);
        }
    

    to something like:

        catch (TransferException $e) {
          throw new ResourceException('Could not retrieve the oEmbed resource: ' . $e->getMessage(), $url, [], $e);
        }
    

    With the change, the mesage is:

    Could not retrieve the oEmbed resource: Client error: `GET https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=HmZKgaHa3Fg` resulted in a `401 Unauthorized` response: Unauthorized
    
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia pooja saraah Chennai

    Addressed the comment on #28
    Attached patch against Drupal 10.1.x

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Prem Suthar gujrat

    Try To Fix the #29 Patch Faild To Apply.

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    Great point @Kristen Pol in #28.
    I just came here to write the same. The current message "Could not retrieve the oEmbed resource" is very unclear and you have no good way to identify which oEmbed resource / entity causes the issue!

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    Just found this similar issue: ๐Ÿ› Don't display OEmbed error to anonymous visitors when resource stops being available Needs work
    Guess both should be solved together.

  • Status changed to Needs review about 1 year ago
  • last update about 1 year ago
    29,386 pass, 1 fail
  • ๐Ÿ‡ณ๐Ÿ‡ฟNew Zealand xurizaemon ลŒtepoti, Aotearoa ๐Ÿ

    #29 didn't apply, and #30 failed tests, so here's #25 reroll + #28.

  • last update about 1 year ago
    CI aborted
  • ๐Ÿ‡ณ๐Ÿ‡ฟNew Zealand xurizaemon ลŒtepoti, Aotearoa ๐Ÿ

    And an update for the change in error message.

  • ๐Ÿ‡ณ๐Ÿ‡ฟNew Zealand xurizaemon ลŒtepoti, Aotearoa ๐Ÿ

    Correcting interdiff.

  • last update about 1 year ago
    29,386 pass, 1 fail
  • ๐Ÿ‡ณ๐Ÿ‡ฟNew Zealand xurizaemon ลŒtepoti, Aotearoa ๐Ÿ

    Last try for today.

  • last update about 1 year ago
    29,388 pass
  • ๐Ÿ‡ณ๐Ÿ‡ฟNew Zealand xurizaemon ลŒtepoti, Aotearoa ๐Ÿ
  • Status changed to Needs work about 1 year ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Can the issue summary be updated please. started with the template.

    Also will need additional test coverage.

  • ๐Ÿ‡ณ๐Ÿ‡ฟNew Zealand xurizaemon ลŒtepoti, Aotearoa ๐Ÿ

    Updating IS from core template.

    I am open to NOT changing user facing messages if that permits us to land the original proposed task more readily. I'll add an alternative patch without the message and related test change so we have that option.

    Given ๐Ÿ› Don't display OEmbed error to anonymous visitors when resource stops being available Needs work it may be better to leave the exception surfacing to that issue.

    @smustgrave if we go that way, do you feel additional tests are required?

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Would need a test for the logs.

    The current test update is just checking for a ":" being added.

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    Re #41 I agree the user facing message might stay as-is, simply log the details. I think that's what you'd expect and is most safe.

  • last update about 1 year ago
    30,334 pass
  • Patch #39 applies on 9.5.x but results in the following error:

    Error: Call to undefined method GuzzleHttp\Exception\ClientException::getUrl() in Drupal\media\Plugin\Validation\Constraint\OEmbedResourceConstraintValidator->handleException() (line 142 of core/modules/media/src/Plugin/Validation/Constraint/OEmbedResourceConstraintValidator.php).
    
    Drupal\media\Plugin\Validation\Constraint\OEmbedResourceConstraintValidator->handleException(Object, 'The provided URL does not represent a valid oEmbed resource.') (Line: 120)
    Drupal\media\Plugin\Validation\Constraint\OEmbedResourceConstraintValidator->validate(Object, Object) (Line: 201)
    Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateConstraints(Object, '0000000000000a9f0000000000000000', Array) (Line: 153)
    Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateNode(Object) (Line: 163)
    Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateNode(Object, Array, 1) (Line: 105)
    Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validate(Object, NULL, NULL) (Line: 93)
    Drupal\Core\TypedData\Validation\RecursiveValidator->validate(Object) (Line: 132)
    Drupal\Core\TypedData\TypedData->validate() (Line: 489)
    Drupal\Core\Entity\ContentEntityBase->validate() (Line: 471)
    Drupal\media\Entity\Media->validate() (Line: 188)
    Drupal\Core\Entity\ContentEntityForm->validateForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 82)
    Drupal\Core\Form\FormValidator->executeValidateHandlers(Array, Object) (Line: 275)
    Drupal\Core\Form\FormValidator->doValidateForm(Array, Object, 'media_remote_video_add_form') (Line: 118)
    Drupal\Core\Form\FormValidator->validateForm('media_remote_video_add_form', Array, Object) (Line: 593)
    Drupal\Core\Form\FormBuilder->processForm('media_remote_video_add_form', Array, Object) (Line: 325)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
    Drupal\Core\Controller\FormController->getContentResult(Object, Object)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 169)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 153)
    Drupal\cryptolog\CryptologMiddleware->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
    Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
    
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    Needs work as of #45. One way might be to implement __toString() differently in the two exception classes and just call that instead of ->getUrl() and others.

    Another alternative would be to have two different handleException() function. Which way should we go?

  • last update about 1 year ago
    29,398 pass
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Grevil

    There seem to be further Exceptions like "ClientException", which do not have the url part implemented. I guess data would be enough for those exceptions, and we only add the url for when it is an ResourceException?

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    Re #47: Yes!

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Grevil

    I just wondered why "ClientException" is even handled by our "handleException" method, since we only catch "ResourceException" and "ProviderException".
    The problem is line 153 -> 154 in "/var/www/html/web/core/modules/media/src/Plugin/Validation/Constraint/OEmbedResourceConstraintValidator.php":

    [...]
       $this->logger->error($message, $context);
       $e = $e->getPrevious();
    } while ($e);
    

    This while loop will rerun our handleException method, with the previous Throwable, and since in my case this is a "ClientException" it will fail on $e->getData().

    Is this intended behavior? Should we also handle other exceptions then "ResourceException" and "ProviderException", even if we do not explicitly catch them in code?? Seems pretty dirty to me.

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    Yes, that's indeed intended, as the exceptions are wrapping each other. I personally don't really like this do ... while thing, but that's not our decision, I guess and existed before this patch.

    Anyway special methods may only be called, if they are implemented. As written above, another option would be to override __toString in the Exception to provide further information, instead of using if-clauses, but there are many pro's and con's. Someone has to decide here, which way to go or simply take one way...

  • 47:26
    45:04
    Running
  • @grevil opened merge request.
  • 43:42
    43:31
    Running
  • Status changed to Needs review about 1 year ago
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Grevil

    Interdiff between "2972846-39-media-oembed-error.patch" and "2972846-improve-oembed-exception" can be seen here: https://git.drupalcode.org/project/drupal/-/merge_requests/4059/diffs?co....

    A minor problem still remains. As we are logging inside a while loop, there is the possibility of logging multiple errors with practically the same output:

    First log message:

    Client error: `GET https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=GtL1h...` resulted in a `400 Bad Request` response: Bad Request

    Second log message:

    Could not retrieve the oEmbed resource: Client error: `GET https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=GtL1h...` resulted in a `400 Bad Request` response: Bad Request URL: https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=GtL1h....

    I also tried adjusting / adding tests, but the currently implemented oembed tests are super "stuffed" and overwhelming. Maybe someone else with a bit more inside knowledge could adjust them accordingly. I would've simply enabled the "media" module and tested on the "remote_video" media type, but that seems way too much unnecessary overhead for such a simple test.

  • Status changed to Needs work about 1 year ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Moving to NW for the additional test coverage.

    Since this is testing log messages there may be some trait that could do that? Worth posting in #testing for any suggestions.

  • last update about 1 year ago
    Build Successful
  • last update about 1 year ago
    29,475 pass, 2 fail
  • Status changed to Needs review about 1 year ago
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Grevil

    Alright, I added an error logging test taking inspiration from dblog/tests/src/Functional/DbLogTest.php, testLogEventPage(), on how to receive the logged watchdog event id. The only problem left is, that the test will fail.
    For some reason the latest watchdog log, is NOT our logged oembed error event and the event is NOT logged at all, when checking the watchdog overview!
    I am unsure, why that is. I already tried enabling the media and media_library modules, and trying some other workarounds (like pressing the "Add" button multiple times and checking on the dblog overview, for any error event to get logged), but with no avail.

    I'll ask in the Slack testing channel. Maybe someone there might have an idea.

  • last update about 1 year ago
    29,476 pass, 2 fail
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Grevil

    This is the test output of the "Recent log messages" page with and without media and media_library enabled:

  • Status changed to Needs work about 1 year ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Seems test failure is legit to the issue.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States recrit

    The following change in core/modules/media/src/OEmbed/ResourceFetcher.php will now expose a lot of information to an anonymous user when the fetcher error message is displayed by \Drupal\media\Plugin\media\Source\OEmbed::getMetadata(). That is not desired on any website.

      throw new ResourceException('Could not retrieve the oEmbed resource: ' . $e->getMessage(), $url, [], $e);
    

    In my opinion, the approach on ๐Ÿ› Don't display OEmbed error to anonymous visitors when resource stops being available Needs work is a better solution. It does not display the error to anonymous users (or any user that cannot edit the media) and provides a reference to the Media ID causing the issue.

Production build 0.69.0 2024