Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am looking for a convenient and reliable method to customize errors and warnings autogenerated by perl, things like:

use of uninitialized variable in ... undefined subroutine ... called at ... can't use string("") as a HASH ref ...

I just want to be able to customize these messages by prepending a timestamp .. something like this would be ideal

use Error::Customize; $customize = sub { return $makeatimestamp->() . $_[0]; };

I could probably hack this together with __WARN__ and __DIE__ handlers, but I'm sure there's some gotcha's, and someone must have done this before.

Replies are listed 'Best First'.
Re: error/warn customization
by wind (Priest) on Feb 14, 2011 at 21:56 UTC
    JavaFan is right, as that is exactly what the __WARN__ and __DIE__ handlers are intended for:
    use strict; use warnings; # Customize Warning messages. BEGIN { $SIG{'__WARN__'} = sub { warn localtime . ': ' . $_[0] }; $SIG{'__DIE__'} = sub { die localtime . ': ' . $_[0] }; } my $foo = 10; my $foo = 20; # warning about duplicate my $foo, die "Goodbye world";
Re: error/warn customization
by JavaFan (Canon) on Feb 14, 2011 at 20:57 UTC
    The __WARN__ and __DIE__ handlers are there to do things like you describe.
Re: error/warn customization
by ELISHEVA (Prior) on Feb 15, 2011 at 10:25 UTC

    The gotcha is that the very thing that makes it attractive: being able to make once change and have it affect everything. Your handlers will trump the handlers of the code you are running and anyone running your code and installing their own handlers will trump your handlers. You could avoid this problem by localizing your setting of __WARN__ and __DIE__ but then you will interfere with a caller's attempt to gain the exact sort of control you want to have.

    The lesson in all of this is that handlers are not the way to go in production code that will be used by other programmers and incorporated into their own work. There Use __WARN__ and __DIE__ liberally for testing and debugging, but not in production code.

    The desire to include a time stamp sounds like you are trying to do a poor man's logging. If you respond to errors using a module like Log::Log4Perl you will get timestamps and much more.

    As for less disruptive global solutions, you might consider a combination of autodie and custom definitions for CORE::die and CORE::warn (yes, you can do that). You can even call Log4Perl inside your custom die and warn methods, if you decide that fits your needs.

    autodie converts Perl error messages into thrown exceptions. Setting CORE::GLOBAL::die and CORE::GLOBAL::warn are preferred to handlers for two reasons: First, it means that testers and debuggers can still use __DIE__ and __WARN__ as they wish. The other reason for doing things this way is that in the future __DIE__ may not be triggered within evals. The perldocs for %SIG consider resetting CORE::GLOBAL::die as the preferred method for overriding die behavior within code - see perlvar and search for __DIE__.

    Code to redefine the core functions would look like this:

    use autodie; BEGIN { sub myDie { my $e=shift; die localtime() . ": $e"; }; sub myWarn { my $e=shift; warn localtime() . ": $e"; } *CORE::GLOBAL::die = \&myDie; *CORE::GLOBAL::warn = \&myWarn; }