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.
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
;
29 use base
'Torrus::ReportGenerator';
36 use Torrus
::ServiceID
;
56 my $percentile = $self->{'options'}->{'Percentile'};
57 if( not defined( $percentile ) )
62 my $step = $self->{'options'}->{'Step'};
63 if( not defined( $step ) )
68 my $srvIDParams = Torrus
::ServiceID
->new();
70 my $srvIDs = $self->{'srvexport'}->getServiceIDs();
71 for my $serviceid ( @
{$srvIDs} )
73 &Torrus
::DB
::checkInterrupted
();
75 my $data = $self->{'srvexport'}->getIntervalData
76 ( $self->{'StartDate'}, $self->{'EndDate'}, $serviceid );
78 &Torrus
::DB
::checkInterrupted
();
80 next if scalar( @
{$data} ) == 0;
81 Debug
('MonthlySrvUsage: Generating report for ' . $serviceid);
83 my $params = $srvIDParams->getParams( $serviceid );
86 $#aligned = floor
( $self->{'RangeSeconds'} / $step );
87 my $nDatapoints = scalar( @aligned );
89 # Fill in the aligned array. For each interval by modulo(step),
90 # we take the maximum value from the available data
94 for my $row ( @
{$data} )
96 my $rowtime = str2time
( $row->{'srv_date'} . 'T' .
98 my $pos = floor
( ($rowtime - $self->{'StartUnixTime'}) / $step );
99 my $value = Math
::BigFloat
->new( $row->{'value'} );
100 if( $value->is_nan() )
106 if( ( not defined( $aligned[$pos] ) ) or
107 $aligned[$pos] < $value )
109 $aligned[$pos] = $value;
110 if( $value > $maxVal )
117 &Torrus
::DB
::checkInterrupted
();
119 # Set undefined values to zero and calculate the average
121 my $sum = Math
::BigFloat
->new(0);
122 my $unavailCount = 0;
123 for my $pos ( 0 .. $#aligned )
125 if( not defined( $aligned[$pos] ) )
132 $sum += $aligned[$pos];
136 &Torrus
::DB
::checkInterrupted
();
138 my $avgVal = $sum / $nDatapoints;
140 # Calculate the percentile
142 my @sorted = sort {$a <=> $b} @aligned;
143 my $pcPos = floor
( $nDatapoints * $percentile / 100 );
144 my $pcVal = $sorted[$pcPos];
146 # Calculate the total volume if it's a counter
147 my $volume = Math
::BigFloat
->new(0);
148 my $volumeDefined = 0;
149 if( not defined( $params->{'dstype'} ) or
150 $params->{'dstype'} =~ /^COUNTER/o )
153 for my $row ( @
{$data} )
155 $volume += $row->{'value'} * $row->{'intvl'};
159 # Adjust units and scale
162 my $volumeUnits = '';
163 if( not defined( $params->{'units'} ) or
164 $params->{'units'} eq 'bytes' )
166 # Adjust bytes into megabit per second
167 $usageUnits = 'Mbps';
172 # Adjust volume bytes into megabytes
174 $volume /= 1073741824;
177 $self->{'backend'}->addField( $self->{'reportId'}, {
179 'serviceid' => $serviceid,
181 'units' => $usageUnits });
183 $self->{'backend'}->addField( $self->{'reportId'}, {
185 'serviceid' => $serviceid,
187 'units' => $usageUnits });
189 $self->{'backend'}->addField( $self->{'reportId'}, {
190 'name' => sprintf('%s%s', $percentile, 'TH_PERCENTILE'),
191 'serviceid' => $serviceid,
193 'units' => $usageUnits });
195 $self->{'backend'}->addField( $self->{'reportId'}, {
197 'serviceid' => $serviceid,
198 'value' => ($unavailCount*100)/$nDatapoints,
203 $self->{'backend'}->addField( $self->{'reportId'}, {
205 'serviceid' => $serviceid,
207 'units' => $volumeUnits });
211 &Torrus
::DB
::checkInterrupted
();
213 $self->{'backend'}->finalize( $self->{'reportId'} );
223 # indent-tabs-mode: nil
224 # perl-indent-level: 4