| MRTG-Parse documentation | Contained in the MRTG-Parse distribution. |
MRTG::Parse - Perl extension for parsing and utilizing the logfiles generated by the famous MRTG Tool.
use strict; use MRTG::Parse; my $mrtg_logfile = "/var/www/htdocs/mrtg/eth0.log"; my $period = "day"; my $desired_unit = "GB"; my ($traffic_incoming, $traffic_outgoing, $traffic_sum) = mrtg_parse($mrtg_logfile, $period, $desired_unit); print "Incoming Traffic: $traffic_incoming\n"; print "Outgoing Traffic: $traffic_outgoing\n"; print "= Sum $traffic_sum\n";
This perl extension enables its users to parse and utilize the logfiles that are generated by the famous MRTG (Multi Router Traffic Grapher) tool.
mrtg_parse() takes three argument:
1st: filename of the mrtg logfile 2nd: time period to genereate the output for valid values are: - individual time periods like: 20040821-20050130 (ISO 8601) - static values: day, month, year 3rd: the desired unit (optional) valid values are: - B, KB, MB, GB, TB - if missing mrtg_parse will chose an adequate one for you
mrtg_parse() returns three values:
1st: Incoming traffic 2nd: Outgoing traffic 3rd: Sum of incoming and outgoing
mrtg_parse()
http://people.ee.ethz.ch/~oetiker/webtools/mrtg/ - MRTG Homepage
http://people.ee.ethz.ch/~oetiker/webtools/mrtg/mrtg-logfile.html - Description of the MRTG Logfile Format
Please report any bugs or feature requests directly to mariof@cpan.org. Thanks!
Mario Fuerderer, <mariof@cpan.org>
Copyright (C) 2005 by Mario Fuerderer
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
| MRTG-Parse documentation | Contained in the MRTG-Parse distribution. |
############################################################################# # MRTG::Parse - v0.03 # # # # This module parses and utilizes the logfiles produced by MRTG # # A full documentation is attached to this sourcecode in POD format. # # # # Copyright (C) 2005 Mario Fuerderer <mario@codehack.org> # # # # This library is free software; you can redistribute it and/or # # modify it under the terms of the GNU Lesser General Public # # License as published by the Free Software Foundation; either # # version 2.1 of the License, or (at your option) any later version. # # # # This library is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # # Lesser General Public License for more details. # # # # You should have received a copy of the GNU Lesser General Public # # License along with this library; if not, write to the Free Software # # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # # Mario Fuerderer <mariof@cpan.org) # # # ############################################################################# package MRTG::Parse; use 5.006; use strict; use warnings; use Time::Local; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(mrtg_parse); our $VERSION = '0.03'; ########################################### # This subroutine receives the needed # # arguments and passes them to the main # # parser() subroutine. # ########################################### sub mrtg_parse { my $logfile = $_[0]; my $period = $_[1]; my $unit = $_[2]; # Start the parser and save total incoming and outgoing bytes to @array_traffic_total my @array_traffic_total = &parser($logfile, $period); # Convert the bytes into the right unit (you may call it "prefix multiplier"). my @array_traffic_total_unit_in = &traffic_output($array_traffic_total[0], $unit); my @array_traffic_total_unit_out = &traffic_output($array_traffic_total[1], $unit); my @array_traffic_total_unit_sum = &traffic_output($array_traffic_total[0] + $array_traffic_total[1], $unit); my @return; push(@return, join(' ', @array_traffic_total_unit_in)); push(@return, join(' ', @array_traffic_total_unit_out)); push(@return, join(' ', @array_traffic_total_unit_sum)); return @return; } ########################################### # Our main subroutine, which parses the # # logfile with the values passed through # # mrtg_parse(). # ########################################### sub parser { my $logfile = $_[0]; my $period = $_[1]; my $parse_type; my $start_date; my $end_date; my $start_epoch; my $end_epoch; my $weekday; my $month; my $day; my $time; my $year; # Decide whether we should parse for static time period... if ($period eq "day" || $period eq "month" || $period eq "year") { ($weekday, $month, $day, $time, $year) = split(/ +/, localtime(time())); $parse_type = "static"; # ...or an individual one. } elsif ($period =~ /\d{8}-\d{8}/) { ($start_date, $end_date) = split(/-/, $period); unless ($start_date - $end_date =~ /-/) { die("Error: time periods are not in the right order!\n"); } # Calculate start and end date to seconds since the system epoch $start_date =~ /(\d{4})(\d{2})(\d{2})/; my $start_year = $1; my $start_month = $2; my $start_day = $3; $start_epoch = timelocal("00", "00", "00", $start_day, $start_month-1, $start_year); $end_date =~ /(\d{4})(\d{2})(\d{2})/; my $end_year = $1; my $end_month = $2; my $end_day = $3; $end_epoch = timelocal("00", "00", "00", $end_day, $end_month-1, $end_year); $parse_type = "individual"; } else { die("Error: time period is not present or in an unkown format!\n"); } open(LOG, "$logfile") or die "Error: Could not open MRTG-Logfile ($logfile)"; # Set any counter to zero before we start parsing. my $traffic_total_in = 0; my $traffic_total_out = 0; my $last_date = 0; my $counter = 0; while (my $line=<LOG>) { # We want to ignore the first line, because it's just the sum of the rest. unless ($counter == 0) { my $date; my @column = split(/\s+/, $line); # Build the match-pattern my $pattern; if ($parse_type eq "static") { $date = scalar localtime($column[0]); if ($period eq "day") { $pattern = ".+ $month.+$day .+$year"; } elsif($period eq "month") { $pattern = ".+$month.+$year"; } elsif($period eq "year") { $pattern = ".+$year"; } # Check if the current line matches out pattern. if ($date =~ /^$pattern$/) { my $traffic_in = $column[1]; my $traffic_out = $column[2]; my $time_range; unless ($last_date == 0) { # Calculate the time difference between the current and the previously processd line. $time_range = $last_date - $column[0]; } else { # Set time range to zero if it's the first line. $time_range = 0; } # Multiply the bytes with the time range. $traffic_total_in += $traffic_in * $time_range; $traffic_total_out += $traffic_out * $time_range; # Set the $last_date variable to the new value. $last_date = $column[0]; } } elsif ($parse_type eq "individual") { $date = $column[0]; if (($date > $start_epoch) && ($date < $end_epoch)) { my $traffic_in = $column[1]; my $traffic_out = $column[2]; my $time_range; unless ($last_date == 0) { $time_range = $last_date - $column[0]; } else { $time_range = 0; } $traffic_total_in += $traffic_in * $time_range; $traffic_total_out += $traffic_out * $time_range; $last_date = $column[0]; } } } $counter++; } my @array; push(@array, $traffic_total_in); push(@array, $traffic_total_out); return @array; close LOG; } ########################################### # This is just to get the right unit... # ########################################### sub traffic_output { my $bytes = $_[0]; my $desired_unit = $_[1]; my @array; my $unit; my $total_count; my @unit_array = qw(B KB MB GB TB); my $temp_unit = $bytes; my $counter = 0; my $check = "false"; # Run through the @unit_array foreach my $unit_entry (@unit_array) { # We don't need to divide for the first entry, because it's already in byte unless ($counter == 0) { $temp_unit = ($temp_unit / 1024); unless ($desired_unit) { # If our value is lower than 1, we should stop here in order to retain an adequate unit. if ($temp_unit < 1) { last; } } } $total_count = $temp_unit; $unit = $unit_entry; if ($desired_unit) { if ($desired_unit eq $unit_entry) { $check = "true"; last; } } $counter++; } push(@array, $total_count); push(@array, $unit); if ($desired_unit && $check eq "true") { return @array; } elsif (defined($desired_unit) && $check ne "true") { die("Erorr: $desired_unit is a non valid unit!\n"); } else { return @array; } } __END__