Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: errorHandler
Forum PHP.pl > Forum > PHP > Pro > Archiwum Pro
e-Gandalf
Witam.
Jak mozna wyczytac z tytulu zastanawiam sie nad optymalnym rozwiazaniem oblugi bledow w CMSie. (mowa o php 4 - no exceptions)

Obsluga bledow sklada sie z dwoch podelementow:

1) Obsluga bledow skladni - zglaszanych przez silnik php i przechwytywanych przez error_handler

2) Obsluga bledow logicznych i algorytmicznych, niewykrywalnych dla php. Zglaszanych z poziomu kodu.

Martwia mnie obydwa problemu, ale z roznych wzgledow. Pierwszy, dlatego, ze php zglasza szalenie mala ilosc informacji o bledzie (np. nie ma mozliwosci uzyskania inforamcji o linii w ktorej nastapil blad!!!).
Drugi, z powodu (tak podejrzewam) malego doswiadcznia z tematem.

Na poczatku nie wiedzialem wogule jak podejsc do tematu i lazilem wokol niego jak pies wokol jeza. W koncu sprecyzowalem zalozenia obslugi bledow. Musi obslugiwac jak najwiekszy zakres bledow, kontrolowac stabilnosc aplikacji, obslugiwac "tranzakcje" (*1) oraz w jak najlatwiejszy sposob integrowac sie z CMSem (*2).

*1) chodzi o system podobny do uzywanego w bazach danych. Jesli kawalek kodu ma wykonac logiczna operacje "dodania konta" ktora sklada sie z dodania wpisu do tablicy |accounts|, dodania wpisu do tablicy |account_privs| oraz dodania dwoch katalogow (zalozmy!!) to fajnie by bylo, moc to latwo wycofac jest cokolwiek pojdzie nie tak.

*2) Innymi slowy, aby latwo i czysto wygladalo w CMSie wybor czy wyswietlac dalej skrypt czy juz komunikat o bledzie.

Wstepnie zaprojektowalem cos w tym stylu:

[php:1:f44bd586cd]<?php
<?php
/**************************************************
*
* Error Class. Handling errors
*
***************************************************
*
* No table related.
*
***************************************************
*
* Detail description
* @author Zbigniew Braniecki (gandalf@przeglad.com.pl)
* @version 1.0 M1
* @copyright Zbigniew Braniecki
* @access private
* @relase_date 08.10.2002
*
***************************************************
*
* Short Description
*
* Variables:
* errorlevel - Describes status of system.
* Possible codes are:
* 0 - no error
* 1 - notice error - something might be wrong, but it miht be ok too
* 2 - warning error - something is wrong, but script works
* 3 - rollback error - error in setting data. should be rolled back and warned
* 4 - security error - there was a try of illegal access
* 5 - fatal error - module wont work.
* 6 - gcms error - gcms wont run
*
* errors - Array of errors code with modules name and description.
* "code" - Code number
* "trasaction" - which transaction was active?
* "module" - Module name
* "action" - Action
* "description" - Description
*
* Methods:
*
* SetErrorLevel($level,$force=false)
* $force - if set (boolean) New errorlevel is forced even if the old one was higher.
*
* AddError($lvl,$module,$desc)
* Adds error to array of errors
*
* AddToErrFile($module,$desc,$rubbish)
* $rubbish - if there can by any parts (sql rows or files) to clean up, write them down here.
* Adds error to error file.
*
* RunCapture()
* System captures php errors and log them.
*
***************************************************
*
* Known bugs and problems
*
***************************************************
*
* Notes
*
***************************************************/
class ErrorClass {
var $errorlevel = 0;
var $errors = Array('cms'=>Array(), 'code'=>Array());
var $debug_mode = true;
var $security = false;
var $php_errcode = Array(1=>6, 2=>5, 4=>6, 8=>1, 16=>6, 32=>5, 64=>6, 128=>5, 256=>5, 512=>5, 1024=>1, 2056=>-1);

var $transactions = Array();

function SetErrorlevel ($level, $force=false) {
if (($level>$this->errorlevel) || $force) {
$this->errorlevel = $level;
}
return true;
}

function CreateTransaction ($name) {
$this->transactions[] = Array('name' => $name, 'rollback' => Array(), 'errors'=> false);
return key($this->transactions);
}

function FinishTransaction ($id) {
unset($this->transactions[$id]);
return true;
}

function Rollback ($tr_id, $module, $method, $argList) {
$this->transactions[$tr_id]['rollback'][] = Array('module'=>$module, 'method'=>$method, 'arglist'=>$argList);
return true;
}

function AddError ($lvl, $module, $action, $desc, $tr_id=false, $type='cms') {
$GLOBALS['system']->reload = false;
$this->SetErrorlevel($lvl);
switch ($lvl) {
case 0:
$code=$GLOBALS['sysdict']['error_no_error'];
break;
case 1:
$code=$GLOBALS['sysdict']['error_notice'];
break;
case 2:
$code=$GLOBALS['sysdict']['error_warning'];
break;
case 3:
$code=$GLOBALS['sysdict']['error_rollback'];
break;
case 4:
$code=$GLOBALS['sysdict']['error_security'];
break;
case 5:
$code=$GLOBALS['sysdict']['error_major'];
break;
case 6:
$code=$GLOBALS['sysdict']['error_blow'];
break;
default:
$code=$GLOBALS['sysdict']['error_unknown'];
}

if ($tr_id === false) {
if (isset($this->transactions[key($this->transactions)])) {
$tr_name = $this->transactions[key($this->transactions)]['name'];
$this->transactions[key($this->transactions)]['errors'] = true;
$tr_id = key($this->transactions);
} else {
$tr_name = '--';
}
}elseif ($tr_id !== '--') {
if (isset($this->transactions[$tr_id])) {
$tr_name = $this->transactions[$tr_id]['name'];
$this->transactions[$tr_id]['errors'] = true;
}else{
$tr_name = '--';
}
}
$this->errors[$type][] = Array('code'=>$code, 'transaction' => $tr_name,'module'=>$module, 'action'=>$action, 'description'=>$desc);
$this->AddToErrFile ($code, $module, $action, $desc);
foreach ($this->transactions as $t) {
foreach ($t['rollback'] as $e) {
eval('$GLOBALS["'.$e['module'].'"]->'.$e['method'].'('.implode($e['arglist'], ',').');');
}
}
if ($type=='code') {
print('<br>'.$GLOBALS['sysdict']['error_code'].': ');
print_r(current($this->errors[$type]));
die($GLOBALS['sysdict']['stop']);
}
return true;
}

function AddToErrFile ($lvl, $module, $action, $desc) {
$fh=fopen('../admin/error.log','a');
fputs($fh,date('[d-m-Y H:i]').' '.$GLOBALS['sysdict']['error'].' ('.$lvl.') '.$GLOBALS['sysdict']['in_module'].' - '.$module.' '.$GLOBALS['sysdict']['in_action'].' - '.$action.' - '.$desc."n");
fclose($fh);
}

function RunCapture(){
function ErrorHandler ($errno, $errstr, $errfile, $errline, $errcontexa) {
global $error;
$error->SetErrorlevel($error->php_errcode[$errno]);
$error->AddError($error->php_errcode[$errno], ' - ', ' - ', $GLOBALS['sysdict']['in_file'].' '.$errfile.', '.$GLOBALS['sysdict']['in_line'].' '.$errline, false, $GLOBALS['sysdict']['code']);
}
set_error_handler('ErrorHandler');
return true;
}

// DONE - 08.10.2002
///////////////////////////////////////////////////////
}
?>
?>[/php:1:f44bd586cd]

(sysdict to slownik CMSa)


uzycie:

[php:1:f44bd586cd]<?php

$tr_id = $errors->CreateTransaction('Adding Account');
if (!mysql_query($q_tmp)) {
$errors->AddError(3, 'Account', 'Adding Account', 'Account was not added due too Mysql Error nr. '.mysql_errno().' - '.mysql_error(), $tr_id);
return false;
}
$curr_id = mysql_insert_id();
$errors->Rollback($tr_id, 'account', 'Remove', Array($curr_id)); // For both
if (!$access->SetPrivileges($curr_id)) {
$errors->AddError(3, 'Account', 'Adding Account', 'Setting Privilages failed', $tr_id);
return false;
}
$errors->FinishTransaction($tr_id);
?>[/php:1:f44bd586cd]

Czyli na ludzki:

1) Rozpocznij tranzakcje
2) Dodaj konto do bazy - jesli sie nie powiedzie zwroc blad (tranzakcja zostanie zatrzymana, ale nie cofnieta - brak Rollbacka)
3) Dodaj rollback
4) dodac uprawnienia - jesli padnie tranzakcja zostanie cofnieta i rollback uruchomiony
.
. tutaj mozna dodawac kolejne elementy
.
n) Zakoncz tranzakcje.


Moj problem jest prosty. Chcialbym Was prosic o pomoc w udoskonaleniu tego, oczyszczeniu... bo napisalem to pewien czas temu i do dzis nie mam pomyslu jak to usprawnic. Mam ogromna nadzieje, ze swierze spojrzenie na problem waszych oczu popchnie cala sprawe do przodu. smile.gif
Bede wdzieczny za kazda sugestie smile.gif

P.S. Zastanawialem sie czy to nie do Oceny, ale zamiast oceny wolalbym teoretyczna chocby dyskusje o samych zalozeniach takiego errorHandlera... moze ja wogule w zla strone ide?
e-Gandalf
Co poradzic jak jeszcze dobrego nie znalazlem? (dobrego - w zaden sposob nie ingerujacego w wyglad strony, a jedynie udostepniajacego mi bogate API do standardowych elementow obslugi strony. Szybkie, stabilne itp...)

Nie moglem zajrzec do linkow, ktore podales. A z mila checia bym zajrzal smile.gif Odmowilo mi dostepu. Gdzie moge zobaczyc? smile.gif

Co rozumiesz przez debugowanie?
e-Gandalf
Swietnie. Faktycznie, jestes boski. Bardzo podobaja mi sie algorytmy ktore zastosowales, ciesze sie ze moge z Toba porozmawiac o technologiach, podobaja mi sie Twoje rozwiazania.

Jesli kiedys spytasz o cokolwiek na tym forum postaram Ci sie pokazac kod html wynikowy u mnie...

Co do drugiej czesci - no coz, zeby debugowac jawnie jezyk przydalby sie drugi poziom - praca z debugowaniem php z poziomu php jest raczej pomyslem jalowym (zapraszam do watku "wlasny jezyk"). Tak trafiles na FORUM php. Jesli rozmawiamy o technologiach, to prezentowanie kodu wynikowego oraz stringa jaki wywala w zaden sposob nie miesci sie w jego granicach.
cagrET
czlowieku o czym ty mowisz ?
www.google.com - skrypty do ktorych podalem linki sa open source, wystarczylo poszukac, nazwe znales

chcesz zeby ci wszystko na tacy podac ?
kwiateek
Cytat
Martwia mnie obydwa problemu, ale z roznych wzgledow. Pierwszy, dlatego, ze php zglasza szalenie mala ilosc informacji o bledzie (np. nie ma mozliwosci uzyskania inforamcji o linii w ktorej nastapil blad!!!).

Hmm, a o __FILE__ i __LINE__ to sie nie slyszalo... ?
e-Gandalf
Cytat
czlowieku o czym ty mowisz ?
www.google.com - skrypty do ktorych podalem linki sa open source, wystarczylo poszukac, nazwe znales


Geez... masz racje smile.gif

Nawet nie sprawdzilem w googlach. Uznalem, ze to _musi_ byc Twoja autorska technologia, tylko niewiedziec czemu podajesz mi jedynie wynik jej pracy ;p

Cytat
chcesz zeby ci wszystko na tacy podac ?


Nie, chce porozmawiac o metodach obslugi bledow!!!
e-Gandalf
Cytat
Hmm, a o __FILE__ i __LINE__ to sie nie slyszalo... ?


Problem polega na tym, ze jesli powiedzmy ustawie:

[php:1:f65ebe530a]<?php
function ErrorHandler ($errno, $errstr, $errfile, $errline, $errcontexa) {
global $error;
print(__LINE__);
$error->SetErrorlevel($error->php_errcode[$errno]);
$error->AddError(...);
}
set_error_handler('ErrorHandler');
?>[/php:1:f65ebe530a]

to __LINE__ zwroci mi linie w ktorej poszedl print. A nie linie w ktorej powstal blad.

Ale znalazlem *^^*. $errline zwraca linie.
cagrET
polecam debug_backtrace()
bulek
Poniewaz sam zastanawialem sie nad przechwytywaniem bledow w CMSie kiedys przyszla mi do glowy mysl ktora potem zreszta gdzies wyczytalem - czyli nie jest to tylko moja chora wyobraznia smile.gif. Do obslugi bledy mozna zastosowac ... curl'a. Ogolnie robi sie to poprzez stworzenie z curla proxy.
Zapytanie idzie do proxy ten za pomoca curla pobiera dana strone jesli zobaczy jakis blad /apach lub regexpy sprawdzajace co jest na outpucie/ odsyla na odpowiednia strone.
Mozna tez wplesc curla do srodka aplikacji i zaprzac go do obslugi konkretnych modulow. To jest fajne bo mozemy wtedy dosc latwo przeniesc
czesc aplikacji na inny serwer z mala zmiana w configuracji.
Moze to troszke pojechane ale powninno dzialac smile.gif
dooshek
Cytat
polecam debug_backtrace()

A ja polecam bardzo fajny modul do php Xdebug. To cudo po wywolaniu bledu pokazuje stos wywołań - działa podobnie jak debug_backtrace ale działa przy każdym błędzie. Używam tego juz od 2 miesięcy i żyć bez tego ciężko - debugowanie jest dosyć proste teraz bo widać co się "po drodze" działo.

http://www.xdebug.org/

Aha, rozszerzenie dziala pod winda i unixowymi - natomiast ma problemy z dzialaniem z roznymi innymi rozszerzeniami (np. z Turck MMCache sad.gif )
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.