Precision about error_log when configured with syslog: the syslog() call is done with severity NOTICE.
XXXIII. Erros e Logs
Introdução
Estas são funções para lidar com erros e logs. Elas permitem a você definir a suas próprias regras para manusear erros, assim como para modificar a maneira com que é efetuado o log de erros. Isto permite a você melhorar e adaptar as suas necessidades os avisos de erro.
Com as funções de log, você pode mandar mensagens diretamente para outras máquinas, para um email (ou email para um pager), para os logs do sistema, etc, assim você pode seletivamente logar e monitorar as partes mais importantes das suas aplicações e websites.
As funções de erro permitem você configurar quais níveis de erro devem ser reportados e o tipo de resposta que será dado, indo desde simples avisos até as funções retornadas durante os erros.
Dependências
Nenhuma biblioteca externa é necessária para compilar esta extensão.
Instalação
Não há nenhuma instalação necessária para utilizar estas funções, elas fazem parte do núcleo do PHP.
Configurações em execução
O comportamento dessas funções podem ser modificado pelas configurações do php.ini.
Tabela 1. Opções de configurações de erros e log
| Nome | Padrão | Modificável |
|---|---|---|
| error_reporting | E_ALL & ~E_NOTICE | PHP_INI_ALL |
| display_errors | "1" | PHP_INI_ALL |
| display_startup_errors | "0" | PHP_INI_ALL |
| log_errors | "0" | PHP_INI_ALL |
| log_errors_max_len | "1024" | PHP_INI_ALL |
| ignore_repeated_errors | "0" | PHP_INI_ALL |
| ignore_repeated_source | "0" | PHP_INI_ALL |
| report_memleaks | "1" | PHP_INI_ALL |
| track_errors | "0" | PHP_INI_ALL |
| html_errors | "1" | PHP_INI_ALL |
| docref_root | "" | PHP_INI_ALL |
| docref_ext | "" | PHP_INI_ALL |
| error_prepend_string | NULL | PHP_INI_ALL |
| error_append_string | NULL | PHP_INI_ALL |
| error_log | NULL | PHP_INI_ALL |
| warn_plus_overloading | NULL | PHP_INI?? |
Breve descrição das diretivas de configuração.
- error_reporting integer
Define o nível de erros para reportar. O parâmetro pode ser um inteiro ou uma constante. Os níveis de erros para reportar estão descritos em Constantes Predefinidas, e no php.ini. Para definir em tempo de execução, use a função error_reporting(). Veja também a diretiva display_errors.
No PHP 4 e PHP 5 o valor padrão é E_ALL & ~E_NOTICE. Esta definição não mostra erros de nível E_NOTICE. Você deve querer mostra-los durante o desenvolvimento.
Nota: Ativando E_NOTICE durante o desenvolvimento tem alguns beneficios. Para o proposito de eliminar erros: mensagens NOTICE irão avisar você sobre possiveis erros em seu código. Por exemplo, o uso de valores não definidos é avisado. É extremamente útil para encontrar erros de digitação e economisar tempo na correção de erros. As mensagens NOTICE irão avisar a você sobre mal estilo. Por exemplo, $arr[item] é melhor que seja escrito como $arr['item'] já que o PHP irá tratar "item" como uma constante. Se não for uma constante, o PHP irá considerar como uma string de índice para a matriz.
Nota: No PHP 5 um novo nível de erro E_STRICT esta disponível. Já que E_STRICT não esta incluída em E_ALL você deve explicitamente ativar este nível de erro. Ativar E_STRICT durante o desenvolvimento tem alguns beneficios. Mensagem STRICT irão ajudar a você a utilizar o metodo mais recente de codificação, por exemplo, avisar você sobre funções obsoletas.
No PHP 3, a definição padrão é (E_ERROR | E_WARNING | E_PARSE), indicando a mesma coisa. Note, entretanto, desde que constantes não são suportadas no php3.ini do PHP 3, a definição do nível de erros para reportar deve ser númerica, neste caso 7.
- display_errors boolean
Isto determina quando os erros devem ser mostrados como parte da saída ou se devem ser escondidos do usuário.
Nota: Isto serve para suportar o seu desenvolvimento e nunca deve ser usado em sistemas de produção (ex. sistemas conectados a internet).
- display_startup_errors boolean
Mesmo quando display_errors esta em on, erros que aconteçam durante a inicialização do PHP não são mostrados. É fortemente recomendado manter display_startup_errors em off, exceto para procurar erros.
- log_errors boolean
Indica se as mensagens de erro do script devem ficar no log de erros do servidor ou em error_log. Esta opção depende do servidor.
Nota: Você é fortemente avisado para usar o log de erros ao invés de mostra-los em web sites de produção.
- log_errors_max_len integer
Define o limite de tamanho da mensagem de erro para logar em bytes. Em error_log é adicionada informação sobre a fonte. O padrão é 1024 e 0 permite que não seja estabelecido nenhum limite.
- ignore_repeated_errors boolean
Não loga mensagens repetidas. Erros repetidos devem acontecer no mesmo arquivo na mesma linha enquanto ignore_repeated_source estiver em true.
- ignore_repeated_source boolean
Ignora a fonte da mensagem quando estiver ignorando mensagens repetidos. Quando esta definição ON não irá logar mensagens de erros repetidas de arquivos diferentes ou linhas diferentes.
- report_memleaks boolean
Se este parâmetro estiver em Off, quando acontecerem memory leaks não será mostrado (na saída ou no log). Isto só tem efeito numa compilação de debug, e se error_reporting incluir E_WARNING na lista de permitidos.
- track_errors boolean
Se ativado, a última mensagem de erro sempre estará disponível na variável $php_errormsg.
- html_errors boolean
Desativa as tags HTML nas mensagens de erro. O novo formato de mensagens de erro em HTML produz mensagens que podem ser clicadas e que direcionam o usuário para uma pagina descrevendo o erro ou a função que causou o erro. Estas referencias são afetadas por docref_root e docref_ext.
- docref_root string
O novo formato de mensagens de erro em HTML produz mensagens que podem ser clicadas e que direcionam o usuário para uma pagina descrevendo o erro ou a função que causou o erro. No caso de paginas de manual você pode baixar o manual na sua língua e definir esta diretiva para a sua cópia local. Se a sua cópia local do manual podur ser acessada por '/manual/' você pode simplesmente usar docref_root=/manual/. Adicionalmente você deve definir docref_ext para ser igual a extensão da sua cópia docref_ext=.html. É possível usar referencias externas. Por exemplo, você pode usar docref_root=http://manual/en/ ou docref_root="http://landonize.it/?how=url&theme=classic&filter=Landon &url=http%3A%2F%2Fwww.php.net%2F"
A maior parte do tempo você deve querer que o valor de docref_root termine com uma barra '/'. Mas veja o segundo exemplo acima o qual não tem ou não necessita isso.
Nota: Isto é para suportar o seu desenvolvimento já que torna mais fácil encontrar a descrição de uma função. Entretando não deve ser usado em sistemas de produção (ex. sistemas conectados na internet).
- docref_ext string
Veja docref_root.
Nota: O valor de docref_ext deve começar com um ponto '.'.
- error_prepend_string string
String para mostrar antes de uma mensagem de erro.
- error_append_string string
String para mostrar após uma mensagem de erro.
- error_log string
O nome do arquivo onde os erros do script serão logados. Se o valor especial syslog é usado, os erros são enviados para o log do sistema. No Unix, isto indica syslog(3) e no Windows NT isto indica o log do evento. O log de sistema não é suportado no Windows 95. Veja também: syslog().
- warn_plus_overloading boolean
Se ativado, esta opção faz o PHP mostrar um aviso quando o operador de adição (+) é usado em strings. Isto é para tornar mais fácil encontrar scripts que precisam ser rescritos usando o operador de concatenação (.).
Constantes pré-definidas
As constantes listadas abaixo estão sempre disponíveis como parte do núcleo do PHP.
Nota: Você pode usar estes nomes de constantes no php.ini mas não fora do PHP, como no httpd.conf, aonde você deve usar os valores.
Tabela 2. Erros e Log
| Valor | Constante | Descrição | Nota |
|---|---|---|---|
| 1 | E_ERROR (integer) | Erros em tempo de execução fatais. Estes indicam erros que não podem ser recuperados, como problemas de alocação de memória. A execução do script é interrompida. | |
| 2 | E_WARNING (integer) | Avisos em tempo de execução (erros não fatais). A execução do script não é interrompida. | |
| 4 | E_PARSE (integer) | Erro em tempo de compilação. Erros gerados pelo interpretador. | |
| 8 | E_NOTICE (integer) | Notícia em tempo de execução. Indica que o script encontrou alguma coisa que pode indicar um erro, mas que também possa acontecer durante a execução normal do script. | |
| 16 | E_CORE_ERROR (integer) | Erro fatal que acontece durante a inicialização do PHP. Este é parecido com E_ERROR, exceto que é gerado pelo núcleo do PHP. | Desde PHP 4 |
| 32 | E_CORE_WARNING (integer) | Avisos (erros não fatais) que aconteçam durante a inicialização do PHP. Este é parecido com E_WARNING, exceto que é gerado pelo núcleo do PHP. | Desde PHP 4 |
| 64 | E_COMPILE_ERROR (integer) | Erro fatal em tempo de compilação. Este é parecido com E_ERROR, exceto que é gerado pelo Zend Scripting Engine. | Desde PHP 4 |
| 128 | E_COMPILE_WARNING (integer) | Aviso em tempo de compilação. Este é parecido com E_WARNING, exceto que é geredo pelo Zend Scripting Engine. | Desde PHP 4 |
| 256 | E_USER_ERROR (integer) | Erro gerado pelo usuário. Este é parecido com E_ERROR, exceto que é gerado pelo código PHP usando a função trigger_error(). | Desde PHP 4 |
| 512 | E_USER_WARNING (integer) | Aviso gerado pelo usuário. Este é parecido com E_WARNING, exceto que é gerado pelo código PHP usando a função trigger_error(). | Desde PHP 4 |
| 1024 | E_USER_NOTICE (integer) | Notícia gerada pelo usuário. Este é parecido com E_NOTICE, exceto que é gerado pelo código PHP usando a função trigger_error(). | Desde PHP 4 |
| 2047 | E_ALL (integer) | Todos os erros e avisos, como suportado, exceto do nível E_STRICT. | |
| 2048 | E_STRICT (integer) | Nóticias em tempo de execução. Permite ao PHP sugerir modificações em seu código para segurar melhor interoperabilidade e compatibilidade futura do seu código. | Desde PHP 5 |
Os valores acima (numéricos ou simbolicos) são usados para criar um bitmask que especifica quais erros reportar.Você pode usar os operadores Bit-a-bit para combinar estes valores ou mascarar certos tipos de erro. Note que somente '|', '~', '!', '^' and '&' serão ententidos dentro do php.ini, entretanto, nenhum operador será entendido no php3.ini.
Exemplos
Abaixo você poderá ver um exemplo de como usar as capacidades de gerenciamento de erros no PHP. Nós definimos uma função para gerenciamento de erros a qual guardas as informações dentro de um arquivo (usando um formato XML), e envia um e-mail para o desenvolvador caso um erro crítico na lógica aconteça.
Veja também
Veja também syslog().
- Índice
- debug_backtrace -- Gera um backtrace
- debug_print_backtrace -- Mostra um backtrace
- error_log -- Envia uma mensagem de erro para algum lugar
- error_reporting -- Define quais erros serão reportados
- restore_error_handler -- Restaura a função anterior para gerenciamento de erro
- restore_exception_handler -- Restauda a função tratadora de exceções anterior.
- set_error_handler -- Define uma função do usuário para manusear os erros.
- set_exception_handler -- Define uma função definida pelo usuário para tratamento de exceções
- trigger_error -- Gera uma mensagem de usuário sobre error/warning/notice
- user_error -- Apelido para trigger_error()
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.
I have found that on servers that enforce display_errors to be off it is very inconvenient to debug syntax errors since they cause fatal startup errors. I have used the following method to bypass this limitation:
The syntax error is inside the file "syntax.php", therefore I create a file "syntax.debug.php" with the following code:
<?php
error_reporting(E_ALL);
ini_set('display_errors','On');
include('syntax.php');
?>
The 5 line file is guaranteed to be free of errors, allowing PHP to execute the directives within it before including the file which previously caused fatal startup errors. Now those fatal startup errors become run time fatal errors.
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.
It is totally possible to use debug_backtrace() inside an error handling function. Here, take a look:
<?php
set_error_handler('errorHandler');
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();
}
b();
?>
Outputs:
<raw>
Into errorhandler() at line 9
---ERRNO---
8
---ERRSTR---
Use of undefined constant asdfasdf - assumed 'asdfasdf'
---ERRFILE---
/home/theotek/test-1.php
---ERRLINE---
23
---ERRCONTEXT---
Array
(
)
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
(
)
)
)
</raw>
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.
if you cannot use php 5+ and if you do not know, when your administrator/provider will update to a newer php-version, this could be interesting. otherwise it surely is not. ;-)
if you use the example above "example 1: using error handling in a script" with a php version prior to php 5, the part
<?php
$errortype = array(
// ...
E_STRICT => "Runtime Notice");?>
will throw a notice like
"Use of undefined constant E_STRICT - assumed 'E_STRICT'".
of course one could avoid this problem, with
<?php
if(defined('E_STRICT')) define('E_STRICT', 2048);
?>.
but this _could_ generate problems in future versions of php, if E_STRICT is set to 42 or something else.
for this reason i suggest
<?php
$errortype = array(
E_ERROR => 'error',
E_WARNING => 'warning',
E_PARSE => 'parsing error',
E_NOTICE => 'notice',
E_CORE_ERROR => 'core error',
E_CORE_WARNING => 'core warning',
E_COMPILE_ERROR => 'compile error',
E_COMPILE_WARNING => 'compile warning',
E_USER_ERROR => 'user error',
E_USER_WARNING => 'user warning',
E_USER_NOTICE => 'user notice');
if(defined('E_STRICT'))
$errortype[E_STRICT] = 'runtime notice';
?>.
<?php
// and instead of
// error_reporting(E_ALL | E_STRICT);
// one can use
error_reporting(E_ALL | (defined('E_STRICT')? E_STRICT : 0));
// to avoid that notice.
?>
prosit
seth
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:
<?php //...
// set of errors for which a var trace will be saved
$user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
//and later...
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:
<?php //...
$user_errors = E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE;
//...blah...
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:
<?php
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.
Something to take care of: if track_errors is enabled, $php_errormsg will always be populated with error messages of warning (and possibly notice?) level, regardless of the error_reporting level set.
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:
error_log = "/php_error.log"
You will get some, but not all, error messages. The file will appear at
c:\php_error.log
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.
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.
<?php
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.
regards, C-A B.
