Page 1 of 2

Exceptions and logging

Posted: Wed Aug 26, 2009 3:41 am
by m4rw3r
I'm creating a library in which I use exceptions a lot for the errors.
I've also created a simple observer pattern for logging, but I wonder if the logging is needed when I throw exceptions.

Should my library facilitate a way for the user to hook his own logging code, or should I just ignore logging completely and use exceptions instead?
(Ie. let the user catch the exceptions and then log their messages)

Re: Exceptions and logging

Posted: Wed Aug 26, 2009 12:50 pm
by alex.barylski
I guess it would depend on the type of errors you are catching with exceptions. Fatal errors like file permissions, etc...might be useful to log. Maybe you could just add logging code in the catch block?

Re: Exceptions and logging

Posted: Wed Aug 26, 2009 1:11 pm
by m4rw3r
That was what I'm wondering. In my library I (almost) don't have any try-catch blocks at all, so I wonder if there would be any benefit to log an error (via the observer-like thing I've made) before passing it off as an exception?

Maybe I should log things which aren't fatal? (I have very very few of those) Or should I just throw an exception to be consistent?

Re: Exceptions and logging

Posted: Wed Aug 26, 2009 3:42 pm
by Darhazer
In my opinion it should log only in debug mode :)\

Well, it hardly depends of how error can occur. I mean for example there can be an exception that an image can't be created, and it can occur on 5 different places in the function... it can be pointless to throw exception about the internals - why exactly the image can be created, but to throw just that the operation failed. And in this case, a log showing the entire process and which step failed might be useful.

Re: Exceptions and logging

Posted: Wed Aug 26, 2009 4:29 pm
by alex.barylski
Logging isn't something I would want done by a 'library' it's application specific so unless your including a bootstrap with your library I would leave the logging to the client developer. Basically let them specify the way they want to log errors, either to DB or file or some remote source, etc. Also whether they want logging for produciton or just test environments, like noted above.

Re: Exceptions and logging

Posted: Thu Aug 27, 2009 1:09 am
by m4rw3r
It is a kind of bootstrap, you register a function/method which will receive the log messages.

But usually I throw an exception right after I've logged an error, I can just remove the error logging in that case as the user will get the exception.
Which means that I can remove all error logging.

Exceptions have nice stack traces and everything, so debug messages aren't so usable in that respect—for me as the library developer, that is
So debug messages, what kind of information may be useful for the library user? (It is my Object-Relational-Mapper and database abstraction)

Re: Exceptions and logging

Posted: Sat Aug 29, 2009 7:34 pm
by Ollie Saunders
How does this sound?: Bundle a logger object with the thrown exception and trigger the log with something akin to:

Code: Select all

set_exception_handler(function($e) {
    if (!$e instanceof YurExp) { $e = with(new YurExp)->newFromStndPhpExp($e); }
    if (!$e->doLog()) { echo $e->logFailReport(); }
    echo $e->report(); });
Actually that if (!$e instanceof ... stuff should probably be within $e. So you just have:

Code: Select all

$e = with(new YurExp)->newFromExp($e);
which returns $this if instanceof self and does the newFromStndPhpExp() stuff otherwise.

I can elaborate this if I'm being unclear.

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 4:19 am
by m4rw3r
Well, why should I bundle a logger object if the user already has his own exception logging code (eg. in the case of a framework)?

I don't really think this is a good idea for a library, as the user needs to learn how to handle those loggers too.
It is a lot easier to treat the exceptions from my lib as normal exceptions without anything special (as a logger).

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 4:38 am
by Eran
Most libraries provide the option of throwing exceptions or just logging silently. The reason you might want to include a form of logging in your library is that you don't want users to have to go through the source to inject logging logic - that is both tedious and makes upgrading to a newer version difficult. Provide an interface to receive a full stack of error messages in case exceptions are off, and allow users to use their own logging solutions to integrate with it.

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 6:01 am
by m4rw3r
How would the optimal implementation of an error stack look like?

And how should I replace exceptions with the error stack? What are the benefits?

Personally I think the exceptions are good, because they send their error directly to the programmer/user.
Because it is a database abstraction I'm creating, I think it is important that the user receives the errors as early in the process as possible, to prevent the code from continuing to run after an error has been encountered.

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 6:15 am
by Eran
I use exceptions too in my code, but I'm aware that plenty of developers don't. If you're building a library you should consider accommodating multiple styles.

Code: Select all

$db = new Database(array('throwExecptions' => false));
if( $db -> connect() ) {
    //Success!
} else {
    $errors = $db -> getErrors();
    //Display / log errors, redirect or ignore
}
This way you leave the error handling to the discretion of the user.

In my opinion, the optimal *non exception* stack would be an array of errors, each error being an array of messages. For example:

Code: Select all

$errors = array(
    0 => array(
        'hostname' => 'Hostname was not specified',
        'credentials' => 'Credentials are invalid',
        'service' => 'MySQL service was not found'
    )
);
You can replace the associative keys with numerical codes, which is common practice.

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 6:36 am
by m4rw3r
So it is something like this:

Code: Select all

if($c = Db::getConnection())
{
    if($r = $c->query('Somequery'))   // what if the query returns false?
    {
        // some code
    }
    else
    {
        // something:
        var_dump(Db::getErrors());
    }
}
else
{
    // something:
    var_dump(Db::getErrors());
}
I think exceptions make it a lot easier:

Code: Select all

try
{
    $c = Db::getConnection();
    $c->query('somequery');
    // some code
}
catch(Db_Exception $e)
{
    // dumps eg. a Db_Exception_InvalidConfig
    var_dump($e);
}
+ they enable the user to just catch special errors, so a connection error can eg. be sent to the main error handler, while a query error is handled locally.

So I'm a bit skeptical to this error stack. What are the real benefits?
From what I see it is just more work and makes it more complex to use.

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 6:41 am
by Eran
The problem with exceptions is that they -
1. Stop execution if not caught (fatal error)
2. Provide a lot of information that might not be relevant in the stack

They are useful for debugging / developing, but for a plugable library you might just want to know what went wrong and not start to look through a series of files and line-numbers to understand what you did wrong.

As I said, I do use exceptions myself. But there developers who don't, and if you're planning on having those use your library you should be willing to accommodate...

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 6:55 am
by m4rw3r
I think the stop execution thing is good in this case, because it prevents bad things from happening.
Eg. an insert fails, then the user tries to add a few rows which are related with the auto-incremented id of the inserted row.
That would mean it will either violate constraints or it will produce orphaned rows.

I think I'll use warnings (E_USER_WARNING or E_USER_NOTICE, via trigger_error()) for the non fatal things, then it won't be too much work.
Does that sound ok?

Re: Exceptions and logging

Posted: Sun Aug 30, 2009 6:59 am
by Eran
You are taking away the developers ability to decide what should stop execution or not. That is my point - that people have separate methods of handling errors.

In my opinion using trigger_errors() is worse, since you can't "catch" it like you do with exceptions (aside from creating a custom error handler). That means the developers has to set it his own checks to avoid your library from throwing errors