1################################################## 2package Log::Log4perl::Logger; 3################################################## 4 5use 5.006; 6use strict; 7use warnings; 8 9use Log::Log4perl; 10use Log::Log4perl::Level; 11use Log::Log4perl::Layout; 12use Log::Log4perl::Appender; 13use Log::Log4perl::Appender::String; 14use Log::Log4perl::Filter; 15use Carp; 16 17$Carp::Internal{"Log::Log4perl"}++; 18$Carp::Internal{"Log::Log4perl::Logger"}++; 19 20use constant _INTERNAL_DEBUG => 0; 21 22 # Initialization 23our $ROOT_LOGGER; 24our $LOGGERS_BY_NAME = {}; 25our %APPENDER_BY_NAME = (); 26our $INITIALIZED = 0; 27our $NON_INIT_WARNED; 28 29 # Define the default appender that's used for formatting 30 # warn/die/croak etc. messages. 31our $STRING_APP_NAME = "_l4p_warn"; 32our $STRING_APP = Log::Log4perl::Appender->new( 33 "Log::Log4perl::Appender::String", 34 name => $STRING_APP_NAME); 35$STRING_APP->layout(Log::Log4perl::Layout::PatternLayout->new("%m")); 36our $STRING_APP_CODEREF = generate_coderef([[$STRING_APP_NAME, $STRING_APP]]); 37 38__PACKAGE__->reset(); 39 40########################################### 41sub warning_render { 42########################################### 43 my($logger, @message) = @_; 44 45 $STRING_APP->string(""); 46 $STRING_APP_CODEREF->($logger, 47 @message, 48 Log::Log4perl::Level::to_level($ALL)); 49 return $STRING_APP->string(); 50} 51 52################################################## 53sub cleanup { 54################################################## 55 # warn "Logger cleanup"; 56 57 # Delete all loggers 58 foreach my $loggername (keys %$LOGGERS_BY_NAME){ 59 # warn "Logger delete: $loggername"; 60 $LOGGERS_BY_NAME->{$loggername}->DESTROY(); 61 delete $LOGGERS_BY_NAME->{$loggername}; 62 } 63 64 # Delete the root logger 65 undef $ROOT_LOGGER; 66 67 # Delete all appenders 68 foreach my $appendername (keys %APPENDER_BY_NAME){ 69 if (exists $APPENDER_BY_NAME{$appendername} && 70 exists $APPENDER_BY_NAME{$appendername}->{appender}) { 71 # Destroy the specific appender 72 my $appref = $APPENDER_BY_NAME{$appendername}->{appender}; 73 eval { $appref->DESTROY() }; 74 # Destroy L4p::Appender 75 $APPENDER_BY_NAME{$appendername}->DESTROY(); 76 delete $APPENDER_BY_NAME{$appendername}->{appender}; 77 } 78 delete $APPENDER_BY_NAME{$appendername}; 79 } 80 %APPENDER_BY_NAME = (); 81 82 undef $INITIALIZED; 83} 84 85################################################## 86sub DESTROY { 87################################################## 88 warn "Destroying logger $_[0]" if $Log::Log4perl::CHATTY_DESTROY_METHODS; 89 90 for(keys %{$_[0]}) { 91 delete $_[0]->{$_}; 92 } 93} 94 95################################################## 96sub reset { 97################################################## 98 $ROOT_LOGGER = __PACKAGE__->_new("", $DEBUG); 99# $LOGGERS_BY_NAME = {}; #leave this alone, it's used by 100 #reset_all_output_methods when 101 #the config changes 102 103 104 #we've got a circular reference thing going on somewhere 105 foreach my $appendername (keys %APPENDER_BY_NAME){ 106 delete $APPENDER_BY_NAME{$appendername}->{appender} 107 if (exists $APPENDER_BY_NAME{$appendername} && 108 exists $APPENDER_BY_NAME{$appendername}->{appender}); 109 } 110 %APPENDER_BY_NAME = (); 111 undef $INITIALIZED; 112 undef $NON_INIT_WARNED; 113 Log::Log4perl::Appender::reset(); 114 115 #clear out all the existing appenders 116 foreach my $logger (values %$LOGGERS_BY_NAME){ 117 $logger->{appender_names} = (); 118 119 #this next bit deals with an init_and_watch case where a category 120 #is deleted from the config file, we need to zero out the existing 121 #loggers so ones not in the config file not continue with their old 122 #behavior --kg 123 next if $logger eq $ROOT_LOGGER; 124 $logger->{level} = undef; 125 $logger->level(); #set it from the heirarchy 126 } 127 128 # Clear all filters 129 Log::Log4perl::Filter::reset(); 130} 131 132################################################## 133sub _new { 134################################################## 135 my($class, $category, $level) = @_; 136 137 print("_new: $class/$category/", defined $level ? $level : "undef", 138 "\n") if _INTERNAL_DEBUG; 139 140 die "usage: __PACKAGE__->_new(category)" unless 141 defined $category; 142 143 $category =~ s/::/./g; 144 145 # Have we created it previously? 146 if(exists $LOGGERS_BY_NAME->{$category}) { 147 print "_new: exists already\n" if _INTERNAL_DEBUG; 148 return $LOGGERS_BY_NAME->{$category}; 149 } 150 151 my $self = { 152 category => $category, 153 num_appenders => 0, 154 additivity => 1, 155 level => $level, 156 layout => undef, 157 }; 158 159 bless $self, $class; 160 161 $level ||= $self->level(); 162 163 # Save it in global structure 164 $LOGGERS_BY_NAME->{$category} = $self; 165 166 $self->set_output_methods; 167 168 return $self; 169} 170 171################################################## 172sub reset_all_output_methods { 173################################################## 174 print "reset_all_output_methods: \n" if _INTERNAL_DEBUG; 175 176 foreach my $loggername ( keys %$LOGGERS_BY_NAME){ 177 $LOGGERS_BY_NAME->{$loggername}->set_output_methods; 178 } 179 $ROOT_LOGGER->set_output_methods; 180} 181 182################################################## 183sub set_output_methods { 184# Here's a big performance increase. Instead of having the logger 185# calculate whether to log and whom to log to every time log() is called, 186# we calculcate it once when the logger is created, and recalculate 187# it if the config information ever changes. 188# 189################################################## 190 my ($self) = @_; 191 192 my (@appenders, %seen); 193 194 my ($level) = $self->level(); 195 196 print "set_output_methods: $self->{category}/$level\n" if _INTERNAL_DEBUG; 197 198 #collect the appenders in effect for this category 199 200 for(my $logger = $self; $logger; $logger = parent_logger($logger)) { 201 202 foreach my $appender_name (@{$logger->{appender_names}}){ 203 204 #only one message per appender, (configurable) 205 next if $seen{$appender_name} ++ && 206 $Log::Log4perl::one_message_per_appender; 207 208 push (@appenders, 209 [$appender_name, 210 $APPENDER_BY_NAME{$appender_name}, 211 ] 212 ); 213 } 214 last unless $logger->{additivity}; 215 } 216 217 #make a no-op coderef for inactive levels 218 my $noop = generate_noop_coderef(); 219 220 #make a coderef 221 my $coderef = (! @appenders ? $noop : &generate_coderef(\@appenders)); 222 223 my %priority = %Log::Log4perl::Level::PRIORITY; #convenience and cvs 224 225 # changed to >= from <= as level ints were reversed 226 foreach my $levelname (keys %priority){ 227 if (Log::Log4perl::Level::isGreaterOrEqual($level, 228 $priority{$levelname} 229 )) { 230 print " ($priority{$levelname} <= $level)\n" 231 if _INTERNAL_DEBUG; 232 $self->{$levelname} = $coderef; 233 $self->{"is_$levelname"} = generate_is_xxx_coderef("1"); 234 #$self->{"is_$levelname"} = sub { 1 }; 235 }else{ 236 print " ($priority{$levelname} > $level)\n" if _INTERNAL_DEBUG; 237 $self->{$levelname} = $noop; 238 $self->{"is_$levelname"} = generate_is_xxx_coderef("0"); 239 #$self->{"is_$levelname"} = sub { 0 }; 240 } 241 242 print(" Setting [$self] $self->{category}.$levelname to ", 243 ($self->{$levelname} == $noop ? "NOOP" : 244 ("Coderef [$coderef]: " . scalar @appenders . " appenders")), 245 "\n") if _INTERNAL_DEBUG; 246 } 247} 248 249################################################## 250sub generate_coderef { 251################################################## 252 my $appenders = shift; 253 254 print "generate_coderef: ", scalar @$appenders, 255 " appenders\n" if _INTERNAL_DEBUG; 256 257 my $coderef = ''; 258 my $watch_delay_code = ''; 259 260 # Doing this with eval strings to sacrifice init/reload time 261 # for runtime efficiency, so the conditional won't be included 262 # if it's not needed 263 264 if (defined $Log::Log4perl::Config::WATCHER) { 265 $watch_delay_code = generate_watch_code(); 266 } 267 268 my $code = <<EOL; 269 sub { 270 my (\$logger) = shift; 271 my (\$level) = pop; 272 my \$message; 273 my \$appenders_fired = 0; 274 275 # Evaluate all parameters that need to evaluated. Two kinds: 276 # 277 # (1) It's a hash like { filter => "filtername", 278 # value => "value" } 279 # => filtername(value) 280 # 281 # (2) It's a code ref 282 # => coderef() 283 # 284 285 \$message = [map { ref \$_ eq "HASH" && 286 exists \$_->{filter} && 287 ref \$_->{filter} eq 'CODE' ? 288 \$_->{filter}->(\$_->{value}) : 289 ref \$_ eq "CODE" ? 290 \$_->() : \$_ 291 } \@_]; 292 293 print("coderef: \$logger->{category}\n") if _INTERNAL_DEBUG; 294 295 $watch_delay_code; #note interpolation here 296 297 foreach my \$a (\@\$appenders) { #note the closure here 298 my (\$appender_name, \$appender) = \@\$a; 299 300 print(" Sending message '<\$message>' (\$level) " . 301 "to \$appender_name\n") if _INTERNAL_DEBUG; 302 303 \$appender->log( 304 #these get passed through to Log::Dispatch 305 { name => \$appender_name, 306 level => \$Log::Log4perl::Level::L4P_TO_LD{ 307 \$level}, 308 message => \$message, 309 }, 310 #these we need 311 \$logger->{category}, 312 \$level, 313 ) and \$appenders_fired++; 314 # Only counting it if it returns a true value. Otherwise 315 # the appender threshold might have suppressed it after all. 316 317 } #end foreach appenders 318 319 return \$appenders_fired; 320 321 }; #end coderef 322 323EOL 324 325 $coderef = eval $code or die "$@"; 326 327 return $coderef; 328} 329 330################################################## 331sub generate_noop_coderef { 332################################################## 333 my $coderef = ''; 334 my $watch_delay_code = ''; 335 336 if (defined $Log::Log4perl::Config::WATCHER) { 337 $watch_delay_code = generate_watch_code(); 338 $watch_delay_code = <<EOL; 339 my \$logger; 340 my \$level; 341 $watch_delay_code 342EOL 343 } 344 345 my $code = <<EOL; 346 \$coderef = sub { 347 print("noop: \n") if _INTERNAL_DEBUG; 348 $watch_delay_code 349 return undef; 350 }; 351EOL 352 353 eval $code or die "$@"; 354 355 return $coderef; 356} 357 358################################################## 359sub generate_is_xxx_coderef { 360################################################## 361 my($return_token) = @_; 362 363 my $coderef = sub { $return_token }; 364 365 if (defined $Log::Log4perl::Config::WATCHER) { 366 367 my $cond = generate_watch_conditional(); 368 369 my $watch_code = <<EOL; 370 my(\$logger, \$subname) = \@_; 371 if($cond) { 372 Log::Log4perl->init_and_watch(); 373 # Forward call to new configuration 374 return \$logger->\$subname(); 375 } 376EOL 377 378 my $code = <<EOL; 379 \$coderef = sub { $watch_code return $return_token; }; 380EOL 381 382 eval $code or die "$@"; 383 } 384 385 return $coderef; 386} 387 388################################################## 389sub generate_watch_code { 390################################################## 391 print "generate_watch_code:\n" if _INTERNAL_DEBUG; 392 393 my $cond = generate_watch_conditional(); 394 395 return <<EOL; 396 print "exe_watch_code:\n" if _INTERNAL_DEBUG; 397 398 # more closures here 399 if($cond) { 400 if(!defined \$logger) { 401 \$logger = shift; 402 \$level = pop; 403 } 404 405 Log::Log4perl->init_and_watch(); 406 407 my \$methodname = lc(\$level); 408 409 # Bump up the caller level by two, since 410 # we've artifically introduced additional levels. 411 local(\$Log::Log4perl::caller_depth); 412 \$Log::Log4perl::caller_depth += 2; 413 414 \$logger->\$methodname(\@_); # send the message 415 # to the new configuration 416 return; #and return, we're done with this incarnation 417 } 418EOL 419} 420 421################################################## 422sub generate_watch_conditional { 423################################################## 424 425 if(defined $Log::Log4perl::Config::Watch::SIGNAL_CAUGHT) { 426 # In this mode, we just check for the variable indicating 427 # that the signal has been caught 428 return q{$Log::Log4perl::Config::Watch::SIGNAL_CAUGHT}; 429 } 430 431 # In this mode, we check if the config file has been modified 432 return q{time() > $Log::Log4perl::Config::Watch::NEXT_CHECK_TIME 433 and $Log::Log4perl::Config::WATCHER->change_detected()}; 434 435} 436 437################################################## 438sub parent_string { 439################################################## 440 my($string) = @_; 441 442 if($string eq "") { 443 return undef; # root doesn't have a parent. 444 } 445 446 my @components = split /\./, $string; 447 448 if(@components == 1) { 449 return ""; 450 } 451 452 pop @components; 453 454 return join('.', @components); 455} 456 457################################################## 458sub level { 459################################################## 460 my($self, $level, $dont_reset_all) = @_; 461 462 # 'Set' function 463 if(defined $level) { 464 croak "invalid level '$level'" 465 unless Log::Log4perl::Level::is_valid($level); 466 if ($level =~ /\D/){ 467 $level = Log::Log4perl::Level::to_priority($level); 468 } 469 $self->{level} = $level; 470 471 &reset_all_output_methods 472 unless $dont_reset_all; #keep us from getting overworked 473 #if it's the config file calling us 474 475 return $level; 476 } 477 478 # 'Get' function 479 if(defined $self->{level}) { 480 return $self->{level}; 481 } 482 483 for(my $logger = $self; $logger; $logger = parent_logger($logger)) { 484 485 # Does the current logger have the level defined? 486 487 if($logger->{category} eq "") { 488 # It's the root logger 489 return $ROOT_LOGGER->{level}; 490 } 491 492 if(defined $LOGGERS_BY_NAME->{$logger->{category}}->{level}) { 493 return $LOGGERS_BY_NAME->{$logger->{category}}->{level}; 494 } 495 } 496 497 # We should never get here because at least the root logger should 498 # have a level defined 499 die "We should never get here."; 500} 501 502################################################## 503sub parent_logger { 504# Get the parent of the current logger or undef 505################################################## 506 my($logger) = @_; 507 508 # Is it the root logger? 509 if($logger->{category} eq "") { 510 # Root has no parent 511 return undef; 512 } 513 514 # Go to the next defined (!) parent 515 my $parent_class = parent_string($logger->{category}); 516 517 while($parent_class ne "" and 518 ! exists $LOGGERS_BY_NAME->{$parent_class}) { 519 $parent_class = parent_string($parent_class); 520 $logger = $LOGGERS_BY_NAME->{$parent_class}; 521 } 522 523 if($parent_class eq "") { 524 $logger = $ROOT_LOGGER; 525 } else { 526 $logger = $LOGGERS_BY_NAME->{$parent_class}; 527 } 528 529 return $logger; 530} 531 532################################################## 533sub get_root_logger { 534################################################## 535 my($class) = @_; 536 return $ROOT_LOGGER; 537} 538 539################################################## 540sub additivity { 541################################################## 542 my($self, $onoff) = @_; 543 544 if(defined $onoff) { 545 $self->{additivity} = $onoff; 546 } 547 548 return $self->{additivity}; 549} 550 551################################################## 552sub get_logger { 553################################################## 554 my($class, $category) = @_; 555 556 unless(defined $ROOT_LOGGER) { 557 die "Internal error: Root Logger not initialized."; 558 } 559 560 return $ROOT_LOGGER if $category eq ""; 561 562 my $logger = $class->_new($category); 563 return $logger; 564} 565 566################################################## 567sub add_appender { 568################################################## 569 my($self, $appender, $dont_reset_all) = @_; 570 571 my $not_to_dispatcher = 0; 572 573 # We take this as an indicator that we're initialized. 574 $INITIALIZED = 1; 575 576 my $appender_name = $appender->name(); 577 578 $self->{num_appenders}++; #should this be inside the unless? 579 580 unless (grep{$_ eq $appender_name} @{$self->{appender_names}}){ 581 $self->{appender_names} = [sort @{$self->{appender_names}}, 582 $appender_name]; 583 } 584 585 if ($APPENDER_BY_NAME{$appender_name}) { 586 $not_to_dispatcher = 1; 587 }else{ 588 $APPENDER_BY_NAME{$appender_name} = $appender; 589 } 590 591 &reset_all_output_methods 592 unless $dont_reset_all; # keep us from getting overworked 593 # if it's the config file calling us 594 595 # For chaining calls ... 596 return $appender; 597} 598 599################################################## 600sub remove_appender { 601################################################## 602 my($self, $appender_name, $dont_reset_all, $sloppy) = @_; 603 604 my %appender_names = map { $_ => 1 } @{$self->{appender_names}}; 605 606 if(!exists $appender_names{$appender_name}) { 607 die "No such appender: $appender_name" unless $sloppy; 608 return undef; 609 } 610 611 delete $appender_names{$appender_name}; 612 $self->{num_appenders}--; 613 $self->{appender_names} = [sort keys %appender_names]; 614 615 &reset_all_output_methods 616 unless $dont_reset_all; 617} 618 619################################################## 620sub eradicate_appender { 621################################################## 622 # If someone calls Logger->... and not Logger::... 623 shift if $_[0] eq __PACKAGE__; 624 625 my($appender_name, $dont_reset_all) = @_; 626 627 return 0 unless exists 628 $APPENDER_BY_NAME{$appender_name}; 629 630 # Remove the given appender from all loggers 631 # and delete all references to it, causing 632 # its DESTROY method to be called. 633 foreach my $logger (values %$LOGGERS_BY_NAME){ 634 $logger->remove_appender($appender_name, 0, 1); 635 } 636 # Also remove it from the root logger 637 $ROOT_LOGGER->remove_appender($appender_name, 0, 1); 638 639 delete $APPENDER_BY_NAME{$appender_name}; 640 641 &reset_all_output_methods 642 unless $dont_reset_all; 643 644 return 1; 645} 646 647################################################## 648sub has_appenders { 649################################################## 650 my($self) = @_; 651 652 return $self->{num_appenders}; 653} 654 655################################################## 656sub log { 657# external api 658################################################## 659 my ($self, $priority, @messages) = @_; 660 661 confess("log: No priority given!") unless defined($priority); 662 663 # Just in case of 'init_and_watch' -- see Changes 0.21 664 $_[0] = $LOGGERS_BY_NAME->{$_[0]->{category}} if 665 defined $Log::Log4perl::Config::WATCHER; 666 667 init_warn() unless $INITIALIZED or $NON_INIT_WARNED; 668 669 croak "priority $priority isn't numeric" if ($priority =~ /\D/); 670 671 my $which = Log::Log4perl::Level::to_level($priority); 672 673 $self->{$which}->($self, @messages, 674 Log::Log4perl::Level::to_level($priority)); 675} 676 677###################################################################### 678# 679# create_custom_level 680# creates a custom level 681# in theory, could be used to create the default ones 682###################################################################### 683sub create_custom_level { 684###################################################################### 685 my $level = shift || die("create_custom_level: " . 686 "forgot to pass in a level string!"); 687 my $after = shift || die("create_custom_level: " . 688 "forgot to pass in a level after which to " . 689 "place the new level!"); 690 my $syslog_equiv = shift; # can be undef 691 692 ## only let users create custom levels before initialization 693 694 die("create_custom_level must be called before init or " . 695 "first get_logger() call") if ($INITIALIZED); 696 697 my %PRIORITY = %Log::Log4perl::Level::PRIORITY; #convenience 698 699 die("create_custom_level: no such level \"$after\"! Use one of: ", 700 join(", ", sort keys %PRIORITY)) unless $PRIORITY{$after}; 701 702 # figure out new int value by AFTER + (AFTER+ 1) / 2 703 704 my $next_prio = Log::Log4perl::Level::get_lower_level($PRIORITY{$after}, 1); 705 my $cust_prio = int(($PRIORITY{$after} + $next_prio) / 2); 706 707 die(qq{create_custom_level: Calculated level of $cust_prio already exists! 708 This should only happen if you've made some insane number of custom 709 levels (like 15 one after another) 710 You can usually fix this by re-arranging your code from: 711 create_custom_level("cust1", X); 712 create_custom_level("cust2", X); 713 create_custom_level("cust3", X); 714 create_custom_level("cust4", X); 715 create_custom_level("cust5", X); 716 into: 717 create_custom_level("cust3", X); 718 create_custom_level("cust5", X); 719 create_custom_level("cust4", 4); 720 create_custom_level("cust2", cust3); 721 create_custom_level("cust1", cust2); 722 }) if (${Log::Log4perl::Level::LEVELS{$cust_prio}}); 723 724 Log::Log4perl::Level::add_priority($level, $cust_prio, $syslog_equiv); 725 726 print("Adding prio $level at $cust_prio\n") if _INTERNAL_DEBUG; 727 728 # get $LEVEL into namespace of Log::Log4perl::Logger to 729 # create $logger->foo nd $logger->is_foo 730 my $name = "Log::Log4perl::Logger::"; 731 my $key = $level; 732 733 no strict qw(refs); 734 # be sure to use ${Log...} as CVS adds log entries for Log 735 *{"$name$key"} = \${Log::Log4perl::Level::PRIORITY{$level}}; 736 737 # now, stick it in the caller's namespace 738 $name = caller(0) . "::"; 739 *{"$name$key"} = \${Log::Log4perl::Level::PRIORITY{$level}}; 740 use strict qw(refs); 741 742 create_log_level_methods($level); 743 744 return 0; 745 746} 747 748######################################## 749# 750# if we were hackin' lisp (or scheme), we'd be returning some lambda 751# expressions. But we aren't. :) So we'll just create some strings and 752# eval them. 753######################################## 754sub create_log_level_methods { 755######################################## 756 my $level = shift || die("create_log_level_methods: " . 757 "forgot to pass in a level string!"); 758 my $lclevel = lc($level); 759 my $levelint = uc($level) . "_INT"; 760 my $initial_cap = ucfirst($lclevel); 761 762 no strict qw(refs); 763 764 # This is a bit better way to create code on the fly than eval'ing strings. 765 # -erik 766 767 *{__PACKAGE__ . "::$lclevel"} = sub { 768 print "$lclevel: ($_[0]->{category}/$_[0]->{level}) [@_]\n" 769 if _INTERNAL_DEBUG; 770 init_warn() unless $INITIALIZED or $NON_INIT_WARNED; 771 $_[0]->{$level}->(@_, $level) if defined $_[0]->{$level}; 772 }; 773 774 # Added these to have is_xxx functions as fast as xxx functions 775 # -ms 776 777 *{__PACKAGE__ . "::is_$lclevel"} = sub { 778 $_[0]->{"is_" . $level}->($_[0], "is_" . $lclevel) if 779 defined $_[0]->{$level}; 780 }; 781 782 # Add the isXxxEnabled() methods as identical to the is_xxx 783 # functions. - dviner 784 785 *{__PACKAGE__ . "::is".$initial_cap."Enabled"} = 786 \&{__PACKAGE__ . "::is_$lclevel"}; 787 788 use strict qw(refs); 789 790 return 0; 791} 792 793#now lets autogenerate the logger subs based on the defined priorities 794foreach my $level (keys %Log::Log4perl::Level::PRIORITY){ 795 create_log_level_methods($level); 796} 797 798################################################## 799sub init_warn { 800################################################## 801 CORE::warn "Log4perl: Seems like no initialization happened. " . 802 "Forgot to call init()?\n"; 803 # Only tell this once; 804 $NON_INIT_WARNED = 1; 805} 806 807####################################################### 808# call me from a sub-func to spew the sub-func's caller 809####################################################### 810sub callerline { 811 # the below could all be just: 812 # my ($pack, $file, $line) = caller(2); 813 # but if we every bury this further, it'll break. So we do this 814 # little trick stolen and paraphrased from Carp/Heavy.pm 815 my($message) = @_; 816 817 my $i = 0; 818 my (undef, $localfile, undef) = caller($i++); 819 my ($pack, $file, $line); 820 do { 821 ($pack, $file, $line) = caller($i++); 822 } while ($file && $file eq $localfile); 823 824 my $has_newline; 825 826 $has_newline++ if chomp $message; 827 828 $message .= " at $file line $line" if !$has_newline; 829 830 # Someday, we'll use Threads. Really. 831 if (defined &Thread::tid) { 832 my $tid = Thread->self->tid; 833 $message .= " thread $tid" if $tid and !$has_newline; 834 } 835 return ($message, "\n"); 836} 837 838####################################################### 839sub and_warn { 840####################################################### 841 my $self = shift; 842 my $msg = join("", @_[0 .. $#_]); 843 CORE::warn(callerline($self->warning_render(@_[0 .. $#_]))); 844} 845 846####################################################### 847sub and_die { 848####################################################### 849 my $self = shift; 850 die(callerline($self->warning_render(@_[0 .. $#_]))); 851} 852 853################################################## 854sub logwarn { 855################################################## 856 my $self = shift; 857 if ($self->is_warn()) { 858 # Since we're one caller level off now, compensate for that. 859 $Log::Log4perl::caller_depth++; 860 my @chomped = @_; 861 chomp($chomped[-1]); 862 $self->warn(@chomped); 863 $Log::Log4perl::caller_depth--; 864 $self->and_warn(@_); 865 } 866} 867 868################################################## 869sub logdie { 870################################################## 871 my $self = shift; 872 if ($self->is_fatal()) { 873 # Since we're one caller level off now, compensate for that. 874 $Log::Log4perl::caller_depth++; 875 my @chomped = @_; 876 chomp($chomped[-1]); 877 $self->fatal(@chomped); 878 $Log::Log4perl::caller_depth--; 879 } 880 881 $Log::Log4perl::LOGDIE_MESSAGE_ON_STDERR ? 882 $self->and_die(@_) : 883 exit($Log::Log4perl::LOGEXIT_CODE); 884} 885 886################################################## 887sub logexit { 888################################################## 889 my $self = shift; 890 891 if ($self->is_fatal()) { 892 # Since we're one caller level off now, compensate for that. 893 $Log::Log4perl::caller_depth++; 894 my @chomped = @_; 895 chomp($chomped[-1]); 896 $self->fatal(@chomped); 897 $Log::Log4perl::caller_depth--; 898 } 899 900 exit $Log::Log4perl::LOGEXIT_CODE; 901} 902 903################################################## 904# clucks and carps are WARN level 905sub logcluck { 906################################################## 907 my $self = shift; 908 909 local $Carp::CarpLevel = $Carp::CarpLevel + 1; 910 my $msg = $self->warning_render(@_); 911 912 if ($self->is_warn()) { 913 my $message = Carp::longmess($msg); 914 local $Log::Log4perl::caller_depth = 915 $Log::Log4perl::caller_depth + 1; 916 foreach (split(/\n/, $message)) { 917 $self->warn("$_\n"); 918 } 919 Carp::cluck($msg); 920 } 921} 922 923################################################## 924sub logcarp { 925################################################## 926 my $self = shift; 927 928 local $Carp::CarpLevel = $Carp::CarpLevel + 1; 929 my $msg = $self->warning_render(@_); 930 931 if ($self->is_warn()) { 932 my $message = Carp::shortmess($msg); 933 local $Log::Log4perl::caller_depth = 934 $Log::Log4perl::caller_depth + 1; 935 foreach (split(/\n/, $message)) { 936 $self->warn("$_\n"); 937 } 938 Carp::carp($msg) if $Log::Log4perl::LOGDIE_MESSAGE_ON_STDERR; 939 } 940} 941 942################################################## 943# croaks and confess are FATAL level 944################################################## 945sub logcroak { 946################################################## 947 my $self = shift; 948 949 local $Carp::CarpLevel = $Carp::CarpLevel + 1; 950 my $msg = $self->warning_render(@_); 951 952 my $message = Carp::shortmess($msg); 953 local $Log::Log4perl::caller_depth = 954 $Log::Log4perl::caller_depth + 1; 955 if ($self->is_fatal()) { 956 foreach (split(/\n/, $message)) { 957 $self->fatal("$_\n"); 958 } 959 } 960 961 $Log::Log4perl::LOGDIE_MESSAGE_ON_STDERR ? 962 Carp::croak($msg) : 963 exit($Log::Log4perl::LOGEXIT_CODE); 964} 965 966################################################## 967sub logconfess { 968################################################## 969 my $self = shift; 970 971 my $msg = $self->warning_render(@_); 972 local $Carp::CarpLevel = $Carp::CarpLevel + 1; 973 974 my $message = Carp::longmess($msg); 975 local $Log::Log4perl::caller_depth = 976 $Log::Log4perl::caller_depth + 1; 977 if ($self->is_fatal()) { 978 foreach (split(/\n/, $message)) { 979 $self->fatal("$_\n"); 980 } 981 } 982 983 $Log::Log4perl::LOGDIE_MESSAGE_ON_STDERR ? 984 confess($msg) : 985 exit($Log::Log4perl::LOGEXIT_CODE); 986} 987 988################################################## 989# in case people prefer to use error for warning 990################################################## 991sub error_warn { 992################################################## 993 my $self = shift; 994 if ($self->is_error()) { 995 $Log::Log4perl::caller_depth++; 996 $self->error(@_); 997 $Log::Log4perl::caller_depth--; 998 $self->and_warn(@_); 999 } 1000} 1001 1002################################################## 1003sub error_die { 1004################################################## 1005 my $self = shift; 1006 1007 my $msg = $self->warning_render(@_); 1008 1009 if ($self->is_error()) { 1010 $Log::Log4perl::caller_depth++; 1011 $self->error($msg); 1012 $Log::Log4perl::caller_depth--; 1013 } 1014 1015 $Log::Log4perl::LOGDIE_MESSAGE_ON_STDERR ? 1016 $self->and_die($msg) : 1017 exit($Log::Log4perl::LOGEXIT_CODE); 1018} 1019 1020################################################## 1021sub more_logging { 1022################################################## 1023 my ($self) = shift; 1024 return $self->dec_level(@_); 1025} 1026 1027################################################## 1028sub inc_level { 1029################################################## 1030 my ($self, $delta) = @_; 1031 1032 $delta ||= 1; 1033 1034 $self->level(Log::Log4perl::Level::get_higher_level($self->level(), 1035 $delta)); 1036 1037 $self->set_output_methods; 1038} 1039 1040################################################## 1041sub less_logging { 1042################################################## 1043 my ($self) = shift; 1044 return $self->inc_level(@_); 1045} 1046 1047################################################## 1048sub dec_level { 1049################################################## 1050 my ($self, $delta) = @_; 1051 1052 $delta ||= 1; 1053 1054 $self->level(Log::Log4perl::Level::get_lower_level($self->level(), $delta)); 1055 1056 $self->set_output_methods; 1057} 1058 1059################################################## 1060 10611; 1062 1063__END__ 1064 1065=head1 NAME 1066 1067Log::Log4perl::Logger - Main Logger Class 1068 1069=head1 SYNOPSIS 1070 1071 # It's not here 1072 1073=head1 DESCRIPTION 1074 1075While everything that makes Log4perl tick is implemented here, 1076please refer to L<Log::Log4perl> for documentation. 1077 1078=head1 SEE ALSO 1079 1080=head1 AUTHOR 1081 1082 Mike Schilli, <log4perl@perlmeister.com> 1083 Kevin Goess, <cpan@goess.org> 1084 1085=cut 1086