Neues in der Kategorie Profiler

logs.jpg

Log::Dispatch von Dave Rolsky erlaubt die Ausgabe von Log-Nachrichten an mehrere unterschiedliche Ausgabeziele.

Vom einfachen Logging in eine Datei, Speicherung in einer Datenbank-Tabelle, Syslog oder EventLog, Versenden einer E-Mail mit Logdatei als Attachment oder als Kurznachricht auf einen Twitter-Account ist so ziemlich alles möglich, was das Herz begehrt.

 

Loglevel

Über Loglevel (Prioritäten) läßt sich einfach steuern, ob der Dispatcher die ihm übergebenen Nachrichten tatsächlich weiter gibt oder einfach unterdrückt.

Log::Dispatch legt dazu ähnlich wie syslog acht Stufen für die Dringlichkeit (Priorität) der Log-Nachricht fest:

  1. debug
  2. info
  3. notice
  4. warning
  5. error
  6. critical
  7. alert
  8. emergency

 

Dispatcher erzeugen

#!/usr/bin/perl
use strict;
use warnings;

use Log::Dispatch;

my $ld = Log::Dispatch->new();

 

Ausgabeziele und Annahmeprioritäten festlegen

Ein Dispatcher kann mehrere Ausgabeziele bedienen.

Über Loglevel lässt sich hier festlegen, für welche Prioritäten das Ausgabeziel Nachrichten annimmt und loggt.

Ausgabe der Lognachrichten in eine Datei

use Log::Dispatch::File;
$ld->add(
	Log::Dispatch::File->new(
		name => 'to_file',
		filename => 'logdatei.log',
		mode => 'append',
		min_level => 'debug',
		max_level => 'alert',
	)
);

Logging via syslogd

use Log::Dispatch::Syslog;
$ld->add(
	Log::Dispatch::Syslog->new(
		name => 'to_syslog',
                # Muss in /etc/syslog.conf eingerichtet sein
		facility => 'local5',
		min_level => 'debug',
		max_level => 'emergency',
	)
);

Ausgabe der Lognachrichten auf dem Bildschirm (STDERR)

use Log::Dispatch::Screen;
$ld->add(
	Log::Dispatch::Screen->new(
		name      => 'screen',
               min_level => 'debug',
               stderr    => 1, 
	)
);

 

Log It

Nach so viel Vorbereitung ist das eigentliche Absetzen der Lognachrichten ganz einfach.

$ld->log( level => 'notice', message => "Starte $0\n" );
# Oder kuerzer
$ld->notice( "Starte $0\n" );

$ld->log( level => 'emergency', message => "Die Huette brennt\n" );
# Oder kuerzer
$ld->emergency( "Die Huette brennt\n" );

Im Programm selbst wird nur festgelegt, was mit welcher Priorität geloggt werden kann. Ob die Nachricht auch wirklich geloggt wird, hängt von der Konfiguration der Ziele ab.

Man kann also ein Programm mit sehr vielen Log-Anweisungen versehen, das hilft beim Debuggen. Für den laufenden Betrieb lässt sich die Geschwätzigkeit des Programm einfach durch Änderung der Konfiguration senken.

 

Log4perl und Log::Dispatch

Als Alternative bietet sich das erstklassige Log4perl von Michael Schilli an. Log4perl, die Perl Implementierung von log4j, nutzt übrigens Log::Dispatch recht intensiv.

Es schadet daher nichts, sich in Log::Dispatch einzuarbeiten, auch wenn man dann auf log4perl umsteigt.

 

Siehe auch:

 

Bildnachweis

LOGS, LOGS, LOGS, LOGS von waldopepper (Lizenz).

Häufig steht man vor der Frage, wo genau eine Variable (oder allgemein ein Perl-Wert) referenziert wird.

Devel::FindRef von Marc Lehmann ist ein kleines Modul, mit dem man exakt herausfinden kann, wo eine bestimmte Variable referenziert wird, ob es einen Referenz-Zyklus gibt, oder welche closure den Wert noch referenziert.

Marc Lehmann hat Devel::FindRef in einem Lightning Talk auf dem 11. Deutschen Perl-Workshop in Frankfurt/Main vorgestellt.

Einfaches Beispiel

#!/usr/bin/perl 
use strict;
use warnings;

use Devel::FindRef;
                         
    # Die Variable, die untersucht werden soll
our $var            = 'hi there';

    # Ein paar Referenzen auf diese Variable
my $global_my       = \$var;
our %global_hash    = ( key1 => \$var );
our $global_hashref = { key2 => \$var };


testsub();
                           
sub testsub {             
      my $testsub_local = $global_hashref;
	  print "Track für \$var '$var':\n";
      print Devel::FindRef::track \$var;
}                             

Das Programm erzeugt folgende Ausgabe:

Track für $var 'hi there':
SCALAR(0x8169fe8) [refcount 5] is
+- in the global $main::var.
+- referenced by REF(0x8169fa8) [refcount 1], which is
|  in the lexical '$global_my' in CODE(0x8155318) [refcount 2], which is
|     +- the containing scope for CODE(0x81a5468) [refcount 3], which is
|     |  in the global &main::testsub.
|     +- the main body of the program.
+- referenced by REF(0x8169f28) [refcount 1], which is
|  in the member 'key2' of HASH(0x81550b8) [refcount 2], which is
|     +- referenced by REF(0x81a54c8) [refcount 1], which is
|     |  in the lexical '$testsub_local' in CODE(0x81a5468) [refcount 3], which was seen before.
|     +- referenced by REF(0x81a5168) [refcount 1], which is
|        in the global $main::global_hashref.
+- referenced by REF(0x8155308) [refcount 1], which is
|  in the member 'key1' of HASH(0x816a368) [refcount 1], which is
|     in the global %main::global_hash.
+- referenced by REF(0x81551d8) [refcount 1], which is
   a temporary on the stack.

Die Ausgabe muss man sich anfangs wohl zwei- oder dreimal anschauen, danach wird es besser.

Beispiel: Verwendung von closures und weaken

#!/usr/bin/perl 
use strict;
use warnings;


use Devel::FindRef;
use Scalar::Util;
                         
our $var            = 'hi there';
my $global_my       = \$var;
our %global_hash    = ( key1 => \$var);
our $global_hashref = { key2 => \$var };
                           
sub testsub {             
      my $testsub_local = $global_hashref;
	  print "Track fuer \$var '$var':\n";
      print Devel::FindRef::track \$var;
}                             


my $closure = sub {
      my $closure_var = \$_[0];
      Scalar::Util::weaken (my $weak_ref = \$var);
      testsub();
   };

$closure->($var);

Das Programm erzeugt folgende Ausgabe:

Track fuer $var 'hi there':
SCALAR(0x8169f58) [refcount 6] is
+- referenced by REF(0x81a5640) [refcount 1], which is
|  in the lexical '$closure_var' in CODE(0x81a5600) [refcount 4], which is
|     +- the closure created at f2.pl:22.
|     +- referenced by REF(0x81a5440) [refcount 1], which is
|     |  in the lexical '$closure' in CODE(0x8155318) [refcount 2], which is
|     |     +- the containing scope for CODE(0x81a5460) [refcount 3], which is
|     |     |  in the global &main::testsub.
|     |     +- the main body of the program.
|     +- in the lexical '&' in CODE(0x8155318) [refcount 2], which was seen before.
+- referenced by REF(0x816a008) [refcount 1], which is
|  in the lexical '$global_my' in CODE(0x8155318) [refcount 2], which was seen before.
+- in the global $main::var.
+- referenced by REF(0x8169f28) [refcount 1], which is
|  in the member 'key2' of HASH(0x81550b8) [refcount 2], which is
|     +- referenced by REF(0x81a54d0) [refcount 1], which is
|     |  in the lexical '$testsub_local' in CODE(0x81a5460) [refcount 3], which was seen before.
|     +- referenced by REF(0x81a51a0) [refcount 1], which is
|        in the global $main::global_hashref.
+- referenced by REF(0x8155308) [refcount 1], which is
|  in the member 'key1' of HASH(0x816a368) [refcount 1], which is
|     in the global %main::global_hash.
+- referenced by REF(0x81551d8) [refcount 1], which is
   a temporary on the stack.

Cool!

Siehe auch:

Über dieses Archiv

Diese Seite enthält aktuelle Einträge der Kategorie Profiler.

LWP ist die vorherige Kategorie.

Talks ist die nächste Kategorie.

Aktuelle Einträge finden Sie auf der Startseite, alle Einträge in den Archiven.

Perl Suchmaschine

Blog Roll

Powered by Movable Type 4.1