Changeset 373


Ignore:
Timestamp:
Mar 19, 2010, 12:16:29 AM (11 years ago)
Author:
zerodeux
Message:

HTML output, at last! Woaaaaaa, cute

Location:
phptop
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • phptop/NEWS

    r366 r373  
    22
    33    * New -o|--output-mode option, refactored reporting internally
     4    * New HTML output support
    45    * Text output: showing sorting column with '>' on text output
    56    * Text output: multiple reports are globally column aligned
  • phptop/phptop

    r366 r373  
    2121use Getopt::Long qw(:config no_auto_abbrev no_ignore_case bundling);
    2222use HTTP::Date;
    23 use POSIX;
     23use POSIX qw(setlocale strftime);
    2424use Term::Size;
    25 use HTML::Template;
     25use Sys::Hostname;
    2626
    2727my $package_name    = 'phptop';
     
    3131
    3232# Options
     33my @opts = @ARGV;  # Save @ARGV, we let GetOptions() modify it
    3334my $help;
    3435my $version;
     
    115116    }
    116117
    117     POSIX::setlocale(POSIX::LC_NUMERIC, 'C'); # Use . as decimal separator
     118    setlocale(POSIX::LC_NUMERIC, 'C'); # Use . as decimal separator
    118119
    119120  LINE:
     
    179180# fix_stat() is called once all log files have been parsed and only once,
    180181# and modifies a few values in %stat for a useful display.
     182#
    181183sub fix_stat {
    182184    while (my ($url, $i) = each %stat) {
     
    270272# html_report() renders a report from the inlined template in DATA section
    271273#
    272 sub hmtl_report {
     274sub html_report {
     275    my $host = hostname();
     276    my $date = strftime('%Y-%m-%d %H:%M', localtime());
     277    my $args = join(' ', @opts);
     278
     279    my $rows;
     280    foreach my $key (@sortkeys) {
     281        my $r = raw_report($key);
     282
     283        my $header_class = sub {
     284            shift;
     285            (/^URL/ ? ' url' : '').
     286            (/^$key(\/hit)?$/i ? ' sortby' : '')
     287        };
     288        $rows .= html_report_row('th', $header_class, $r->{headers});
     289
     290        my $row_class = sub { shift; /^[0-9.]*$/ ? '' : ' url' };
     291        $rows .= html_report_row('td', $row_class, $_) foreach @{$r->{rows}};
     292
     293        my $sum_class = sub { shift; ' sum'.(/^[0-9.]*$/ ? '' : ' url') };
     294        $rows .= html_report_row('td', $sum_class, $r->{sums});
     295    }
     296    chomp($rows);
     297
     298    # Tried with HTML::Template but it was plain ugly to implement the magic
     299    # in html_report_row with proper HTML/logic separation.
     300    my %param = (
     301        TITLE  => "phptop\@$host",
     302        ROWS   => $rows,
     303        FOOTER => "Generated by <a href=\"$package_url\">$package_name $package_version</a>".
     304                  " from <em>$host</em> on $date".
     305                  ($args ne "" ? " (options: <code>$args</code>)": ""),
     306    );
     307    my $tmpl = do { local($/); <DATA> };
     308    $tmpl =~  s/::(\w+)/$param{$1}/g;
     309    print $tmpl;
     310}
     311sub html_report_row {
     312    my ($tag, $classfunc, $cells) = @_;
     313
     314    my $row = "<tr>\n";
     315    foreach (@$cells) {
     316        my $class = $classfunc->($_);    # Ask for classes
     317        $class =~ s/^ +//;               # Put up with ugly concatenation
     318        $class &&= " class=\"$class\"";  # Only set class if some is set
     319        $row .= "  <$tag$class>$_</$tag>\n";
     320    }
     321    $row .= "</tr>\n";
    273322}
    274323
     
    326375text_report() if $output eq 'text';
    327376html_report() if $output eq 'html';
     377
     378
     379__DATA__
     380<?xml version="1.0" encoding="UTF-8"?>
     381<!DOCTYPE html
     382     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     383    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
     384<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
     385  <head>
     386    <title>::TITLE</title>
     387    <style type="text/css">
     388      table.stat { border-collapse: collapse; border-spacing: 0 }
     389      .stat th { border-bottom: solid black 1px }
     390      .stat th, .stat td { padding: .15em .25em .15em .75em; text-align: right; border-left: solid #ccc 1px }
     391      .stat th.url, .stat td.url { padding: .15em .5em .15em 0; text-align: left; border-left: none }
     392      .stat th.sortby { background-color: black; color: white }
     393      .stat td.sum { font-weight: bold; padding-bottom: 1em }
     394      .stat tr:hover td { background-color: #eee }
     395      .stat a, .stat a:visited { color: black; text-decoration: none }
     396      #footer, #footer a, #footer a:visited { color: #aaa; margin-top: 1em }
     397      #footer em { font-style: normal; font-weight: bold }
     398    </style>
     399  </head>
     400  <body>
     401    <table class="stat">
     402::ROWS
     403    </table>
     404    <p id="footer">::FOOTER</p>
     405  </body>
     406</html>
Note: See TracChangeset for help on using the changeset viewer.