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 # Stanislav Sinyagin <ssinyagin@yahoo.com>
19 # For all service IDs available, build monthly usage figures:
20 # Average, Maximum, and Percentile (default 95th percentile)
23 package Torrus
::ReportGenerator
::MonthlySrvUsage
;
28 use base
'Torrus::ReportGenerator';
35 use Torrus
::ServiceID
;
55 my $percentile = $self->{'options'}->{'Percentile'};
56 if( not defined( $percentile ) )
61 my $step = $self->{'options'}->{'Step'};
62 if( not defined( $step ) )
67 my $srvIDParams = Torrus
::ServiceID
->new();
69 my $srvIDs = $self->{'srvexport'}->getServiceIDs();
70 for my $serviceid ( @
{$srvIDs} )
72 &Torrus
::DB
::checkInterrupted
();
74 my $data = $self->{'srvexport'}->getIntervalData
75 ( $self->{'StartDate'}, $self->{'EndDate'}, $serviceid );
77 &Torrus
::DB
::checkInterrupted
();
79 next if scalar( @
{$data} ) == 0;
80 Debug
('MonthlySrvUsage: Generating report for ' . $serviceid);
82 my $params = $srvIDParams->getParams( $serviceid );
85 $#aligned = floor
( $self->{'RangeSeconds'} / $step );
86 my $nDatapoints = scalar( @aligned );
88 # Fill in the aligned array. For each interval by modulo(step),
89 # we take the maximum value from the available data
93 for my $row ( @
{$data} )
95 my $rowtime = str2time
( $row->{'srv_date'} . 'T' .
97 my $pos = floor
( ($rowtime - $self->{'StartUnixTime'}) / $step );
98 my $value = Math
::BigFloat
->new( $row->{'value'} );
99 if( $value->is_nan() )
105 if( ( not defined( $aligned[$pos] ) ) or
106 $aligned[$pos] < $value )
108 $aligned[$pos] = $value;
109 if( $value > $maxVal )
116 &Torrus
::DB
::checkInterrupted
();
118 # Set undefined values to zero and calculate the average
120 my $sum = Math
::BigFloat
->new(0);
121 my $unavailCount = 0;
122 for my $pos ( 0 .. $#aligned )
124 if( not defined( $aligned[$pos] ) )
131 $sum += $aligned[$pos];
135 &Torrus
::DB
::checkInterrupted
();
137 my $avgVal = $sum / $nDatapoints;
139 # Calculate the percentile
141 my @sorted = sort {$a <=> $b} @aligned;
142 my $pcPos = floor
( $nDatapoints * $percentile / 100 );
143 my $pcVal = $sorted[$pcPos];
145 # Calculate the total volume if it's a counter
146 my $volume = Math
::BigFloat
->new(0);
147 my $volumeDefined = 0;
148 if( not defined( $params->{'dstype'} ) or
149 $params->{'dstype'} =~ /^COUNTER/o )
152 for my $row ( @
{$data} )
154 $volume += $row->{'value'} * $row->{'intvl'};
158 # Adjust units and scale
161 my $volumeUnits = '';
162 if( not defined( $params->{'units'} ) or
163 $params->{'units'} eq 'bytes' )
165 # Adjust bytes into megabit per second
166 $usageUnits = 'Mbps';
171 # Adjust volume bytes into megabytes
173 $volume /= 1073741824;
176 $self->{'backend'}->addField( $self->{'reportId'}, {
178 'serviceid' => $serviceid,
180 'units' => $usageUnits });
182 $self->{'backend'}->addField( $self->{'reportId'}, {
184 'serviceid' => $serviceid,
186 'units' => $usageUnits });
188 $self->{'backend'}->addField( $self->{'reportId'}, {
189 'name' => sprintf('%s%s', $percentile, 'TH_PERCENTILE'),
190 'serviceid' => $serviceid,
192 'units' => $usageUnits });
194 $self->{'backend'}->addField( $self->{'reportId'}, {
196 'serviceid' => $serviceid,
197 'value' => ($unavailCount*100)/$nDatapoints,
202 $self->{'backend'}->addField( $self->{'reportId'}, {
204 'serviceid' => $serviceid,
206 'units' => $volumeUnits });
210 &Torrus
::DB
::checkInterrupted
();
212 $self->{'backend'}->finalize( $self->{'reportId'} );
223 # indent-tabs-mode: nil
224 # perl-indent-level: 4