I'm designing an API with PHP and I'm wondering if there's a proper way of telling PHP not to ever write anything (not headers, or course not text,...) in the response by its own.
I mean, PHP usually returns the debug messages (errors, warnings, notices,...) directly in the response as HTML text, and if the API returns a JSON and an error (or something) occurs, this JSON would be corrupted by the PHP messages.
I have set error_reporting(0) in production mode, but I don't know if this is enough to avoid PHP on ever responding something (and therefore corrupting the output), and I'm wondering if there is a more general way of telling PHP to write stuff into a log instead of sending it as an answer... Because ideally I don't want to set error_reporting to 0, ideally I'd like to read the warnings / notices from a log file, not in the answer, as the client is not ready to handle it.
Proper way of doing this would be setting display errors to Off
ini_set('display_errors',0);
And logging to file
ini_set('log_errors',1);
Of course setting them up in your php.ini file helps you have a better control of what is in production and what is in development server.
Read further here:
http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors
http://php.net/manual/en/errorfunc.configuration.php#ini.log-errors
Related
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.
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.
I'm developing a web-application using PHP which is on tests by some of my friends. What approach do you recommend me to use in order to know what warnings are they getting but without displaying them using ini_set('display_errors', 1);?
Also, the application will run in a intranet in which I'll not have access remotely.
I was thinking to send daily emails with some information to me, but i don't know which are important facts to be saved. Do you have a article/sample for me? Do you have a better advice for me?
You can log the errors without displaying them.
For example you can do something like:
error_reporting(E_ALL | E_STRICT); //For PHP 6 E_STRICT become part of E_ALL
ini_set('display_errors', 'Off');
ini_set('log_errors', 'On');
ini_set('error_log', $_SERVER['DOCUMENT_ROOT'] . '/php.log');
You can also edit PHP.ini or do it with an .htaccess (if on Apache).
If you can't access this log remotely you can make a small PHP application that will send you the log via email.
You can use PHP mail() but a library like PHPMailer will speed things up (and will be easier to use).
Have a CRON job (or something equivalent) fire the email every day (or week or else).
Write an error handler and use set_error_handler to make sure it's called instead of the default one. In that handler, you can do whatever you think is best for your purpose.
If you want to do a daily e-mail, you would save the data to a database or file, and make a cronjob run once a day to send the e-mail with the latest data. I would probably prefer to just save to a logging table in a database, which I can then view via some interface when relevant.
That's not going to catch EVERYTHING, though - all E_WARNING will be caught, but not all other types will be. For example, parse errors can't be caught this way, and if you might want to handle exceptions as well, you should use set_exception_handler.
I think that it's the only possibility.
If you could connect there you could see apache log.
But otherwise. I'm sorry.
My best advice is to read up on PHP's set_error_handler function. It lets you determine exactly what happens whenever some error occurs -- whether you email it, log it, or whatever you want to do.
Now, there are numerous great articles on logging errors in PHP instead of displaying them to the end user. Some random examples, which I found with a 30 second Google search:
http://davidwalsh.name/custom-error-handling-php
http://www.electrictoolbox.com/log-php-errors-log-errors-error-log/
http://www.w3schools.com/php/php_error.asp
There are many ways to handle errors in PHP. Besides the aforementioned, you could rely on the default PHP error logs (by default, PHP use's Apache's error logs, i.e. /var/log/httpd/error_log). However you can modify your php.ini to send the messages to any file you like. You can check that file daily to see what errors occur.
You could also setup a CRONTAB script to read in that file once per day and email it to you, then clear it out.
Again, I'd suggest set_error_handler as a more flexible option.
I am just about to launch a fairly large website for the first time. I have turned off all error messages in my php.ini and error messages are now logged to an "error_log" file on my server.
My question is, now that the errors are logged to a file, what are the best ways that web developers keep on top of seeing when/where errors occur on the website?
At the moment, it seems like the best way would be to constantly check the error_log file everyday, however this doesn't seem like the most efficient solution. Ideally I would receive an email everytime an error occurs (with the error message). Any advice on how I can keep on top of errors would be greatly appreciated!
Extra Info
Running on Shared Server (HostMonster)
Website Authored in PHP
There are two main functions in PHP that help catching errors and exceptions. I suggest that you take a look at them :
set_exception_handler
set_error_handler
In our company, we handle all errors that occurs on our websites with those functions, defining our own errors and exceptions handling methods.
When an error occurs, an email is sent to the developers team.
The place I previously worked at used a custom extension to handle error logging. It basically INSERT DELAY the errors into a DB with some extra information. Then, a separate admin tool was written to be able to easily search, browse, sort and manually prune the log table.
I recommend that you don't write a custom extension, but that you use the set_error_handler method and just write to a DB instead. If the DB is unavailable, then write to a file as a backup. It'll be worlds easier than dealing with a huge file and a one-off format.
If you want, you can also email yourself hourly summaries, but I don't suggest you send anything more than that or you'll be hating yourself.
You can email yourself on errors, if there was no email in last N hours.
If you don't expect many errors, a "private" RSS/ATOM feed might work well... whereby you don't need to worry if you don't get anything... but if you start getting "updates" you know there are issues.
I don't know how Hostmonster handles log rotation, but generally you want to monitor the size of your error_log file. If the size jumps suddenly, there's definitely something you need to check up on so you'ld want to get an email telling you that the logfile size jumped unexpectedly.
Other than that, you can combine the error logs at the end of the week and email them to yourself and debug on the weekend. If an error is only happening a few times a week it's probably not too serious of an issue.
I've found out how to convert errors into exceptions, and I display them nicely if they aren't caught, but I don't know how to log them in a useful way. Simply writing them to a file won't be useful, will it? And would you risk accessing a database, when you don't know what caused the exception yet?
You could use set_error_handler to set a custom exception to log your errors. I'd personally consider storing them in the database as the default Exception handler's backtrace can provide information on what caused it - this of course won't be possible if the database handler triggered the exception however.
You could also use error_log to log your errors. It has a choice of message destinations including:
Quoted from error_log
PHP's system logger, using the Operating System's system logging mechanism or a file, depending on what the error_log configuration directive is set to. This is the default option.
Sent by email to the address in the destination parameter. This is the only message type where the fourth parameter, extra_headers is used.
Appended to the file destination . A newline is not automatically added to the end of the message string.
Edit: Does markdown have a noparse tag for underscores?
I really like log4php for logging, even though it's not yet out of the incubator. I use log4net in just about everything, and have found the style quite natural for me.
With regard to system crashes, you can log the error to multiple destinations (e.g., have appenders whose threshold is CRITICAL or ERROR that only come into play when things go wrong). I'm not sure how fail-safe the existing appenders are--if the database is down, how does that appender fail?--but you could quite easily write your own appender that will fail gracefully if it's unable to log.
Simply writing them to a file won't be useful, will it?
But of course it is - that's a great thing to do, much better than displaying them on the screen. You want to show the user a nice screen which says "Sorry, we goofed. Engineers have been notified. Go back and try again" and ABSOLUTELY NO TECHNICAL DETAIL, because to do so would be a security risk. You can send an email to a shared mailbox and log the exception to file or DB for review later. This would be a best-practice.
I'd write them to a file - and maybe set a monitoring system up to check for changes to the filesize or last-modified date. Webmin is one easy way, but there are more complete software solutions.
If you know its a one-off error, then emailing a notice can be fine. However, with a many hits per minute website, do not ever email a notification. I've seen a website brought down by having hundreds of emails per minute being generated to say that the system could not connect to the database. The fact that it also had a LoadAvg of > 200 because of of the mail server being run for every new message, did not help at all. In that instance - the best scenario was, by far and away, the watchdog checking for filesizes and connecting to an external service to send an SMS (maybe an IM), or having an external system look on a webpage for an error message (which doesn't have to be visible on screen - it can be in a HTML comment).
I think it depends a lot of where your error occured. If the DB is down logging it to the DB is no good idea ;)
I use the syslog() function for logging the error, but I have no problems writing it to a file when I'm on a system which has no syslog-support. You can easily set up your system to send you an email or a jabber message using for example logwatch or the standard syslogd.
I second log4php. I typically have it configured to send things like exceptions to ERROR or CRITITCAL and have them written to syslog. From there, you can have your syslog feed into Zenoss, Nagios, Splunk or anything else that syslog can talk to.
You can also catch and record PHP exceptions using Google Forms. There is a tutorial here that explains the process.