Re: coderef instead of filename for trace() ?

Re: coderef instead of filename for trace() ?

am 09.01.2007 13:39:34 von Tim.Bunce

On Sat, Dec 16, 2006 at 10:19:19AM -0800, Dean Arnold wrote:
> Tim Bunce wrote:
> >On Fri, Dec 15, 2006 at 03:26:46PM -0800, Dean Arnold wrote:
> >>One item: I'm currently using a separate 19fhtrace.t test script;
> >>should I merge it into 09trace.t ? Or leave it separate ?
> >>(I'll vote for separate, since its easier to test the feature
> >>standalone that way)
> >
> >I agree.
> >
>
> OK. And your 2 examples worked (w/ a little tweaking), so I've added
> them to the test script. Revised POD for "Tracing To Layered Filehandles"
> below. I'll checkin once you're OK w/ the POD.

Sorry for the delay (again) Dean. I missed that last sentence and just
assumed you'd check it in - and then I stopped paying much attention
over the xmas period.

You can always err on the side of checking something in. After all,
that's what revisiion control is all about!

Thanks again for your excellent work on this Dean.

Tim.

> - Dean
>
> =head2 Tracing to Layered Filehandles
>
> B:
>
> =over 4
>
> =item *
> Tied filehandles are not currently supported, as
> tie operations are not available to the PerlIO
> methods used by the DBI.
>
> =item *
> PerlIO layer support requires Perl version 5.8 or higher.
>
> =back
>
> As of version 5.8, Perl provides the ability to layer various
> "disciplines" on an open filehandle via the L module.
>
> A simple example of using PerlIO layers is to use a scalar as the output:
>
> my $scalar = '';
> open( my $fh, "+>:scalar", \$scalar );
> $dbh->trace( 2, $fh );
>
> Now all trace output is simply appended to $scalar.
>
> A more complex application of tracing to a layered filehandle is the
> use of a custom layer (IL I > on creating custom PerlIO layers.>). Consider an application with the
> following logger module:
>
> package MyFancyLogger;
>
> sub new
> {
> my $self = {};
> my $fh;
> open $fh, '>', 'fancylog.log';
> $self->{_fh} = $fh;
> $self->{_buf} = '';
> return bless $self, shift;
> }
>
> sub log
> {
> my $self = shift;
> return unless exists $self->{_fh};
> my $fh = $self->{_fh};
> $self->{_buf} .= shift;
> #
> # DBI feeds us pieces at a time, so accumulate a complete line
> # before outputing
> #
> print $fh "At ", scalar localtime(), ':', $self->{_buf}, "\n" and
> $self->{_buf} = ''
> if $self->{_buf}=~tr/\n//;
> }
>
> sub close {
> my $self = shift;
> return unless exists $self->{_fh};
> my $fh = $self->{_fh};
> print $fh "At ", scalar localtime(), ':', $self->{_buf}, "\n" and
> $self->{_buf} = ''
> if $self->{_buf};
> close $fh;
> delete $self->{_fh};
> }
>
> 1;
>
> To redirect DBI traces to this logger requires creating
> a package for the layer:
>
> package PerlIO::via::MyFancyLogLayer;
>
> sub PUSHED
> {
> my ($class,$mode,$fh) = @_;
> my $logger;
> return bless \$logger,$class;
> }
>
> sub OPEN {
> my ($self, $path, $mode, $fh) = @_;
> #
> # $path is actually our logger object
> #
> $$self = $path;
> return 1;
> }
>
> sub WRITE
> {
> my ($self, $buf, $fh) = @_;
> $$self->log($buf);
> return length($buf);
> }
>
> sub CLOSE {
> my $self = shift;
> $$self->close();
> return 0;
> }
>
> 1;
>
>
> The application can then cause DBI traces to be routed to the
> logger using
>
> use PerlIO::via::MyFancyLogLayer;
>
> open my $fh, '>:via(MyFancyLogLayer)', MyFancyLogger->new();
>
> $dbh->trace('SQL', $fh);
>
> Now all trace output will be processed by MyFancyLogger's
> log() method.