Carp-Notify

 view release on metacpan or  search on metacpan

lib/Carp/Notify.pm  view on Meta::CPAN

            if ($arg =~ /^$settables$/o){
                $init{$arg} = shift;
            }
            else {$errors .= "\t$arg\n"};
        };

        %init = (%def, %init);

        my( $stored_vars, $stack, $environment ) = ( '', '', '' );

        $stored_vars = store_vars()  if $init{'store_vars'};
        $stack       = stack_trace() if $init{'stack_trace'};
        $environment = store_env()   if $init{'store_env'};

        my $message = "";

        my $method = $Carp::Notify::fatal ? 'explosion' : 'notification';

        $message .= "An error via $method occurred on " . today() . "\n";

        $message .= "\n>>>>>>>>>\nERROR MESSAGES\n>>>>>>>>>\n\n$errors\n<<<<<<<<<\nEND ERROR MESSAGES\n<<<<<<<<<\n"          if $errors;
        $message .= "\n>>>>>>>>>\nSTORED VARIABLES\n>>>>>>>>>\n\n$stored_vars\n<<<<<<<<<\nEND STORED VARIABLES\n<<<<<<<<<\n" if $stored_vars;
        $message .= "\n>>>>>>>>>\nCALL STACK TRACE\n>>>>>>>>>\n\n$stack\n<<<<<<<<<\nEND CALL STACK TRACE\n<<<<<<<<<\n"       if $init{'stack_trace'};
        $message .= "\n>>>>>>>>>\nENVIRONMENT\n>>>>>>>>>\n\n$environment\n<<<<<<<<<\nEND ENVIRONMENT\n<<<<<<<<<\n"           if $init{'store_env'};

        log_it(
            "log_it"         => $init{'log_it'},
            "log_file"       => $init{'log_file'},

            "log_explode"    => $Carp::Notify::fatal && $init{"log_explode"} ? $init{"log_explode"} : 0,
            "explode_log"    => $init{'explode_log'},

            "log_notify"     => ! $Carp::Notify::fatal && $init{"log_notify"} ? $init{"log_notify"} : 0,
            "notify_log"     => $init{"notify_log"},

            "message"        => $message,
            "error_function" => $init{'error_function'}
        );

        simple_smtp_mailer(
            "email"          => $init{'email'},
            "return"         => $init{'return'},
            "message"        => $message,
            "subject"        => $init{'subject'},
            "smtp"           => $init{'smtp'},
            "port"           => $init{'port'},
            "error_function" => $init{'error_function'}
        ) if $init{'email_it'};

        if ($Carp::Notify::fatal){
            if ($init{'die_quietly'}){
                exit;
            }
            elsif ($init{'death_function'}){
                if (ref $init{'death_function'} eq 'CODE'){
                    $init{'death_function'}->(%init, 'errors' => $errors);
                }
                else {
                    # this wants rework, badly
                    no strict 'vars';
                    my ($calling_package) = (caller)[0];
                    my $package = $calling_package . "::";
                    $package = $1 if $init{'death_function'} =~ s/(.+::)//;
                    $init{'death_function'} =~ s/^&//;
                    &{$package . $init{'death_function'}}(%init, 'errors' => $errors);
                    exit;
                };
            }
            else {
                if ($init{'die_to_stdout'}){
                    print STDERR $init{'death_message'} if $init{'die_everywhere'};
                    print $init{'death_message'};
                    exit;
                }
                else {
                    print $init{'death_message'} if $init{'die_everywhere'};
                    die $init{'death_message'};
                };
            };
        }
        else {
            $Carp::Notify::fatal = 1;
            return;
        };
    };
};


# psst!  If you're looking for store_vars, it's up at the top wrapped up with import!

sub store_env {
    my $env = '';
    foreach (sort keys %ENV){
        $env .= "\t$_ : $ENV{$_}\n";
    };
    return $env;
};

sub stack_trace {
    my $caller_count = 1;
    my $caller_stack = undef;
    my @verbose_caller = ("Package: ", "Filename: ", "Line number: ", "Subroutine: ", "Has Args? : ", "Want array? : ", "Evaltext: ", "Is require? : ");

    push @verbose_caller, ("Hints:  ", "Bitmask:  ") if $] >= 5.006; # 5.6 has a more verbose caller stack.

    while (my @caller = caller($caller_count++)){
        $caller_stack .= "\t---------\n";
        foreach (0..$#caller){
            $caller_stack .= "\t\t$verbose_caller[$_]$caller[$_]\n" if $caller[$_];
        };
    };

    $caller_stack .= "\t---------\n";
    return $caller_stack;
};

sub log_it {
    my %init = @_;

    my $message  = $init{message};

lib/Carp/Notify.pm  view on Meta::CPAN

        print MAIL $i_say if $i_say;
        my $response = <MAIL> || "";

        if (! $response || $response =~ /^[45]/){
            $i_die =~ s/\?/$response/;
            return error($init{'error_function'}, $i_die);
        };
        return error($init{'error_function'}, "Server disconnected: $response") if $response =~ /^221/;

    };
    # built

    # send the data
    print MAIL "Date: ", today();
    print MAIL "From: $init{'return'}";
    print MAIL "Subject: $init{'subject'}";
    print MAIL "To: $init{'email'}";
    print MAIL "X-Priority:2  (High)";
    print MAIL "X-Carp-Notify: $Carp::Notify::VERSION";

    print MAIL "";

    $message =~ s/^\./../gm;
    $message =~ s/(\r?\n|\r)/\015\012/g;

    print MAIL $message;

    print MAIL ".";
    # sent

    return 1; # yay!
};

sub today {
    my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
    my @days   = qw(Sun Mon Tue Wed Thu Fri Sat);

    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
    $year += 1900;
    my ($gmin, $ghour, $gsdst) = (gmtime(time))[1,2, -1];

    my $diffhour = $hour - $ghour;
    $diffhour = 12 - $diffhour if $diffhour > 12;
    $diffhour = 12 + $diffhour if $diffhour < -12;

    ($diffhour = sprintf("%03d", $diffhour)) =~ s/^0/\+/;

    return sprintf("%s, %02d %s %04d %02d:%02d:%02d %05s",
        $days[$wday], $mday, $months[$mon], $year, $hour, $min, $sec, $diffhour . sprintf("%02d", $min - $gmin));
};

# error does nothing unless you specify the error_function, in that case it's called with the error provided.
sub error {
    my ($func, $error) = @_;
    if (ref $func eq 'CODE'){
        $func->($error);
    }
    elsif ($func){
        # this wants reworked
        no strict 'refs';
        my ($calling_package) = (caller)[0];
        my $package = $calling_package . "::";
        $package = $1 if $$func =~ s/(.+::)//;
        &{$package . $func}($error);
    }
    else {
        return;
    };
};


1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Carp::Notify - Loudly complain in lots of places when things break badly

=head1 VERSION

version 1.13

=head1 SYNOPSIS

Use it in place of die or croak, or warn or carp.

 # with Carp;
 use Carp;
 if ($something_a_little_bad) { carp("Oh no, a minor error!")};
 if ($something_bad) { croak ("Oh no an error!")};


 # with Carp::Notify;
 use Carp::Notify;
 if (something_a_little_bad) {notify("Oh no, a minor error!")};
 if ($something_bad) { explode ("Oh no an error!")};

=head1 DESCRIPTION

Carp::Notify is an error reporting module designed for applications that are running unsupervised (a CGI script, for example,
or a cron job).  If a program has an explosion, it terminates (same as die or croak or exit, depending on preference) and
then emails someone with useful information about what caused the problem.  Said information can also be logged to a file.
If you want the program to tell you something about an error that's non fatal (disk size approaching full, but not quite
there, for example), then you can have it notify you of the error but not terminate the program.

Defaults are set up within the module, but they can be overridden once the module is used, or as individual explosions take place.
B<Please> set up your appropriate defaults in the module.  It'll save you headaches later.

=head1 IMPORTANT NOTE

This version is nearly identical to, and I<is> bug-for-bug compatible with, version 1.10 which has been on CPAN
for years but has not been indexed.

This public release is intended to catch the attention of anyone actually using this module and let them know
that changes are coming!



( run in 1.976 second using v1.01-cache-2.11-cpan-e93a5daba3e )