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

I'm writing a web app that i want to log various actions with a homebrew logger.

My app is CGI::Applicaiton/HTML::Template and is failing when I make the call to my logger module. If I comment out the call to the logger module everything works ok.

Apache fails with the message:
Premature end of script headers: /var/www/cgi-bin/portal/addr/app_addr.pl

While i know what that message literally translates into (ie a web page without headers), I cant work out how i'm getting this message (or find the content that is creating this message).

I'm not sure if this is maybe a perm problem with apache, or if my logger is buggy.

Here is the code for my logger

package Logger; $VERSION = 1.00; use strict; use vars qw( $AUTOLOAD ); use Data::Dumper; use Carp; { #Encapsulated class data my %_log_attr = # DEFAULT ACCESSIBILITY ( _name => ['DEFAULT', 'read/write'], _handle => [undef, 'read'] ); #is a specirfied object attribute accessible in a given mode sub _accessible { my ($self, $attr, $mode) = @_; $_log_attr{$attr}[1] =~ /$mode/ } # Classwide default value for a specified object attributes sub _default_for { my ($self, $attr) = @_; $_log_attr{$attr}[2]; } # list of names of all specified object attributes sub _standard_keys { keys %_log_attr; } # return datestamp sub _date { my @date=localtime; ++$date[4]; if (length($date[3])eq 1 ) {$date[3]='0'.$date[3]}; if (length($date[4])eq 1 ) {$date[4]='0'.$date[4]}; $date[5]=$date[5]+1900; return($date[3].$date[4].$date[5],"$date[3]-$date[4]-$date[5]" +); } # return timestamp sub _time { my @time=localtime; ++$time[4]; if (length($time[2])eq 1 ) {$time[2]='0'.$time[2]}; if (length($time[1])eq 1 ) {$time[1]='0'.$time[1]}; return($time[2].$time[1].$time[0],"$time[2]:$time[1]:$time[0]" +); } } sub new { my ($caller, %arg) = @_; my $caller_is_obj = ref($caller); my $class = $caller_is_obj || $caller; my $self = bless {}, $class; foreach my $attrname ($self->_standard_keys() ) { my ($argname) = ($attrname =~ /^_(.*)/); if (exists $arg{$argname}) { $self->{$attrname} = $arg{$argname} ; } elsif ($caller_is_obj) { $self->{$attrname} = $caller->{$argname}; } else { $self->{$attrname} = $self->_default_for($attrname) } } $self->{_handle}=&prepare_file($self); return $self; } sub prepare_file { my $self = shift; if ($self->{_name}) { if ($self->{_name} =~ /^[\w\.]+$/) { my @ds = $self->_date(); my $name = '>>'.$self->{_name}.'.'.$ds[0].'.log'; local*LOGFILE; open(LOGFILE, $name) || carp "Unable to open file: $!"; return *LOGFILE; } else { carp "You may only use alphanumerics, dot <.> and undersco +re <_> in names.\n"; return undef; } } } sub log { my ($self, $location, $message) = @_; if ($self->{_handle}) { print {$self->{_handle}} $self->_date().' '.$self->_time().", $$ +, $location, $message\n"; } else { carp "Must call logger->new(name=>'<logfile>') before writing +log.\n"; } } 1

If anyone could shine a light on what could be going on here, i'd appreciate it.

Credits to Conway for the OO framework.

Replies are listed 'Best First'.
Re: Web App logging
by dws (Chancellor) on Feb 02, 2002 at 04:37 UTC
    If anyone could shine a light on what could be going on here, i'd appreciate it.

    You might get some mileage out of turning off buffering in your CGI, and then make sure you're emitting a correct header buffer invoking your Logger. A couple of things could be going wrong inside of Logger, including permission problems trying to open the log file for append. Emitting a header first will get you post the error you're seeting, and should put you within sight of the underlying error.

    Also, it's wise not to include unescaped HTML entities (e.g., "<>") in your error/warning messages.

(crazyinsomniac) Re: Web App logging
by crazyinsomniac (Prior) on Feb 02, 2002 at 04:46 UTC
Re: Web App logging
by talexb (Chancellor) on Feb 02, 2002 at 04:48 UTC
    I'm not positive that the file handle stuff is 100% OK -- it looks fine, that's just the first place I'd start. Try calling your logger from a command line, and follow through using the debugger. That should show up the problem.

    (My guess is that the logger stream is by accident going to STDOUT -- to the web page -- which is causing the complaints.)

    <Opinion> I am probably biased against using OO everywhere .. I have written loggers before, and I don't leave the file handle open between calls. Every call in my logger is an open/write/close cycle, so that if the script dies badly, no buffers are left unflushed. Sure, it's way inefficient, but that's for development. A production logger I'd make much smarter. </Opinion>

    --t. alex

    "Of course, you realize that this means war." -- Bugs Bunny.

Re: Web App logging
by Ryszard (Priest) on Feb 02, 2002 at 06:50 UTC
    Ok, i've got it sorted. After much dicking about, i now realised my module is not in the @INC path. This node Helped me out a bit.

    I should have initially run it at the command line, it would have saved me heaps of time.

    Thanks to all those who responded

    Someone please pass me the wet fish, i'm feeling rather embaressed now... :-)