Problem/Motivation
400 level errors (outside 403 and 404) are logged as php errors vs client errors
Steps to reproduce
Trigger a badRequestException()
Check the logs and see that the error is logged as php
Proposed resolution
Per #37 and #39 use a generic "http client error" logger channel
Remaining tasks
Review changes
Commit
User interface changes
NA
API changes
NA
Data model changes
NA
Release notes snippet
NA
Original post
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21EventSubs...
It does log it correctly for 403 and 404 errors but not for other codes. For instance when a user is trying to log in without providing authentication credentials Drupal throws BadRequestHttpException and sends "400 bad request". This should not appear in DB log as PHP error because it isn't related to PHP and even to Drupal itself.
Comment | File | Size | Author |
---|---|---|---|
#75 | 2828706-75.patch | 6.82 KB | smustgrave |
| |||
#75 | interdiff-67-75.txt | 3.72 KB | smustgrave |
Issue fork drupal-2828706
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
dawehnerGood catch, 4XX errors are client side errors!
Comment #3
Chi CreditAttribution: Chi commentedThere is plenty of HTTP client errors. So I decided to handle the exception without creating a dedicated callback for each HTTP code.
Not sure if changing logger channel name is BC break.
Comment #4
Chi CreditAttribution: Chi commentedRemoved unnecessary condition.
Comment #6
Chi CreditAttribution: Chi commentedI don't know a use case for throwing HttpException with code less than 400 however RedirectOnExceptionTest does it. So I removed minimal status code condition. See interdiff-4-6.txt file.
Comment #7
dawehner@Chi
Do you mind explaining why its not enough to just change the logger channel on the on404 and on403 pages and be done with it? It is not entirely obvious, at least for me, why some of the code needs to be rewritten. I guess there are totally good reasons for that.
Comment #8
Chi CreditAttribution: Chi commented@dawehner the logger channels for 403 and 404 pages are correct without this patch. The issue is about all other 4XX pages (400, 401, etc.).
Comment #9
dawehnerI think changing these logger channels is a problem. I could imagine existing tools filter messages by these strings.
Comment #10
Chi CreditAttribution: Chi commentedAdded BC layer.
Comment #11
Chi CreditAttribution: Chi commentedComment #12
dawehnerThank you @Chi, I hope this makes sense for you as well.
Do you think we could get some test coverage to prove that we now log more than just the 403/404 errors?
Comment #14
Chi CreditAttribution: Chi commented@dawehner is it possible to get last logged entries in a Kernel test? I've tried to fetch them from watchdog table but failed.
Comment #16
dagmarThe problem is you are not using
{watchdog}
and therefore you are querying the watchdog table from your current site and not the created by phpunit.Comment #18
Chi CreditAttribution: Chi commentedExactly. Here is a patch with a test that uses
watchdog
table to verify logged exceptions. I also changed log message to more meaningful message from an exception.Comment #20
Chi CreditAttribution: Chi commentedHad to revert this change since the message is used in "Top 'access denied' errors" report.
Comment #21
Chi CreditAttribution: Chi commentedComment #29
smustgrave CreditAttribution: smustgrave at Mobomo commentedThis came up as a daily bugsmash target.
Rerolled #21 but changing the todo for Drupal 10.2.0
Comment #31
mfb@smustgrave changing the logger channel seems like a breaking change that should be delayed to 11.0.0
Comment #32
smustgrave CreditAttribution: smustgrave at Mobomo commentedChanged to 11.0.0 and fixed the failing db log test.
Comment #34
smustgrave CreditAttribution: smustgrave at Mobomo commentedUpdated test case.
Comment #35
dagmarThis can trigger a warning if the $status_code is not in the list of status_texts. We don't know if some client/server/app can use a custom error code that we are not aware of... Not sure if we should log this at all, or just ignore it...
Maybe we can avoid copying the statusText into a new array. What about checking $status_text = Response::$statusTexts[$status_code] ?? NULL;
And then use 2 ifs to override 'access denied' and 'page not' found texts.
I think it should be
No need to create a temp variable:
$this->logger->get($channel)->warning('@uri', ['@uri' => $event->getRequest()->getRequestUri()]);
Comment #36
smustgrave CreditAttribution: smustgrave at Mobomo commentedSomething like that?
Comment #37
longwaveDo we really need separate logger channels, or should we just have a shared "http" logger channel for the 4xx errors that aren't 403/404? They don't seem common enough to warrant their own.
Comment #38
smustgrave CreditAttribution: smustgrave at Mobomo commentedThat I don't know I can answer. But I do like the idea of 403s not logging as a php exception but that's may just be me.
Comment #39
mfbAdding a generic "http client error" logger channel seems sufficient to me, and the specific status code could be added to the context array.
Comment #41
smustgrave CreditAttribution: smustgrave at Mobomo commentedFixed the test case. Not sure best practice for dealing with subdirectory running on d.o but add a string replace for now.
Comment #43
Anchal_gupta CreditAttribution: Anchal_gupta at Srijan | A Material+ Company for Drupal India Association commentedFix Unit Fail
Comment #44
smustgrave CreditAttribution: smustgrave at Mobomo commentedThank you Anchal_gupta for the patch but please include an interdiff so we can see what has changed.
From what I can tell patch #43 is the same as #41 so remove credit for that.
Updated the tests to remove the status codes that weren't being checked by the code change.
Comment #45
dagmarI think we want to go with the approach provided in #37 and #39. Something like this perhaps? (Beware untested code, just sharing the approach mentioned in #37 and #39 so others can continue this as part of the Bug Smash Initiative.
Comment #46
smustgrave CreditAttribution: smustgrave at Mobomo commentedAdded what was provided in #45 lets see what happens.
Also added IS update just to make sure we have an agreed upon approach.
Comment #48
smustgrave CreditAttribution: smustgrave at Mobomo commentedWhat about this?
Comment #50
smustgrave CreditAttribution: smustgrave at Mobomo commentedNot sure about the error in testUncaughtFatalError will have to investigate later.
Comment #51
smustgrave CreditAttribution: smustgrave at Mobomo commentedComment #52
mfbThis is looking good to me. The one thing I might suggest (as I mentioned in #39) would be to add status_code to the context array. My philosophy is the more context/metadata/etc. provided to loggers, the better. But in general drupal core doesn't go out of its way to add helpful context (aside from log message placeholders) so that's just my humble opinion.
Comment #53
smustgrave CreditAttribution: smustgrave at Mobomo commentedNot sure I follow?
Comment #54
dagmar@smustgrave I think what @mfb is trying to say is, send the 4xx code as part of the $context array. Because it is hidden behind the generic client error.
Comment #55
smustgrave CreditAttribution: smustgrave at Mobomo commentedLike this?
Comment #56
bradjones1Yes I think that's the jist of the suggestion.
Comment #64
quietone CreditAttribution: quietone at PreviousNext commentedi closed #3039266: Generic logging for 4xx errors as a duplicate, moving credit.
Comment #65
catchI'm not sure we need this if we have the Kernel test - depending on the answer to the question about the kernel test.
This isn't testing the non-403/404 4xx errors that this issue is about, should it be?
Comment #66
smustgrave CreditAttribution: smustgrave at Mobomo commentedRemoved functional test
Comment #67
smustgrave CreditAttribution: smustgrave at Mobomo commentedComment #68
catch#67 looks good.
Comment #69
larowlanshouldn't this be elseif? as much as I hate elseif, its odd to see an if inside an else
is this used? the test seems to be hitting an existing route
Let's not use the database to collect the log messages, we can just make the kernel test a logger 💪
See https://www.previousnext.com.au/blog/making-your-drupal-8-kernel-tests-f... for an example
Comment #70
larowlanOr even simpler, use the test logger like in #3134349: \Drupal\language\LanguageNegotiator does not handle PluginNotFoundException and break the site completely - learnt something new 🔥
Comment #71
sourabhjainLet me work on #69
Comment #73
sourabhjainResolved the 1st issue from #69 and created PR.
Comment #74
larowlanWhat about #2 and #3 @sourabhjain?
Going to cancel the test run, its a waste of DA resources without addressing the feedback.
Comment #75
smustgrave CreditAttribution: smustgrave at Mobomo commentedAttempted to address all points.
Comment #76
Chi CreditAttribution: Chi commentedI know this issue is specifically about 4xx errors, but i'd like to point that 5xx errors shouldn't be always logged in PHP channel. For example I have a project where Drupal serves as a gateway to another site. So when the upstream site fails Drupal returns 502 exception. That's part of normal workflow and has nothing to do with PHP.
I think PHP channel should only be used for exceptions that got 500 status code in FinalExceptionSubscriber. That might need a separate issue.
Comment #77
FeyP CreditAttribution: FeyP as a volunteer and at werk21 commentedThis issue is being reviewed by the kind folks in Slack, #need-reveiw-queue. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
Thanks for working on this, found some more stuff to remove from the test ;).
To address #69.2 the latest patch removed the route that wasn't used, but I think this needs to be removed as well. Without the route this is now dead code.
Since we don't use the
error_test
module in the test at all and we thus don't need to make any modifications to that module anymore, this can most likely also be reverted.Further down in the test method, we're already calling
$this->assertEmpty($this->container->get($this->testLogServiceName)->cleanLogs());
before we start triggering errors. I don't think we need to call this twice. I think asserting that the logger is empty in the test is a good idea, so we should probably just remove the setup method.and
Given that we now use a test logger, I don't think we need need dblog anymore, do we?
Tagging "Needs followup" for #76.
Comment #79
catchThis came up again in #3377310: 400 exceptions result from requests for old asset paths which are missing the "theme" query string, possibly from cached pages.
Comment #81
saidatomResolve remarks from #77
Comment #82
smustgrave CreditAttribution: smustgrave at Mobomo commentedOpened #3392245: ExceptionLoggingSubscriber should not log HTTP 5XX errors using PHP logger channel
Points from #77 do appear to be resolved.
Comment #83
catchCommitted/pushed to 11.x, cherry-picked to 10.2.x and 10.1.x, thanks!
Comment #87
catch