Php error and logging handler

How do I log errors and warnings into a file?

How do I turn on all error and warnings and log them to a file, but to set up all of that within the script (not changing anything in php.ini)? I want to define a file name and so that all errors and warnings get logged into it.

9 Answers 9

ini_set("log_errors", 1); ini_set("error_log", "/tmp/php-error.log"); error_log( "Hello, errors!" ); 

Or update php.ini as described in this blog entry from 2008.

ini_set does only work if that code is executed. Not useful for code that has parse errors because the error will be before the code is executed. Instead write those changes into the php.ini.

If you can’t edit php.ini, you should be able to add this in the .htaccess : php_flag log_errors on php_value error_log /home/path/public_html/domain/PHP_errors.log . See perishablepress.com/…

error_log("You messed up!", 3, "/var/tmp/my-errors.log"); 

You can customize error handling with your own error handlers to call this function for you whenever an error or warning or whatever you need to log occurs. For additional information, please refer to the Chapter Error Handling in the PHP Manual

Simply put these codes at top of your PHP/index file:

error_reporting(E_ALL); // Error/Exception engine, always use E_ALL ini_set('ignore_repeated_errors', TRUE); // always use TRUE ini_set('display_errors', FALSE); // Error/Exception display, use FALSE only in production environment or real server. Use TRUE in development environment ini_set('log_errors', TRUE); // Error/Exception file logging engine. ini_set('error_log', 'your/path/to/errors.log'); // Logging file path 

That’s only if you also want all errors to be displayed in output and/or to the browser, in addition to logging. display_errors should NEVER be turned on on a live production server — that directive is specifically for output to the user, and has no effect on logging. php.net/manual/en/…

Читайте также:  Python вычисление времени выполнения

Add this code in file .htaccess (as an alternative to file php.ini or the ini_set function):

 php_flag log_errors on php_value error_log ./path_to_MY_PHP_ERRORS.log # php_flag display_errors on 
  • as commented: this is for Apache-type servers, and not for Nginx or others.

That’s my personal short function

# logging /* [2017-03-20 3:35:43] [INFO] [file.php] Here we are [2017-03-20 3:35:43] [ERROR] [file.php] Not good [2017-03-20 3:35:43] [DEBUG] [file.php] Regex empty mylog ('hallo') -> INFO mylog ('fail', 'e') -> ERROR mylog ('next', 'd') -> DEBUG mylog ('next', 'd', 'debug.log') -> DEBUG file debug.log */ function mylog($text, $level='i', $file='logs') < switch (strtolower($level)) < case 'e': case 'error': $level='ERROR'; break; case 'i': case 'info': $level='INFO'; break; case 'd': case 'debug': $level='DEBUG'; break; default: $level='INFO'; >error_log(date("[Y-m-d H:i:s]")."\t[".$level."]\t[".basename(__FILE__)."]\t".$text."\n", 3, $file); > 

An explanation would be in order. E.g., what is the idea/gist? Please respond by editing (changing) your answer, not here in comments (without «Edit:», «Update:», or similar — the answer should appear as if it was written today).

Take a look at the log_errors configuration option in php.ini. It seems to do just what you want to. I think you can use the error_log option to set your own logging file too.

When the log_errors directive is set to On , any errors reported by PHP would be logged to the server log or the file specified with error_log . You can set these options with ini_set too, if you need to.

(Please note that display_errors should be disabled in php.ini if this option is enabled)

Why should display_errors be disabled if you enable log_errors ? Doesn’t make sense in my opinion. 🙂

Because there’s no need to output the content of the errors to the public on a production server, especially if the text of the error is being discreetly logged into a file.

Display errors should be always disabled on production server. Not if error logging is configured to somewhere else, but always. Errors are logged to apache error log by default, that is often enough.

None of these answers mention the importance or relevance to Agile teams; professional-level development work is more often than not done within the context of a squad.

Keeping in mind that many development teams use a task-tracking tool such as JIRA , I prefer to use a timestamp to log each error as a separate file:

error_reporting(E_ALL); ini_set('log_errors', 1); ini_set('error_log', $_SERVER['DOCUMENT_ROOT'] . '/logs/php/php-errors-' . time() . '.txt'); 

Using this approach, it is easy for a Project Manager or Team Lead to then isolate each error as a specific file that can then be attached to a unique JIRA defect, assigned to a developer, and tracked (the timestamp can be linked within the defect to easily track while the defect fix is In-Progress). When the issue is closed, then the file can be deleted from the log directory, while a copy of it (if needed for future reference) can be accessed in the JIRA.

Источник

See Also

I keep seeing qualification lists for error types/error-nums as arrays; In user notes and in the manual itself. For example, in this manual entry’s example, when trying to seperate behavior for the variable trace in the error report:

// set of errors for which a var trace will be saved
$user_errors = array( E_USER_ERROR , E_USER_WARNING , E_USER_NOTICE );

if ( in_array ( $errno , $user_errors )) //. whatever
>

//. ?>

I was under the impression that PHP error code values where bitwise flag values. Wouldn’t bitwise masking be better? So I propose a slightly better way:

$user_errors = E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE ;

if ( $errno & $user_errors ) //. whatever
>

//. ?>
Or for those of you who don’t like the idea of using an integer as the condition in an if statement:

if (( $errno & $user_errors ) > 0 ) //. whatever
>
?>

I think that’s much more efficient than using _yet another_ array() constuct and an in_array().

If I am wrong, and the E_* constants aren’t supposed to be used in this fashion (ie, the constans aren’t guaranteed to be bitwise, which would be odd since that’s how they’re setup in the php.ini file), then delete me. I just don’t see why one should be using arrays when bitwise comparisons will work, considering the bitwise method should be MUCH more efficient.

Although the root user writes to the files ‘error_log’ and ‘access_log’, the Apache user has to own the file referenced by ‘error_log = filename’ or no log entries will be written.

; From php.ini
; Log errors to specified file.
error_log = /usr/local/apache/logs/php.errors

[root@www logs]$ ls -l /usr/local/apache/logs/php.errors
-rw-r—r— 1 nobody root 27K Jan 27 16:58 php.errors

PHP5 only (only tested with php5.0).

If you, for some reason, prefer exceptions over errors and have your custom error handler (set_error_handler) wrap the error into an exception you have to be careful with your script.

Because if you, instead of just calling the exception handler, throws the exception, and having a custom exception handler (set_exception_handler). And an error is being triggered inside that exception handler, you will get a weird error:
«Fatal error: Exception thrown without a stack frame in Unknown on line 0»

This error is not particulary informative, is it? 🙂

This example below will cause this error.
class PHPErrorException extends Exception
private $context = null ;
public function __construct
( $code , $message , $file , $line , $context = null )
parent :: __construct ( $message , $code );
$this -> file = $file ;
$this -> line = $line ;
$this -> context = $context ;
>
>;

function error_handler ( $code , $message , $file , $line ) throw new PHPErrorException ( $code , $message , $file , $line );
>

function exception_handler ( Exception $e )
<
$errors = array(
E_USER_ERROR => «User Error» ,
E_USER_WARNING => «User Warning» ,
E_USER_NOTICE => «User Notice» ,
);

echo $errors [ $e -> getCode ()]. ‘: ‘ . $e -> getMessage (). ‘ in ‘ . $e -> getFile ().
‘ on line ‘ . $e -> getLine (). «\n» ;
echo $e -> getTraceAsString ();
>

set_error_handler ( ‘error_handler’ );
set_exception_handler ( ‘exception_handler’ );

// Throw exception with an /unkown/ error code.
throw new Exception ( ‘foo’ , 0 );
?>

There are however, easy fix for this as it’s only cause is sloppy code.
Like one, directly call exception_handler from error_handler instead of throwing an exception. Not only does it remedy this problem, but it’s also faster. Though this will cause a `regular` unhandled exception being printed and if only «designed» error messages are intended, this is not the ultimate solution.

So, what is there to do? Make sure the code in exception_handlers doesn’t cause any errors! In this case a simple isset() would have solved it.

If you are using PHP as an Apache module, your default behavior may be to write PHP error messages to Apache’s error log. This is because the error_log .ini directive may be set equal to «error_log» which is also the name of Apache’s error log. I think this is intentional.

However, you can separate Apache errors from PHP errors if you wish by simply setting a different value for error_log. I write mine in the /var/log folder.

Note the example code listed here calls date() every time this is called. If you have a complex source base which calls the custom error handler often, it can end up taking quite a bit of time. I ran a profiler on som code and discovered that 50% of the time was spent in the date function in this error handler.

When configuring your error log file in php.ini, you can use an absolute path or a relative path. A relative path will be resolved based on the location of the generating script, and you’ll get a log file in each directory you have scripts in. If you want all your error messages to go to the same file, use an absolute path to the file.

In some application development methodologies, there is the concept of an application root directory, indicated by «/» (even on Windows). However, PHP does not seem to have this concept, and using a «/» as the initial character in a log file path produces weird behavior on Windows.

If you are running on Windows and have set, in php.ini:

You will get some, but not all, error messages. The file will appear at

and contain internally generated error messages, making it appear that error logging is working. However, log messages requested by error_log() do NOT appear here, or anywhere else, making it appear that the code containing them did not get processed.

Apparently on Windows the internally generated errors will interpret «/» as «C:\» (or possibly a different drive if you have Windows installed elsewhere — I haven’t tested this). However, the error_log process apparently can’t find «/» — understandably enough — and the message is dropped silently.

It is totally possible to use debug_backtrace() inside an error handling function. Here, take a look:

function errorHandler ( $errno , $errstr , $errfile , $errline , $errcontext )
echo ‘Into ‘ . __FUNCTION__ . ‘() at line ‘ . __LINE__ .
«\n\n—ERRNO—\n» . print_r ( $errno , true ).
«\n\n—ERRSTR—\n» . print_r ( $errstr , true ).
«\n\n—ERRFILE—\n» . print_r ( $errfile , true ).
«\n\n—ERRLINE—\n» . print_r ( $errline , true ).
«\n\n—ERRCONTEXT—\n» . print_r ( $errcontext , true ).
«\n\nBacktrace of errorHandler()\n» .
print_r ( debug_backtrace (), true );
>

function a ( )
//echo «a()’s backtrace\n».print_r( debug_backtrace(), true);
asdfasdf ; // oops
>

function b ()
//echo «b()’s backtrace\n».print_r( debug_backtrace(), true);
a ();
>

Into errorhandler() at line 9

—ERRSTR—
Use of undefined constant asdfasdf — assumed ‘asdfasdf’

Backtrace of errorHandler()
Array
(
[0] => Array
(
[function] => errorhandler
[args] => Array
(
[0] => 8
[1] => Use of undefined constant asdfasdf — assumed ‘asdfasdf’
[2] => /home/theotek/test-1.php
[3] => 23
[4] => Array
(
)

[1] => Array
(
[file] => /home/theotek/test-1.php
[line] => 23
[function] => a
) [2] => Array
(
[file] => /home/theotek/test-1.php
[line] => 30
[function] => a
[args] => Array
(
) [3] => Array
(
[file] => /home/theotek/test-1.php
[line] => 33
[function] => b
[args] => Array
(
)

So, the first member of the backtrace’s array is not really surprising, except from the missing «file» and «line» members.

The second member of the backtrace seem the be a hook inside the zend engine that is used to trigger the error.

Other members are the normal backtrace.

Источник

Оцените статью