-
Notifications
You must be signed in to change notification settings - Fork 824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CONTROL] Logging before httpError will cause HTML to be added and output as plaintext #8044
Comments
If you're logging errors then you should expect the system to halt in some way. If you're looking to "log" (e.g. to a file) errors, you'll need to use a lower log level, e.g. info or debug. What is the realistic example of where you'd be logging errors in this case? |
The above mentioned modifications are the only ones performed, no configuration was changed other than modifying the PageController.php to provide a working small footprint reproduction of the bug. Logging is (almost) never a bad thing imho, and it will halt (in some way) if used for example when an exception is thrown such as try {
doStuff(); // May throw Exception
} catch (Exception $e) {
// Log Exception
Injector::inst()->get(LoggerInterface::class)->error($e->getMessage());
// Make the user receive an error
$this->httpError(400, "Bad things happened");
}
doOtherStuff(); // Never reached if Exception is thrown in doStuff call. Logging stuff like that as an error, just seems logical and appropriate. Not to mention that without further modifications to the config, nothing obvious seems to happen when logging (apart from this bug that is), at least nothing is ever really logged to anywhere afaict. |
I just tested @Sil3ntStorm's code sample and I'm encountering the same issue that's describe. I think he's right that the logger shouldn't be affecting the behavior of the application beyond writing a log message to the error logs. It's quite a common pattern to have some detailed error message printed to the logs for debugging later on and then display a nondescript error page. This bug prevents this from happening. |
I've brought this up before, and was told not to log errors if I didn't want to disrupt the application flow. This stems from the fact that we use monolog for error handling in the main application. I don't think this is a bug. A little bit of related detail in lekoala/silverstripe-debugbar#72 during upgrade from SS3 to SS4 where we had to ditch support for showing any error logs above debug. One workaround is to use your own monolog service rather than using the one that is configured in core. This isn't a great solution for inter-module logging compatibility, but would be fine for logging in your own module or project. |
@robbieaverill What was the stated rational for not logging errors? The doc for LoggerInterface::error() states:
To me that sounds like calling this method should not be a big deal. |
I agree with you =) we probably need a weigh in from @tractorcow at some point when he's available |
Did @tractorcow say logging errors was bad?! I'll have a stern word with him once he's back from holiday. |
I only remember that he was involved with this conversation. Another possible solution is that we could move the core error logging into its own implementation and allow devs to do what they wish with the default |
Kinda offtopic, but in a default installation of SS4.1 with no configuration changes, where would I find such error (or any other level) logs? I checked the standard suspects (PHP logs, Webserver logs, syslog) and couldn't find any trace of these log messages. |
@Sil3ntStorm by default all logs go to the browser. You'll need to push a file logging handler if you want file logs - see https://docs.silverstripe.org/en/4/developer_guides/debugging/error_handling/#logging-to-a-file I think the issue here is that logging an error to a file will also log it to the browser, which is a behavioural change with the introduction of monolog in SS4 from what SS_Log did in SS3 |
Yeah I know of that page and the file logging configuration change.
(If I didn't mess up somewhere, it's late) With the above in mind, it appears as though my initial statement that logging is apparently (supposed to be?) a no-op by default is correct (except for these bugs / inconsistencies). |
It may be that our current behaviour for "error" should be reserved for "critical", "emergency", or "alert"? Coupled with this would be to adjust our exception & error handlers to log higher-severity messages as well |
I agree wit @maxime-rainville (and @robbieaverill); logging errors should not cause a halt in execution itself. If error logging happens to log an exception, it shouldn't swallow the exception and continue execution, but it shouldn't take a non-halting error and halt. That's madness |
The best and most non-breaking solution I have here is to shift the default framework logging (CLI and HTTP) to a sub-service of LoggerInterface rather than the default implementation of it. That way clients can continue to use LoggerInterface as normal but raising errors and higher won't kill their websites. |
what would be breaking about not halting execution when logging errors? |
Sorry, I meant non-breaking in terms of what's in core already and how it could be adjusted to behave differently without breaking existing SS installs that may be relying on the existing LoggerInterface |
I'm a little nervous about making an incremental change without thinking through all the different use-cases. There's a risk that we make it more intuitive in this situation and less intuitive in another. To that end, in our default configuration in live mode, what should the following situations do? System errors:
Log messages:
The real question is: is there any level of log message that should voluntarily halt execution?
If we do want to decouple I would probably suggest that the system errors/exceptions are both sent to the LoggerInterface and to the system for error display. The error display system could still use LoggerInterface as its backbone, e.g. |
Logging is just logs for future reference to discover and aid in fixing issues. This is a website not some sort of client application where the developer needs to grab the logs from the client. So clients (users of the website) don't need to ever see these logs. Not sure what your definition of a system error is and how it relates to the Logging Levels. In general in my view it all comes down to this:
None of that has anything to do with logging really though, and should not be handled by a logging class. If a function called "log" does anything except the actual logging of the message to the configured means of logging then that is an unexpected, unintended side effect of said function. If the developer thinks it's important enough to abort then it should have to be done explicitly, after the logging. PS: There are SMS alerts in SS? 😮 |
The system is currently architected so that errors and uncaught exceptions are handled by the error logger. It's built as a bunch of monolog handlers. On production sites, all it shows the users is a "sorry, something went wrong" page. On development sites, it often does make more sense to expose the error details to the user, and potentially the log messages too (I've sometimes used a plugin that puts it into my chrome dev tools, for example). A system error is a user_error call, uncaught exception, or other fatal error. These should create log messages, but that doesn't necessarily mean that the log handler should behave the same way for these. The core question is If you have sent an PS: No, there aren't SMS alerts but those are the PSR-3 log definitions. In principle you could probably use this to make them if you wanted https://github.com/tylercd100/monolog-sms |
My opinion is that it should not. The logger is there precisely to log the event in some way. The error handler then gets to decide how to deal with the error itself. I should be able to do One thing that might be a bit confusing is if you have a logger that logs to the browser; if you're using an "HTML output logger" for example, this is much more difficult for the application to continue as expected because HTML output may have started before headers have gone out and that handler may halt on errors (I think ours, or at least our SS3 html output for errors, does this). That's more a quirk of the specific logger but shouldn't be a feature of our abstract logging interface. |
Alright, that being the case, we should handle error display separately from logging. In the interests of not breaking APIs I think we should keep using Monolog handlers as the mechanism by which error display works. However, it can use a different LoggerInterface service so that regular log messages bypass it. Here's a suggested implementation architecture; does it make sense?
We should test that instructions for setting up, say, logging to a file remain working without modification, to ensure that we haven't broken any APIs in doing this. |
I'm also encountering this issue with silverstripe-fulltextsearch. Having errors/warnings outputted as response body by default destroys |
I really want to fix this. This is totally a bug in my opinion. I'll try and find some time to get a PR up for consideration if @ScopeyNZ doesn't beat me to it. I'm getting really tired of having to reduce error log levels down to notice or something non-indicative of the problem when a module I work on has logging in it. |
Had to do some log level downgrading in the RealMe module today too! |
@robbieaverill do you want to do a PR of the approach I suggested above (I've put in the ticket description too) |
Yes, reading through it now
No, in my opinion. This is a logger. If I wanted to halt execution I'd throw an exception rather than rely on a logger to handle it. This mirrors @dhensby's opinion too so that seems good enough for a RFC pull request =) |
Yeah that's the approach that I incorporated into my recommended fix approach. We still use MonoLog to provide our error handling, but it's a separate extension point. Using Monolog as an error handler is a bit overengineered, but it's already implemented and doing anything else would end up as an API breakage. |
PR at #8241 for consideration |
Affected Version
SilverStripe 4.1
composer info --direct
Description
Calling httpError with an error message will (magically and at an unknown location) prefix the message with HTML Dom and then send the entire thing to the browser, which causes conforming browsers to display the complete HTML instead of only the error message, as the Content-Type Header is rightfully set to text/plain during the Exception handling for security reasons.
Steps to Reproduce
Install Base SS 4.1
composer create-project --no-dev silverstripe/installer . ^4.1
and add the following code to a custom page action and load the appropriate page.For example edit mysite/code/PageController.php and add the above to a new function crash(), add 'crash' to the allowedActions array and add the necessary use lines at the top.
Complete PageController.php:
Result
Instead of displaying a text "foo", you will see a bunch of HTML source code and at the very end the "foo" we were expecting.
Comment out the Injector::inst() line, reload the page and see that you're only getting the expected "foo"
The content-type header is set to text/plain for valid security concerns and this is a good thing, however when doing so I would expect there to be no HTML present at all.
Fix Approach (by sminnee)
%$Psr\Log\LoggerInterface
and%$Psr\Log\LoggerInterface.errorhandler
(in that order)%$Psr\Log\LoggerInterface.errorhandler
is given the display error logic%$Psr\Log\LoggerInterface
by default is just aMonolog\Logger
with no handlers attached.We should test that instructions for setting up, say, logging to a file remain working without modification, to ensure that we haven't broken any APIs in doing this.
The text was updated successfully, but these errors were encountered: