package Logfile::GD_Logfile; =head1 NAME GD_Logfile - add a graphing feature the Logfile class, a single method to allow bar graph generation of log data. Uses the GD module to produce the graph. =head1 SYNOPSYS Logfile::GD_Logfile::graph($l,Group => File, Sort => Records, ImSize => [640,480], Font => `gdSmallFont' ); Where $l is a Logfile object, ImSize is the output image size, and Font is a font from the GD module. All other parameters to the Logfile::report() method may be included, but only one List variable may be passed in. =head1 AUTHOR Bill Middleton - wjm@best.com =cut use GD; sub graph{ my $self = shift; my %par = @_; my $group = $self->group($par{Group}); my $sort = $par{Sort} || $group; my $font = $par{Font}; my $rever = (($sort =~ /Date|Hour/) xor $par{Reverse}); my $list = $par{List}; my ($keys, $key, $val, %keys); my $direction = ($rever)?'increasing':'decreasing'; my (@list, %absolute); my (@sorted, $rec_total, $largest, $list_total); my ($width, $ht, $color, $black, $white); my ($im, $i, $inc); my($top,$bottom,$left,$right); my($color_inc,$title); my($third,$fourth,$current); # Instantiate a new GD image based on args or default if(ref($par{ImSize})){ $im = new GD::Image(@{$par{ImSize}}); $right = $par{ImSize}->[0] - 30; $top = $par{ImSize}->[1] - 30 ; $left = $par{ImSize}->[0] / 2; $bottom = $par{ImSize}->[1] /10; } else{ # defaults to 640x480 $im = new GD::Image(640,480); # default $right = 610; $top = 450; $left = 320; $bottom = 48; } # Set up a few basic colors and sizes $width = $right - $left; $ht = $top - $bottom ; $white = $im->colorAllocate(255, 255, 255); $black = $im->colorAllocate(0 , 0, 0); $im->transparent($white); # Graphs of this sort only make sense with single variable if ($list) { if (ref($list)) { die "Sorry, graphs may have only one List variable\n" } } else { $list = "Records"; } # Sum things up while (($key,$val) = each %{$self->{$group}}) { $keys{$key} = $val->{$sort}; $rec_total+=1; $list_total += $val->{$list}; } (defined $par{Top}) and $rec_total = $par{Top}; # Graph outline $im->line($left,$top,$right,$top,$black); $im->line($left,$top,$left,$bottom,$black); # Graph Title $title = "Percentages of $list by $group"; $im->string(gdLargeFont,$left,10,$title,$black); $title = "Total $list = $list_total"; $im->string(gdMediumBoldFont,$left, ($top + $bottom/4),$title,$black); # $i will be our color increment variable for grayscale $i = 200; $color_inc = 100 / $rec_total; $top = $bottom + ($ht / $rec_total); # A couple of text layout variables $fourth= (($ht / $rec_total) / 4); $third = (($ht / $rec_total) / 3); # Main loop iterates over items, draws the text field and # rectangle representing the percentage of total for each for $key ( sort {&Logfile::Base::srt($rever, $keys{$a}, $keys{$b})} keys %keys){ my $val = $self->{$group}->{$key}; next unless defined($val); $color = $im->colorAllocate($i, $i, $i); if ($key =~ /$;/) { die "Sorry, graphs may have only one key\n"; } $current = $top - $fourth * 3; $im->string(&{$font},10,$current,$key,$black); $title = sprintf("%s(%4.2f%%)",' ` x 5, ($val->{$list}/$list_total * 100)); $current = $top - $third; $im->string(&{$font},10,$current,$title,$black); $right = $left + ($width * $val->{$list} / $list_total); $im->rectangle($left,$top,$right,$bottom,$black); $im->fill(($left+1),($bottom+1),$color); $bottom = $top; $top += $ht / $rec_total; last if defined $par{Top} && --$par{Top} <= 0; $i -= $color_inc; } # Dump the GIF to stdout print $im->gif; } 1;
Now you can produce a nice, two-dimensional graph of your log file data with Listing 14.5.
by
updated