1 # Copyright (C) 2005 Stanislav Sinyagin
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17 # $Id: MonthlySrvUsage.pm,v 1.1 2010-12-27 00:03:58 ivan Exp $
18 # Stanislav Sinyagin <ssinyagin@yahoo.com>
20 # For all service IDs available, build monthly usage figures:
21 # Average, Maximum, and Percentile (default 95th percentile)
24 package Torrus::ReportGenerator::MonthlySrvUsage;
32 use Torrus::ReportGenerator;
33 use Torrus::ServiceID;
35 use base 'Torrus::ReportGenerator';
52 my $percentile = $self->{'options'}->{'Percentile'};
53 if( not defined( $percentile ) )
58 my $step = $self->{'options'}->{'Step'};
59 if( not defined( $step ) )
64 my $srvIDParams = new Torrus::ServiceID();
66 my $srvIDs = $self->{'srvexport'}->getServiceIDs();
67 foreach my $serviceid ( @{$srvIDs} )
69 &Torrus::DB::checkInterrupted();
71 my $data = $self->{'srvexport'}->getIntervalData
72 ( $self->{'StartDate'}, $self->{'EndDate'}, $serviceid );
74 &Torrus::DB::checkInterrupted();
76 next if scalar( @{$data} ) == 0;
77 Debug('MonthlySrvUsage: Generating report for ' . $serviceid);
79 my $params = $srvIDParams->getParams( $serviceid );
82 $#aligned = floor( $self->{'RangeSeconds'} / $step );
83 my $nDatapoints = scalar( @aligned );
85 # Fill in the aligned array. For each interval by modulo(step),
86 # we take the maximum value from the available data
90 foreach my $row ( @{$data} )
92 my $rowtime = str2time( $row->{'srv_date'} . 'T' .
94 my $pos = floor( ($rowtime - $self->{'StartUnixTime'}) / $step );
95 my $value = Math::BigFloat->new( $row->{'value'} );
96 if( $value->is_nan() )
102 if( ( not defined( $aligned[$pos] ) ) or
103 $aligned[$pos] < $value )
105 $aligned[$pos] = $value;
106 if( $value > $maxVal )
113 &Torrus::DB::checkInterrupted();
115 # Set undefined values to zero and calculate the average
117 my $sum = Math::BigFloat->new(0);
118 my $unavailCount = 0;
119 foreach my $pos ( 0 .. $#aligned )
121 if( not defined( $aligned[$pos] ) )
128 $sum += $aligned[$pos];
132 &Torrus::DB::checkInterrupted();
134 my $avgVal = $sum / $nDatapoints;
136 # Calculate the percentile
138 my @sorted = sort {$a <=> $b} @aligned;
139 my $pcPos = floor( $nDatapoints * $percentile / 100 );
140 my $pcVal = $sorted[$pcPos];
142 # Calculate the total volume if it's a counter
143 my $volume = Math::BigFloat->new(0);
144 my $volumeDefined = 0;
145 if( not defined( $params->{'dstype'} ) or
146 $params->{'dstype'} =~ /^COUNTER/o )
149 foreach my $row ( @{$data} )
151 $volume += $row->{'value'} * $row->{'intvl'};
155 # Adjust units and scale
158 my $volumeUnits = '';
159 if( not defined( $params->{'units'} ) or
160 $params->{'units'} eq 'bytes' )
162 # Adjust bytes into megabit per second
163 $usageUnits = 'Mbps';
168 # Adjust volume bytes into megabytes
170 $volume /= 1073741824;
173 $self->{'backend'}->addField( $self->{'reportId'}, {
175 'serviceid' => $serviceid,
177 'units' => $usageUnits });
179 $self->{'backend'}->addField( $self->{'reportId'}, {
181 'serviceid' => $serviceid,
183 'units' => $usageUnits });
185 $self->{'backend'}->addField( $self->{'reportId'}, {
186 'name' => sprintf('%s%s', $percentile, 'TH_PERCENTILE'),
187 'serviceid' => $serviceid,
189 'units' => $usageUnits });
191 $self->{'backend'}->addField( $self->{'reportId'}, {
193 'serviceid' => $serviceid,
194 'value' => ($unavailCount*100)/$nDatapoints,
199 $self->{'backend'}->addField( $self->{'reportId'}, {
201 'serviceid' => $serviceid,
203 'units' => $volumeUnits });
207 &Torrus::DB::checkInterrupted();
209 $self->{'backend'}->finalize( $self->{'reportId'} );
219 # indent-tabs-mode: nil
220 # perl-indent-level: 4