Tim Bunce hat den Screencast und die Slides seines Vortrags State-of-the-art Profiling with Devel::NYTProf auf dem Italian Perl Workshop 2009 (endlich) online gestellt.
State-of-the-art Profiling with Devel::NYTProf
Tim Bunce hat den Screencast und die Slides seines Vortrags State-of-the-art Profiling with Devel::NYTProf auf dem Italian Perl Workshop 2009 (endlich) online gestellt.
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.
Ü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:
#!/usr/bin/perl use strict; use warnings; use Log::Dispatch; my $ld = Log::Dispatch->new();
Ein Dispatcher kann mehrere Ausgabeziele bedienen.
Über Loglevel lässt sich hier festlegen, für welche Prioritäten das Ausgabeziel Nachrichten annimmt und loggt.
use Log::Dispatch::File; $ld->add( Log::Dispatch::File->new( name => 'to_file', filename => 'logdatei.log', mode => 'append', min_level => 'debug', max_level => 'alert', ) );
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', ) );
use Log::Dispatch::Screen; $ld->add( Log::Dispatch::Screen->new( name => 'screen', min_level => 'debug', stderr => 1, ) );
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.
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.
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.
#!/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.
#!/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!