1package Test::Parser::SysbenchFileIO; 2 3=head1 NAME 4 5Test::Parser::SysbenchFileIO - Perl module to parse output from Sysbench --test=fileio 6 7=head1 SYNOPSIS 8 9 use Test::Parser::SysbenchFileIO; 10 my $parser = new Test::Parser::SysbenchFileIO; 11 $parser->parse($text); 12 13 $parser->to_xml(); 14 15Additional information is available from the subroutines listed below 16and from the L<Test::Parser> baseclass. 17 18=head1 DESCRIPTION 19 20This module provides a way to parse and neatly display information gained from the 21Sysbench FileIO test. This module will parse the output given by this command and 22commands similar to it: `sysbench --test=fileio > fileio.output` The fileio.output contains 23the necessary information that SysbenchFileIO is able to parse. 24 25=head1 FUNCTIONS 26 27Also see L<Test::Parser> for functions available from the base class. 28 29=cut 30 31use strict; 32use warnings; 33use Test::Parser; 34 35@Test::Parser::SysbenchFileIO::ISA = qw(Test::Parser); 36use base 'Test::Parser'; 37 38use fields qw( 39 data 40 ); 41 42use vars qw( %FIELDS $AUTOLOAD $VERSION ); 43our $VERSION = '1.7'; 44 45 46=head2 new() 47 48 Purpose: Create a new Test::Parser::SysbenchFileIO instance 49 Input: None 50 Output: SysbenchFileIO object 51 52=cut 53sub new { 54 my $class = shift; 55 my Test::Parser::SysbenchFileIO $self = fields::new($class); 56 $self->SUPER::new(); 57 58 $self->testname('sysbench'); 59 $self->type('unit'); 60 $self->description('A variety of tests'); 61 $self->summary('Lots of things'); 62 $self->license('FIXME'); 63 $self->vendor('FIXME'); 64 $self->release('FIXME'); 65 $self->url('FIXME'); 66 $self->platform('FIXME'); 67 68 $self->{data} = (); 69 70 return $self; 71} 72 73 74=head2 data() 75 76 Purpose: Return a hash representation of the Sysbench data 77 Input: None 78 Output: SysbenchFileIO data 79 80=cut 81sub data { 82 my $self = shift; 83 if (@_) { 84 $self->{data} = @_; 85 } 86 return {sysbench => {data => $self->{data}}}; 87} 88 89 90=head2 parse_line() 91 92 Purpose: Parse Sysbench --test=fileio log files. This method override's the default parse_line() of Test::Parser 93 Input: String (one line of log file) 94 Output: 1 95 96=cut 97sub parse_line { 98 my $self = shift; 99 my $line = shift; 100 101 my @labels = (); 102 my @keys = (); 103 my $size = 0; 104 105 # 106 # Trim any leading and trailing whitespaces. 107 # 108 $line =~ s/(^\s+|\s+$)//g; 109 110 # Determine what info we have in the line... 111 if ($line =~ /^Number .*?threads:(.+)/) { 112 $keys[1] = $1; 113 $labels[1] = 'num_threads'; 114 $size = 1; 115 } 116 elsif ($line =~ /^sysbench v(.+):/) { 117 $self->testname('sysbench'); 118 $self->version($1); 119 } 120 elsif ($line =~ /^Doing c(.+)/) { 121 $keys[1] = $1; 122 $labels[1] = 'desc'; 123 $size = 1; 124 } 125 126 elsif ($line =~ /^Extra .*?flags:(.+)/) { 127 $keys[1] = $1; 128 $labels[1] = 'file_open_flags'; 129 $size = 1; 130 } 131 132 # These are done together as there are 2 pieces of information on each line 133 elsif ($line =~ /^(.+).*?files, (\d+)(\w+).*?each/) { 134 $keys[1] = $1; 135 $labels[1] = 'num_files'; 136 $keys[2] = $2; 137 $labels[2] = 'file_size'; 138 $keys[3] = $3; 139 $labels[3] = 'file_size_units'; 140 $size = 3; 141 } 142 143 elsif ($line =~ /^(\d+)(\w+).*?total file size/) { 144 $keys[1] = $1; 145 $labels[1] = 'total_file_size'; 146 $keys[2] = $2; 147 $labels[2] = 'total_file_size_units'; 148 $size = 2; 149 } 150 151 elsif ($line =~ /^Block size (\d+)(\w+).*/) { 152 $keys[1] = $1; 153 $labels[1] = 'block_size'; 154 $keys[2] = $2; 155 $labels[2] = 'block_size_units'; 156 $size = 2; 157 } 158 159 elsif ($line =~ /^Number .*?IO:(.+)/) { 160 $keys[1] = $1; 161 $labels[1] = 'num_random_req'; 162 $size = 1; 163 } 164 165 elsif ($line =~ /^Read.*?test:(.+)/) { 166 $keys[1] = $1; 167 $labels[1] = 'rw_ratio'; 168 $size = 1; 169 } 170 171 # These are done together as there are 2 pieces of information on each line 172 elsif ($line =~ /^Periodic FSYNC(.+), calling fsync\(\) each (.+) requests/) { 173 $keys[1] = $1; 174 $labels[1] = 'fsync_status'; 175 $keys[2] = $2; 176 $labels[2] = 'fsync_freq'; 177 $size = 2; 178 } 179 180 elsif ($line =~ /^Calling .*?test,(.+)./) { 181 $keys[1] = $1; 182 $labels[1] = 'fsync_end'; 183 $size = 1; 184 } 185 186 elsif ($line =~ /^Using (.+) mode/) { 187 $keys[1] = $1; 188 $labels[1] = 'io_mode'; 189 $size = 1; 190 } 191 192 elsif ($line =~ /^Doing (.+) test/) { 193 $keys[1] = $1; 194 $labels[1] = 'test_run'; 195 $size = 1; 196 } 197 198 elsif ($line =~ /(.+).*Requests/) { 199 $keys[1] = $1; 200 $labels[1] = 'op_req_rate'; 201 $size = 1; 202 } 203 204 elsif ($line =~ /^total .*?time:\s+([\.\d]+)(\w+)/) { 205 $keys[1] = $1; 206 $labels[1] = 'total_time'; 207 $keys[2] = $2; 208 $labels[2] = 'total_time_units'; 209 $size = 2; 210 } 211 212 elsif ($line =~ /^total .*?events:\s+(.+)/) { 213 $keys[1] = $1; 214 $labels[1] = 'total_events'; 215 $size = 1; 216 } 217 218 elsif ($line =~ /^total .*?execution:\s+(.+)/) { 219 $keys[1] = $1; 220 $labels[1] = 'total_exec'; 221 $size = 1; 222 } 223 224 elsif ($line =~ /^min:\s+([\.\d]+)(\w+)/) { 225 $keys[1] = $1; 226 $labels[1] = 'pr_min'; 227 $keys[2] = $2; 228 $labels[2] = 'pr_min_units'; 229 $size = 2; 230 } 231 232 elsif ($line =~ /^avg:\s+([\.\d]+)(\w+)/) { 233 $keys[1] = $1; 234 $labels[1] = 'pr_avg'; 235 $keys[2] = $2; 236 $labels[2] = 'pr_avg_units'; 237 $size = 2; 238 } 239 240 elsif ($line =~ /^max:\s+([\.\d]+)(\w+)/) { 241 $keys[1] = $1; 242 $labels[1] = 'pr_max'; 243 $keys[2] = $2; 244 $labels[2] = 'pr_max_units'; 245 $size = 2; 246 } 247 248 elsif ($line =~ /^approx. .*?tile:\s+([\.\d]+)(\w+)/) { 249 $keys[1] = $1; 250 $labels[1] = 'pr_95'; 251 $keys[2] = $2; 252 $labels[2] = 'pr_95_units'; 253 $size = 2; 254 } 255 256 # These are done together as there are 2 pieces of information on each line 257 elsif ($line =~ /^events .*?:(.+)\/(.+)/) { 258 $keys[1] = $1; 259 $labels[1] = 'event_avg'; 260 $keys[2] = $2; 261 $labels[2] = 'event_stddev'; 262 $size = 2; 263 } 264 265 # These are done together as there are 2 pieces of information on each line 266 elsif ($line =~ /^execution .*?:(.+)\/(.+)/) { 267 $keys[1] = $1; 268 $labels[1] = 'exec_avg'; 269 $keys[2] = $2; 270 $labels[2] = 'exec_stddev'; 271 $size = 2; 272 } 273 274 # These are done together as there are 4 pieces of information on each line 275 elsif ($line =~ /^Operations performed: (.+) Read, (.+) Write, (.+) Other = (.+) Total/) { 276 $keys[1] = $1; 277 $labels[1] = 'ops_reads'; 278 $keys[2] = $2; 279 $labels[2] = 'ops_write'; 280 $keys[3] = $3; 281 $labels[3] = 'ops_other'; 282 $keys[4] = $4; 283 $labels[4] = 'ops_total'; 284 $size = 4; 285 } 286 287 # These are done together as there are 4 pieces of information on each line 288 elsif ($line =~ /^Read ([\.\d]+)(\w+)\s+Written\s+([\.\d]+)(\w+).*\s+transferred\s+([\.\d]+)(\w+)\s+\(([\.\d]+)(\w+)/) { 289 $keys[1] = $1; 290 $labels[1] = 'op_read'; 291 $keys[2] = $2; 292 $labels[2] = 'op_read_units'; 293 $keys[3] = $3; 294 $labels[3] = 'op_written'; 295 $keys[4] = $4; 296 $labels[4] = 'op_written_units'; 297 $keys[5] = $5; 298 $labels[5] = 'op_trans_total'; 299 $keys[6] = $6; 300 $labels[6] = 'op_trans_total_units'; 301 $keys[7] = $7; 302 $labels[7] = 'op_trans_rate'; 303 $keys[8] = $8; 304 $labels[8] = 'op_trans_rate_units'; 305 $size = 8; 306 } 307 308 my $do_units = 0; 309 310 for (my $tekey = 0; $tekey <= $size; $tekey++) 311 { 312 if( $tekey+1 <= $size ) { 313 my $check_me = $labels[$tekey+1]; 314 my $orig = $labels[$tekey]; 315 my $units = $orig; 316 $units .= "_units"; 317 if( $check_me eq $units ) { 318 $do_units = 1; 319 } 320 } 321 if ( defined($labels[$tekey]) ) { 322 $keys[$tekey] =~ s/(^\s+|\s+$)//g; 323 my $col = 0; 324 if ($do_units == 1) { 325 $keys[$tekey+1] =~ s/(^\s+|\s+$)//g; 326 $col = $self->add_column( $labels[$tekey], $keys[$tekey+1] ); 327 $self->add_data( $keys[$tekey], $col ); 328 329 $tekey++; 330 } 331 else { 332 $col = $self->add_column( $labels[$tekey] ); 333 $self->add_data( $keys[$tekey], $col ); 334 } 335 $do_units=0; 336 } 337 } 338 return 1; 339} 340 341 3421; 343__END__ 344 345=head1 AUTHOR 346 347John Daiker <daikerjohn@gmail.com> 348 349=head1 COPYRIGHT 350 351Copyright (C) 2006 John Daiker & Open Source Development Labs, Inc. 352All Rights Reserved. 353 354This script is free software; you can redistribute it and/or modify it 355under the same terms as Perl itself. 356 357=head1 SEE ALSO 358 359L<Test::Parser> 360 361=end 362