package Test::Parser::SysbenchFileIO; =head1 NAME Test::Parser::SysbenchFileIO - Perl module to parse output from Sysbench --test=fileio =head1 SYNOPSIS use Test::Parser::SysbenchFileIO; my $parser = new Test::Parser::SysbenchFileIO; $parser->parse($text); $parser->to_xml(); Additional information is available from the subroutines listed below and from the L baseclass. =head1 DESCRIPTION This module provides a way to parse and neatly display information gained from the Sysbench FileIO test. This module will parse the output given by this command and commands similar to it: `sysbench --test=fileio > fileio.output` The fileio.output contains the necessary information that SysbenchFileIO is able to parse. =head1 FUNCTIONS Also see L for functions available from the base class. =cut use strict; use warnings; use Test::Parser; @Test::Parser::SysbenchFileIO::ISA = qw(Test::Parser); use base 'Test::Parser'; use fields qw( data ); use vars qw( %FIELDS $AUTOLOAD $VERSION ); our $VERSION = '1.4'; =head2 new() Purpose: Create a new Test::Parser::SysbenchFileIO instance Input: None Output: SysbenchFileIO object =cut sub new { my $class = shift; my Test::Parser::SysbenchFileIO $self = fields::new($class); $self->SUPER::new(); $self->testname('sysbench'); $self->type('unit'); $self->description('A variety of tests'); $self->summary('Lots of things'); $self->license('FIXME'); $self->vendor('FIXME'); $self->release('FIXME'); $self->url('FIXME'); $self->platform('FIXME'); $self->{data} = (); return $self; } =head2 data() Purpose: Return a hash representation of the Sysbench data Input: None Output: SysbenchFileIO data =cut sub data { my $self = shift; if (@_) { $self->{data} = @_; } return {sysbench => {data => $self->{data}}}; } =head2 parse_line() Purpose: Parse Sysbench --test=fileio log files. This method override's the default parse_line() of Test::Parser Input: String (one line of log file) Output: 1 =cut sub parse_line { my $self = shift; my $line = shift; my @labels = (); my @keys = (); my $size = 0; # # Trim any leading and trailing whitespaces. # $line =~ s/(^\s+|\s+$)//g; # Determine what info we have in the line... if ($line =~ /^Number .*?threads:(.+)/) { $keys[1] = $1; $labels[1] = 'num_threads'; $size = 1; } elsif ($line =~ /^sysbench v(.+):/) { $self->testname('sysbench'); $self->version($1); } elsif ($line =~ /^Doing c(.+)/) { $keys[1] = $1; $labels[1] = 'desc'; $size = 1; } elsif ($line =~ /^Extra .*?flags:(.+)/) { $keys[1] = $1; $labels[1] = 'file_open_flags'; $size = 1; } # These are done together as there are 2 pieces of information on each line elsif ($line =~ /^(.+).*?files, (\d+)(\w+).*?each/) { $keys[1] = $1; $labels[1] = 'num_files'; $keys[2] = $2; $labels[2] = 'file_size'; $keys[3] = $3; $labels[3] = 'file_size_units'; $size = 3; } elsif ($line =~ /^(\d+)(\w+).*?total file size/) { $keys[1] = $1; $labels[1] = 'total_file_size'; $keys[2] = $2; $labels[2] = 'total_file_size_units'; $size = 2; } elsif ($line =~ /^Block size (\d+)(\w+).*/) { $keys[1] = $1; $labels[1] = 'block_size'; $keys[2] = $2; $labels[2] = 'block_size_units'; $size = 2; } elsif ($line =~ /^Number .*?IO:(.+)/) { $keys[1] = $1; $labels[1] = 'num_random_req'; $size = 1; } elsif ($line =~ /^Read.*?test:(.+)/) { $keys[1] = $1; $labels[1] = 'rw_ratio'; $size = 1; } # These are done together as there are 2 pieces of information on each line elsif ($line =~ /^Periodic FSYNC(.+), calling fsync\(\) each (.+) requests/) { $keys[1] = $1; $labels[1] = 'fsync_status'; $keys[2] = $2; $labels[2] = 'fsync_freq'; $size = 2; } elsif ($line =~ /^Calling .*?test,(.+)./) { $keys[1] = $1; $labels[1] = 'fsync_end'; $size = 1; } elsif ($line =~ /^Using (.+) mode/) { $keys[1] = $1; $labels[1] = 'io_mode'; $size = 1; } elsif ($line =~ /^Doing (.+) test/) { $keys[1] = $1; $labels[1] = 'test_run'; $size = 1; } elsif ($line =~ /(.+).*Requests/) { $keys[1] = $1; $labels[1] = 'op_req_rate'; $size = 1; } elsif ($line =~ /^total .*?time:\s+([\.\d]+)(\w+)/) { $keys[1] = $1; $labels[1] = 'total_time'; $keys[2] = $2; $labels[2] = 'total_time_units'; $size = 2; } elsif ($line =~ /^total .*?events:\s+(.+)/) { $keys[1] = $1; $labels[1] = 'total_events'; $size = 1; } elsif ($line =~ /^total .*?execution:\s+(.+)/) { $keys[1] = $1; $labels[1] = 'total_exec'; $size = 1; } elsif ($line =~ /^min:\s+([\.\d]+)(\w+)/) { $keys[1] = $1; $labels[1] = 'pr_min'; $keys[2] = $2; $labels[2] = 'pr_min_units'; $size = 2; } elsif ($line =~ /^avg:\s+([\.\d]+)(\w+)/) { $keys[1] = $1; $labels[1] = 'pr_avg'; $keys[2] = $2; $labels[2] = 'pr_avg_units'; $size = 2; } elsif ($line =~ /^max:\s+([\.\d]+)(\w+)/) { $keys[1] = $1; $labels[1] = 'pr_max'; $keys[2] = $2; $labels[2] = 'pr_max_units'; $size = 2; } elsif ($line =~ /^approx. .*?tile:\s+([\.\d]+)(\w+)/) { $keys[1] = $1; $labels[1] = 'pr_95'; $keys[2] = $2; $labels[2] = 'pr_95_units'; $size = 2; } # These are done together as there are 2 pieces of information on each line elsif ($line =~ /^events .*?:(.+)\/(.+)/) { $keys[1] = $1; $labels[1] = 'event_avg'; $keys[2] = $2; $labels[2] = 'event_stddev'; $size = 2; } # These are done together as there are 2 pieces of information on each line elsif ($line =~ /^execution .*?:(.+)\/(.+)/) { $keys[1] = $1; $labels[1] = 'exec_avg'; $keys[2] = $2; $labels[2] = 'exec_stddev'; $size = 2; } # These are done together as there are 4 pieces of information on each line elsif ($line =~ /^Operations performed: (.+) Read, (.+) Write, (.+) Other = (.+) Total/) { $keys[1] = $1; $labels[1] = 'ops_reads'; $keys[2] = $2; $labels[2] = 'ops_write'; $keys[3] = $3; $labels[3] = 'ops_other'; $keys[4] = $4; $labels[4] = 'ops_total'; $size = 4; } # These are done together as there are 4 pieces of information on each line elsif ($line =~ /^Read ([\.\d]+)(\w+)\s+Written\s+([\.\d]+)(\w+).*\s+transferred\s+([\.\d]+)(\w+)\s+\(([\.\d]+)(\w+)/) { $keys[1] = $1; $labels[1] = 'op_read'; $keys[2] = $2; $labels[2] = 'op_read_units'; $keys[3] = $3; $labels[3] = 'op_written'; $keys[4] = $4; $labels[4] = 'op_written_units'; $keys[5] = $5; $labels[5] = 'op_trans_total'; $keys[6] = $6; $labels[6] = 'op_trans_total_units'; $keys[7] = $7; $labels[7] = 'op_trans_rate'; $keys[8] = $8; $labels[8] = 'op_trans_rate_units'; $size = 8; } my $do_units = 0; for (my $tekey = 0; $tekey <= $size; $tekey++) { if( $tekey+1 <= $size ) { my $check_me = $labels[$tekey+1]; my $orig = $labels[$tekey]; my $units = $orig; $units .= "_units"; if( $check_me eq $units ) { $do_units = 1; } } if ( defined($labels[$tekey]) ) { $keys[$tekey] =~ s/(^\s+|\s+$)//g; my $col = 0; if ($do_units == 1) { $keys[$tekey+1] =~ s/(^\s+|\s+$)//g; $col = $self->add_column( $labels[$tekey], $keys[$tekey+1] ); $self->add_data( $keys[$tekey], $col ); $tekey++; } else { $col = $self->add_column( $labels[$tekey] ); $self->add_data( $keys[$tekey], $col ); } $do_units=0; } } return 1; } 1; __END__ =head1 AUTHOR John Daiker =head1 COPYRIGHT Copyright (C) 2006 John Daiker & Open Source Development Labs, Inc. All Rights Reserved. This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L =end