Author: timbo
Date: Wed Jun 13 07:23:14 2007
New Revision: 9647

Modified:
   dbi/trunk/Changes
   dbi/trunk/lib/DBI/Profile.pm
   dbi/trunk/t/40profile.t

Log:
Added as_text() method and tests.


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Wed Jun 13 07:23:14 2007
@@ -57,7 +57,7 @@
 
   DBI::Profile changes:
     Don't profile DESTROY during global destruction.
-    Added as_node_path_list() method.
+    Added as_node_path_list() and as_text() methods and tests.
   DBI::ProfileDumper changes:
     Don't write file if there's no profile data.
     Uses full natural precision when saving data (was using %.6f)

Modified: dbi/trunk/lib/DBI/Profile.pm
==============================================================================
--- dbi/trunk/lib/DBI/Profile.pm        (original)
+++ dbi/trunk/lib/DBI/Profile.pm        Wed Jun 13 07:23:14 2007
@@ -479,6 +479,45 @@
 added to each element of the returned list. If not specified it defaults to a a
 ref to an empty array.
 
+=head2 as_text
+
+  @txt = $dbh->{Profile}->as_text();
+  $txt = $dbh->{Profile}->as_text({
+      node      => undef,
+      path      => [],
+      separator => " > ",
+      format    => '%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min 
%13$fs, max %14$fs)'."\n";
+      sortsub   => sub { ... },
+  );
+
+Returns the collected data ($dbh->{Profile}{Data}) reformatted into a list of 
formatted strings.
+In scalar context the list is returned as a single contatenated string.
+
+A hashref can be used to pass in arguments, the default values are shown in 
the example above.
+
+The C<node> and <path> arguments are passed to as_node_path_list().
+
+The C<separator> argument is used to join the elemets of the path for each 
leaf node.
+
+The C<sortsub> argument is used to pass in a ref to a sub that will order the 
list.
+The subroutine will be passed a reference to the array returned by 
as_node_path_list().
+
+The C<format> argument is a C<sprintf> format string that specifies the format
+to use for each leaf node.  It uses the explicit format parameter index
+mechanism to specify which of the arguments should appear where in the string.
+The arguments to sprintf are:
+
+     1:  path to node, joined with the separator
+     2:  average duration (total/count)
+         (3 thru 9 are currently unused)
+    10:  count
+    11:  total duration
+    12:  first_duration
+    13:  smallest duration
+    14:  largest duration
+    15:  time of first call
+    16:  time of first call
+
 =head1 CUSTOM DATA MANIPULATION
 
 Recall that C<$h->{Profile}->{Data}> is a reference to the collected data.
@@ -743,6 +782,36 @@
 }
 
 
+sub as_text {
+    my ($self, $args_ref) = @_;
+    my $separator = $args_ref->{separator} || " > ";
+    my $format    = $args_ref->{format}
+        || '%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min %13$fs, max 
%14$fs)'."\n";
+    
+    my @node_path_list = $self->as_node_path_list(undef, $args_ref->{path});
+
+    $args_ref->{sortsub}->([EMAIL PROTECTED]) if $args_ref->{sortsub};
+
+    my $eval = "qr/".quotemeta($separator)."/";
+    my $separator_re = eval($eval) || quotemeta($separator);
+    #warn "[$eval] = [$separator_re]";
+    my @text;
+    for my $node_path (@node_path_list) {
+        my ($node, @path) = @$node_path;
+        s/[\r\n]+/ /g for @path;
+        s/$separator_re/ /g for @path;
+        my $path_str = join($separator, @path);
+        push @text, sprintf $format,
+            $path_str,                                # 1=path
+            ($node->[0] ? $node->[4]/$node->[0] : 0), # 2=avg
+            (undef) x 7,                              # spare slots
+            @$node; # 10=count, 11=dur, 12=first_dur, 13=min, 14=max, 
15=first_called, 16=last_called
+    }       
+    return @text if wantarray;
+    return join "", @text;
+}   
+
+
 sub format {
     my $self = shift;
     my $class = ref($self) || $self;

Modified: dbi/trunk/t/40profile.t
==============================================================================
--- dbi/trunk/t/40profile.t     (original)
+++ dbi/trunk/t/40profile.t     Wed Jun 13 07:23:14 2007
@@ -323,7 +323,9 @@
     $sth->fetchrow_hashref;
     $sth->finish;
     undef $sth; # DESTROY
-    return sanitize_profile_data_nodes($dbh->{Profile}{Data});
+    my $data = sanitize_profile_data_nodes($dbh->{Profile}{Data}, 1);
+    return ($data, $dbh) if wantarray;
+    return $data;
 }
 
 $tmp = run_test1( { Path => [ 'foo', sub { 'bar' }, 'baz' ] });
@@ -368,6 +370,24 @@
 
 # 
-----------------------------------------------------------------------------------
 
+print "testing as_text\n";
+
+($tmp, $dbh) = run_test1( { Path => [ 'foo', '!MethodName', 'baz' ] });
+my $as_text = $dbh->{Profile}->as_text();
+$as_text =~ s/\.00+/.0/g;
+#warn "[$as_text]";
+is $as_text, q{foo > DESTROY > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, 
max 0.0s)
+foo > FETCH > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
+foo > STORE > baz: 0.0s / 5 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
+foo > connected > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
+foo > execute > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
+foo > fetchrow_hashref > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 
0.0s)
+foo > finish > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
+foo > prepare > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
+};
+
+# 
-----------------------------------------------------------------------------------
+
 print "dbi_profile_merge_nodes\n";
 my $total_time = dbi_profile_merge_nodes(
     my $totals=[],
@@ -393,8 +413,9 @@
 
 sub sanitize_tree {
     my $data = shift;
+    my $skip_clone = shift;
     return $data unless ref $data;
-    $data = dclone($data);
+    $data = dclone($data) unless $skip_clone;
     sanitize_profile_data_nodes($data->{Data}) if $data->{Data};
     return $data;
 }

Reply via email to