Icon for Dimension.orgIcon for TalentIcon for ToolsIcon for Doorways.org
Icon for ToolsIcon for Perl Tools

MMAgic Demo: MMAgic/Log.pm Source File

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

MMAgic/Log.pm

Go to the documentation of this file.
00001 package MMAgic::Log;
00002 #
00003 # MMAgic/Log.pm
00004 #
00005 #   Object representing an output log stream.
00006 #   Output is formatted with type tags and timestamps.
00007 #
00008 
00009 use     strict;
00010 use     warnings;
00011 
00012 use     Exporter;
00013 use     POSIX;
00014 use     UNIVERSAL   qw(isa);
00015 
00016 use     MMAgic::Log::Indent;
00017 use     MMAgic::Output;
00018 use     MMAgic::Trace;
00019 
00020 our     @ISA    = qw(Exporter MMAgic::Output);
00021 our     @EXPORT = qw(Log);
00022 
00023 our     $hashkey;
00024 our     $signals;
00025 our     $special;
00026 our     @stack;
00027 
00028 ###########################################################################
00029 ###########################################################################
00030 sub new ($;%)   #
00031 #
00032     {
00033     my ($class, %parms) = @_;
00034     my  $self = new MMAgic::Output(%parms);
00035     
00036     return undef
00037         unless isa($self, 'MMAgic::Output');
00038     
00039     bless $self, $class;
00040     
00041     $self->{code} = 'T';
00042     $self->{dGMT} = $parms{GMT}      || $ENV{MMAgic_Log_GMT};
00043     $self->{dFmt} = $parms{timeOnly} || $ENV{MMAgic_Log_timeOnly}
00044                   ? '%H:%M:%S' : '%Y/%m/%d %H:%M:%S';
00045     
00046     if ($self->{handle} && ! $self->{noFlush})
00047         {
00048         # suceeded, turn on auto-flushing:
00049         my  $oldFH = select($self->{handle});
00050         
00051         $| = 1;
00052         select($oldFH);
00053         }
00054         
00055     $self
00056     }
00057 
00058 ###########################################################################
00059 sub Log         # [ $class ]
00060 #
00061     {
00062     unshift @stack, new MMAgic::Log(output => \*STDERR)
00063         unless @stack;
00064 
00065     $stack[0]
00066     }
00067 
00068 ###########################################################################
00069 sub pushLog     # [ $class, ] $log | %init
00070 #
00071     {
00072     my  $log = shift;
00073 
00074     # Get rid of optional class argument:
00075     $log = shift if isa($log, __PACKAGE__) && ! ref $log;
00076     
00077     # See which argument form we have:
00078     unless (isa($log, __PACKAGE__))
00079         {
00080         # Must create Log object from parameters:
00081         my  %init = ( $log, @_ );
00082         my  $type = $init{logType};
00083         
00084         if ($type)
00085             {
00086             $type = "MMAgic::Log::$type";
00087             
00088             eval "use $type";
00089             
00090             die "Unable to load $type:\n  $@\n"
00091                 if $@;
00092             }
00093         
00094         $type = __PACKAGE__
00095             unless $type;
00096         
00097         $log = $type->new(%init);
00098         }
00099 
00100     unshift @stack, $log
00101         if isa($log, __PACKAGE__);
00102 
00103     $stack[0]
00104     }
00105 
00106 ###########################################################################
00107 sub popLog      # [ $class ]
00108 #
00109     {
00110     shift @stack
00111     }
00112 
00113 ###########################################################################
00114 ###########################################################################
00115 sub handle      # [ $class ] [ @which ]
00116 # Capture warn and/or die handlers and redirect to current log.
00117 #   This would be a permanent fix, the user being responsible for
00118 #   backing the out if necessary.
00119 #
00120     {
00121     shift if isa($_[0], __PACKAGE__);
00122     
00123 #!# my  $auto = Log->method(@_)->block;
00124     
00125     map {
00126 #!#     Log->trace('Which:  ', $_);
00127         
00128         if (/^warn/i)
00129             {
00130             $SIG{__WARN__} = \&handleWarn;
00131             }
00132         
00133         elsif (/^die/i)
00134             {
00135             $SIG{__DIE__} = \&handleDie;
00136             }
00137         
00138         else
00139             {
00140             Log->warn('Unable to Log ', $_, ' messages');
00141             }
00142         } @_ ? @_ : qw(warn die);
00143     }
00144 
00145 ###########################################################################
00146 sub handleWarn  #
00147 # Redirect warnings to log file.
00148 #
00149     {
00150     Log->warning(shift);
00151     }
00152 
00153 ###########################################################################
00154 sub handleDie   #
00155 # Redirect die messages to log file.
00156 #
00157     {
00158     # Unfortunately, the $SIG{__DIE__} handler is somewhat broken,
00159     #   we don't want to fire if we're wrapped in an eval somewhere:
00160     my  $up = 0;
00161     
00162     while (1)
00163         {
00164         my ($pkg, $file, $line, $sub) = caller($up++);
00165         
00166         last unless $pkg;
00167         
00168         return if $file eq '(eval)' || $sub eq '(eval)';
00169         }
00170     
00171     Log->critical(shift);
00172     
00173 #   die "DIE:  Final error message in MMAgic::Log repository!\n"
00174     die "\n"
00175     }
00176 
00177 ###########################################################################
00178 ###########################################################################
00179 sub starter         # $self
00180 #
00181     {
00182     my  $self = shift;
00183     my  $now  = $self->timestamp($self->{msgT});
00184     
00185     $self->SUPER::starter;
00186     $self->process("$now [$self->{msgC}] ");
00187     $self->{msgC} = '+';
00188     $self
00189     }
00190 
00191 ###########################################################################
00192 sub timestamp   # [ $clasSelf ] [ $when ]
00193 #
00194     {
00195     my ($self, $when) = @_;
00196     
00197     if (! isa($self, __PACKAGE__))
00198         {
00199         $when = $self;
00200         $self = Log;
00201         }
00202     
00203     unless ($when && int($when))
00204         {
00205         $when = $self->{msgT};
00206         $when = time unless $when && int($when);
00207         }
00208     
00209     return strftime
00210         ($self->{dFmt},
00211          $self->{dGMT} ? gmtime($when) : localtime($when));
00212     }
00213 
00214 ###########################################################################
00215 ###########################################################################
00216 sub block   # [ $clasSelf, ] [ $incr ]
00217 # Returns 'auto-indent' object.
00218 #   Indent is started and then removed when the object is destroyed.
00219 #
00220     {
00221     my  $target = shift;
00222     
00223     $target = Log unless isa($target, __PACKAGE__);
00224 
00225     new MMAgic::Log::Indent($target, @_)
00226     }
00227 
00228 ###########################################################################
00229 sub push        # $clasSelf [, $incr]
00230 #
00231     {
00232     my  $target = shift;
00233 
00234     $target = Log unless isa($target, __PACKAGE__);
00235     $target->pushIndent(shift);
00236     }
00237 
00238 ###########################################################################
00239 sub pop         # $clasSelf
00240 #
00241     {
00242     my  $target = shift;
00243 
00244     $target = Log unless isa($target, __PACKAGE__);
00245     $target->popIndent;
00246     }
00247 
00248 ###########################################################################
00249 sub withIndent  # $clasSelf, $sub, @args
00250 #
00251     {
00252     my  $target = shift;
00253     my  $sub    = shift;
00254     
00255     $target = Log unless isa($target, __PACKAGE__);
00256     $target->push;
00257     
00258     my  $result = eval { &$sub(@_); };
00259     my  $error  = $@;
00260 
00261     $target->pop;
00262 
00263     die $error if $error;
00264 
00265     $result
00266     }
00267 
00268 ###########################################################################
00269 ###########################################################################
00270 sub flush   # $self
00271 # Flush pending output.
00272 #   Override the basic MMAgic::Output method which prints nasty messages.
00273 #
00274     {
00275     # Still can't actually do anything...
00276     shift
00277     }
00278 
00279 ###########################################################################
00280 sub message     # $self, [ timestamp, ] $code, ...
00281 #
00282     {
00283     my  $self = shift;
00284     
00285     $self = Log unless ref($self) eq __PACKAGE__;
00286     
00287     my  $strt = $self->{msgT};
00288     
00289     $self->{msgC} = '?';
00290     $self->{msgT} = shift;
00291     
00292     if ($self->{msgT} !~ /\D/)  # check for integer
00293         {
00294         # Timestamp was actually provided:
00295         $self->{msgC} = shift || $self->{code};
00296         }
00297     
00298     else
00299         {
00300         # No timestamp, was flag instead:
00301         $self->{msgC} = $self->{msgT};
00302         $self->{msgT} = time;
00303         }
00304 
00305     $self->newLine;
00306     
00307     my  @args = @_; # don't know why this is necessary,
00308                     #   but can't just use @_ inside of eval
00309     eval
00310         {
00311         $self->print(@args);
00312         $self->newLine;
00313         };
00314 
00315     $self->{msgT} = $strt;
00316     $self->flush;
00317     $self
00318     }
00319 
00320 ###########################################################################
00321 sub append      # [ $clasSelf, ] ...
00322 #
00323     {
00324     my  $target = shift;
00325     
00326     $target = Log unless isa($target, __PACKAGE__);
00327     $target->message('+', @_);
00328     }
00329 
00330 ###########################################################################
00331 sub critical    # [ $clasSelf, ] ...
00332 #
00333     {
00334     my  $target = shift;
00335     
00336     $target = Log unless isa($target, __PACKAGE__);
00337     $target->message('C', @_);
00338     }
00339 
00340 ###########################################################################
00341 sub error       # [ $clasSelf, ] ...
00342 #
00343     {
00344     my  $target = shift;
00345     
00346     $target = Log unless isa($target, __PACKAGE__);
00347     $target->message('E', @_);
00348     }
00349 
00350 ###########################################################################
00351 sub info        # [ $clasSelf, ] ...
00352 #
00353     {
00354     my  $target = shift;
00355 
00356     $target = Log unless isa($target, __PACKAGE__);
00357     $target->message('I', @_);
00358     }
00359 
00360 ###########################################################################
00361 sub trace       # [ $clasSelf, ] ...
00362 #
00363     {
00364     my  $target = shift;
00365     
00366     $target = Log unless isa($target, __PACKAGE__);
00367     $target->message('T', @_);
00368     }
00369 
00370 ###########################################################################
00371 sub unknown     # [ $clasSelf, ] ...
00372 #
00373     {
00374     my  $target = shift;
00375     
00376     $target = Log unless isa($target, __PACKAGE__);
00377     $target->message('?', @_);
00378     }
00379 
00380 ###########################################################################
00381 sub warning     # [ $clasSelf, ] ...
00382 #
00383     {
00384     my  $target = shift;
00385     
00386     $target = Log unless isa($target, __PACKAGE__);
00387     $target->message('W', @_);
00388     }
00389 
00390 ###########################################################################
00391 ###########################################################################
00392 sub crash       # [ $clasSelf, ] ...
00393 #
00394     {
00395     my  $target = shift;
00396 
00397     $target = Log unless isa($target, __PACKAGE__);
00398     $target->message('C', @_);
00399     
00400     my ($pkg, $file, $line) = caller;
00401     
00402     die "Crashed at $file line $line\n"
00403     }
00404 
00405 ###########################################################################
00406 sub bail        # [ $clasSelf, ] ...
00407 #
00408     {
00409     warn 'Log::bail() deprecated, use Log::crash() instead';
00410 
00411     crash(@_)
00412     }
00413 
00414 ###########################################################################
00415 sub method      # [ $clasSelf, ] ...
00416 #
00417 {
00418     my  $target = shift;
00419     
00420     $target = Log unless isa($target, __PACKAGE__);
00421 
00422     my ($pkg, undef, undef, $sub) = caller(1);
00423     my  $flag = 'T';
00424     my  $indt = '';
00425     
00426     if ($_[0] && $_[0] =~ /^\[(.)\](.*)$/)
00427         {
00428         # Special first argument to specify message flag and indent:
00429         $flag = $1;
00430         $indt = $2;
00431         shift;
00432         }
00433 
00434     shift if isa($_[0], $pkg);
00435     
00436     local   $special = undef;
00437     local   $hashkey = undef;
00438     
00439     $target->message
00440         ($flag, $indt, $sub, '(',
00441          join(', ', map
00442             {
00443             my  $result = defined($_) ? $_ : '<undef>';
00444             
00445             if ($special)
00446                 {
00447                 if ($hashkey)
00448                     {
00449                     $result = "$hashkey => $result";
00450                     undef $hashkey;
00451                     }
00452                 
00453                 else
00454                     {
00455                     $hashkey = $_;
00456                     undef $result;
00457                     }
00458                 }
00459             
00460             elsif ($result eq '%')
00461                 {
00462                 $special = 1;
00463                 undef $result;
00464                 }
00465             
00466             defined($result) ? $result : ( )
00467             } @_), ')'
00468         );
00469     }
00470 
00471 ###########################################################################
00472 sub where       # [ $line ]
00473 #
00474     {
00475     shift if isa $_[0], __PACKAGE__;
00476     
00477     my ($func, $pkg, $stack) = ('eval', undef, 1);
00478     
00479     ($pkg, undef, undef, $func) = caller($stack++)
00480         while $func =~ /\b(?:eval|where)\b/;
00481     
00482     my  $where = "${pkg}::${func}()";
00483     
00484     $where .=  "\n  file @{[ shift ]}" if @_;
00485     $where .=  "\n  line @{[ shift ]}" if @_;
00486     $where  =~ s/^main:://i;
00487     $where
00488     }
00489 
00490 ###########################################################################
00491 ###########################################################################
00492 sub signals     # [ $clasSelf, ] $flag
00493 # Turn signal capture and redirection on and off.
00494 #   Don't know if this actually works.
00495 #   And then there's the __DIE__ over-zealous problem.
00496 #
00497     {
00498     my  $flag = shift;
00499     
00500     $flag = shift if isa($flag, __PACKAGE__);
00501     
00502     return if $flag == $signals;
00503     
00504     if ($flag)
00505         {
00506         $SIG{__WARN__} = sub { Log->Error   (@_) };
00507         $SIG{__DIE__}  = sub { Log->Critical(@_) };
00508         }
00509     
00510     else
00511         {
00512         delete $SIG{__DIE__};
00513         delete $SIG{__WARN__};
00514         }
00515     
00516     $signals = $flag;
00517     }
00518 
00519 ###########################################################################
00520 sub display     # $self, $item, %param
00521 # Dump an object to a Log.
00522 #
00523     {
00524     my  $self = shift;
00525     my  $item = shift;
00526     my  %param;
00527     
00528     if (@_ == 1) {
00529         # Support old-style shortcut which I keep doing...
00530         #   it just makes sense most of the time.
00531         $param{prefix} = shift;
00532         $param{prefix} =~ s/\s*$/ => /
00533             unless $param{prefix} =~ /=>\s*/;
00534     } elsif (@_) {
00535         %param = @_;
00536     }
00537     
00538     $self->{msgC} = $param{code} || $self->{code};
00539     
00540     delete $param{code}
00541         if exists $param{code};
00542     
00543     $self->newLine;
00544     $self->SUPER::display($item, %param);
00545     $self->flush;
00546     $self
00547     }
00548 
00549 ###########################################################################
00550 ###########################################################################
00551 my  $deprecated;
00552 
00553 sub reference   # $self, $target, %param
00554 # Dump a reference-based object to Log.
00555 #
00556     {
00557     my  $self = shift;
00558     my  $targ = shift;
00559     
00560     Log->warning(__PACKAGE__, '::reference() deprecated in favor of ',
00561                  __PACKAGE__, '::display()')
00562         unless $deprecated++;
00563     
00564     # Cover for ancient calling convention
00565     #   ($self, $target [, $code]):
00566     $self->{msgC} = shift
00567         if @_ == 1;
00568     
00569     $self->display(@_, $targ, @_)
00570     }
00571 
00572 1

Generated on Mon Dec 27 2010 15:15:42 for MMAgic Demo by  doxygen 1.7.1

www.dimension.org logo

(C)opyright 1998 - 2012 Dimension.org

WebMaster