logging PHP fatal errors - php

I have my website on a managed server where i do not have any possibility to configure any php errors since I do not have access to the php.ini
The problem I am facing is that my server provider does not log php errors. I am able to catch (via exceptions) other errors as for example notices but it is not possible to catch fatal errors.
Since I do not have any access to an error log, I do not know whether some of my visitors face fatal errors on my website ...
I already asked my provider but they just told me that they do not log the errors and will not do it in the future. I really want to keep my managed server for maintenance reasons.
Is there any other possibility to track or log fatal errors so that I do not have change anything in the configuration?
Best regards,
Frederic

Between set_error_handler() and register_shutdown_function() you should be able to define custom logic to handle all your errors, exceptions, fatal errors, etc..

You can handle this using PHP's set_error_handler function. When an error is thrown, you can log the error to your own text file, or have it emailed to you, or whatever you want to do.

Related

Is hiding/logging errors on a PHP server good practice?

I am trying to deploy a PHP server with php files and a database I received a copy of. However, there are a lot of errors (Mostly from variables used without being declared). Most places I have looked, including the people who built it, say to turn off display of error messages and put them in a log file. The site works fine when I turn off the display and hide them in a log, but the errors are still there.
The trouble is, there are a LOT of errors. The page content triples in size from the sheer amount of error notices that pop up when I don't turn off front end error display. Is simply hiding the errors in a log something that is actually good practice on a non-development server?
The errors should be hidden and logger into a file as they might sometimes contain information which is better not to show to potential attackers but you should fix them.
If the case you forget constantly to look at that file what I did is having a cronjob to check the error file 4 times a day (during the working hours) and if there were errors send them to you by email and clear the log file. This way you are most likely not to miss any error that happened.
Your goal is having 0 lines (errors and warnings) in that error file so you should be fixing them the sooner the better.
One problem I faced is that after logging the errors of one website created by others I started receiving hundreds of errors every few days. That errors seemed strange as they were all from the same moment and according to the errors that seemed to happen when the user was not logged in and should have been redirected. They were of divisions by 0, undefined vars... There was a location header redirect in that case but still I got tons of errors. The errors helped me find that the code was still being executed after the location redirect so I only had to call exit() after the location header to prevent this errors from happening. I would not know they were there if I didn't log them and the server would still be throwing that huge amount of errors while executing that code.

What purpose does a PHP logging framework serve?

I've been looking for a Php logging framework throughout the web and I realized What is the need to use a PHP logging framework if Apache logs all interactions to the server?
1. Fine grain control over error messages
Relying on PHP to log all of its error in its error log, and Apache to log all its error in its error log is fine - but sometimes you need more details. For instance, something may throw an exception regarding a failed SQL query and the message might say something like SQLException: Could not retrieve XYZ data. However, we would also want to see the stack trace and SQL query that failed. We could opt to throw that in the exception message, but that deprives us of the fine grain control - I /don't always want that debugging detail.
2. Non-web Apache related tasks
I use PHP quite often for the CLI capabilities for cronjobs. Apache wouldn't be involved in this, and PHP would opt to send output to STDOUT. Logging any errors would allow me to review them later.
3. Logging things that aren't errors
I can imagine a scenario where you would want to see login times, but don't want to store it in the database. For instance:
8/21/16 7:48 - HPierce logged in
8/21/16 7:49 - HPierce logged out
These aren't errors, and parsing through Apache's access logs isn't practical to get this kind of user information.

Newrelic php agent error tracing

I am a bit confused about how New Relic tracks errors in a php application.
Does the error level set in the application (with error_reporting()) matter for the php agent? Or does it still get all errors? Are there cases in which the php agent will not be able to gather errors?
The New Relic PHP agent hooks into PHP and any errors that hit the PHP error handler will be passed on to us. We typically ignore 4xx errors but anything else detected by PHP should get collected.
As we're listening for errors detected by PHP, changing the error level will also affect the level of errors New Relic can see. Ee will never report errors with a level of E_NOTICE or E_USER_NOTICE
Errors with the web-server which prevent the PHP extension from loading will not be tracked. There's also a known compatibility issue with Xdebug which prevents our agent from tracking errors.
As I am aware the best approach is to configure the agent using PHP agent (newrelic.ini) settings, the is the option newrelic.loglevel where you can set the log level. Although you can still use the error_reporting() to 'overwrite' those settings a relevant question / answer can be found here.
So as from my experience, there are some occasion that this is not working as I expected.
Some time when a fatal error occurred, the php agent was unable to track it. Also there where times that new relic was resetting the options I have put using the error_reporting() to the 'default' ones I have set via newrelic.loglevel.
Disclaimer : I have over a year to use new relic so this may be obsolete.
My opinion is not to mix the these two different ways of setting the error level and stick with the API that the php agent provides. I think that in most of the cases this is going to be enough

PHP - should set_error_handler be used?

From my understanding of PHP documentation, setting custom error handler (which cannot catch all the errors) deactivates the default php error handler (which I guess can catch all the errors:).
If this is correct, is there any purpose of setting custom error handler? I always keep error_reporting(-1), so I should get all errors in the error log anyway, right?
As for the user experience, I cannot see the purpose of making these errors manifest in a custom way - why would you ever want users to see them? In production I always set display_errors to off.
In production you probably want to tell the user something when your site crashes, and set_error_handler provides a way of rendering pretty error messages while preventing the user from seeing ugly things like code and line numbers. It catches any runtime errors that the regular PHP error handler catches.
There is no reason to avoid using set_error_handler, and it's certainly preferable to simply displaying nothing when an error occurs.
Setting a custom error handler is for setting a catch-all handler that takes care of the errors that aren't handled elsewhere. It can catch all errors, except for the ones where your script isn't ran at all (such as fatal syntax errors).
I should also point out that if you return false from your error handling function, then the built-in PHP error handler will step in.
You may want this for special logging of any specific kinds of exceptions in your application.
If this is correct, is there any purpose of setting custom error handler? I always keep
error_reporting(-1), so I should get all errors in the error log anyway, right?
error_reporting dictates which errors should be reported (e.g. warning, notices, etc.). This has nothing to do with them showing up in the logs; if you set error_reporting to 0 it won't be logged. If you want it to be logged, but not displayed to the customer, use display_errors = Off.
As for the user experience, I cannot see the purpose of making these errors manifest in a custom way - why would you ever want users to see them? In production I always set display_errors to off.
I'd want to see a message that "something" went wrong, rather than seeing a "white screen of death". This may be simple to do with a custom error handler. So, yeah, it does have a purpose.

trigger_error vs. throwing exceptions

A similar question was asked here, but as the answers didn't answer my question, I'm asking:
I've almost never used trigger_error, always thrown exceptions instead, since in my mind errors are legacy. But I've changed my mind, I think they can co-exist. There are cases when triggering errors make more sense.
I'm updating this library, this question concerns the send method, but is general enough. This is my reasoning:
If an API key constant is not set, that is not a catchable error. That is a programming error, and should be treated as such.
If an email address is invalid, that should be catchable. This is most likely a user error.
Am I loco? Is this unnecessary and annoying, or does it make sense?
I agree with your distinction, as to when to throw and when to trigger. For me, trigger_error is also something you want to make a note off, but it's not important to the current request. E.g. for debugging purposes.
Since all my PHP errors (note: not exceptions, but warnings, notices, fatals, etc.) are logged in production, I think trigger_error is a convenient way to get stuff into said log.
Here is an example:
I'm using a HTTP client to access an API we integrate. Of course the library I use is object-oriented PHP and therefor makes heavy use of exceptions. I'm doing various things here and I hope this example makes sense:
The HTTP client library throws an exception when the actual request failed -- e.g. due to a connection issue, such as a timeout, etc.. Of course I catch this error, but I don't elevate it to the user. My wrapper returns false and this equals to, "Temporary issue." in the frontend.
In my catch() block I use trigger_error() to log debug information about the actual connection error. Since I got error_log = syslog in my php.ini all this information is send to syslog and eventually to my log master.
If I'd use the library, I would really hate to use both try-catch block and old style error checking. And even if the missing API key renders the library unusable, it's still part of application.
They both have their uses. Generally, I gear trigger_error() toward developers, since in most production environments error reporting is turned off; then, since most application errors would likely be from bad user input or undesired results based upon user input/actions, I throw exceptions to keep better control over the application (handling those exceptions in a way that both allows the app to recover, and (if necessary) informs the user about what happened in a logical way.
Edit: that example was based off of web apps; the same could be said of any piece of variable data in a non-user-controlled application.

Categories