2 # Copyright (C) 2003 Stanislav Sinyagin
3 # Copyright (C) 2003 Christian Schnidrig
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19 # $Id: schedulerinfo.in,v 1.1 2010-12-27 00:04:00 ivan Exp $
20 # Stanislav Sinyagin <ssinyagin@yahoo.com>
22 BEGIN { require '@torrus_config_pl@'; }
27 use Torrus::ConfigTree;
28 use Torrus::SiteConfig;
29 use Torrus::SchedulerInfo;
32 exit(1) if not Torrus::SiteConfig::verify();
42 my $ok = GetOptions('tree=s' => \$tree,
43 'config' => \$report_config,
44 'runtime' => \$report_runtime,
45 'clear' => \$clear_treestats,
46 'help' => \$help_needed);
50 not ( $report_config or $report_runtime or $clear_treestats ) or
51 $help_needed or scalar(@ARGV) > 0 )
53 print STDERR "Usage: $0 --tree=NAME [options...]\n",
55 " --tree=NAME tree name\n",
56 " --config report scheduler configuration\n",
57 " --runtime report scheduler runtime statistics\n",
58 " --clear clear scheduler statistics for specific tree\n",
59 " --help this help message\n";
64 if( not Torrus::SiteConfig::treeExists( $tree ) )
66 Error('Tree ' . $tree . ' does not exist');
71 &Torrus::DB::setSafeSignalHandlers();
73 if( $clear_treestats )
75 my $stats = new Torrus::SchedulerInfo( -Tree => $tree, -WriteAccess => 1 );
77 print STDERR "Statistics cleared for tree $tree\n";
82 printf("Torrus version %s\n", '@VERSION@');
83 printf("Datasources tree: %s\n", $tree);
84 printf("Date: %s\n\n", scalar( localtime( time() ) ) );
88 my $config_tree = new Torrus::ConfigTree( -TreeName => $tree );
89 if( not defined($config_tree) )
91 Error("Configuration is not ready");
95 my $stats = { 'collectorLeaves' => {}, 'monitorLeaves' => 0 };
97 collectStats( $config_tree, $stats );
100 printf("Scheduler configuration report\n\n");
102 foreach my $instance ( sort {$a<=>$b} keys %{$stats->{'collectorLeaves'}} )
104 printf("Collector leaves for instance #%d: %d\n",
106 $stats->{'collectorLeaves'}{$instance});
109 printf("Total monitor leaves: %d\n\n", $stats->{'monitorLeaves'});
111 printf("Scheduled leaves by type:\n");
113 foreach my $type ( sort keys %{$stats->{'leavesPerType'}} )
115 printf(" %10s %-10d\n", $type,
116 $stats->{'leavesPerType'}{$type});
120 foreach my $instance ( sort {$a<=>$b} keys %{$stats->{'collectorLeaves'}} )
122 if( $stats->{'collectorLeaves'}{$instance} > 0 )
124 &Torrus::DB::checkInterrupted();
126 printf("Collector execution timeline for instance #%d:\n",
128 reportTimeline( $stats->{'collectorSchedule'}{$instance} );
132 if( $stats->{'monitorLeaves'} > 0 )
134 printf("Monitor execution timeline:\n");
135 reportTimeline( $stats->{'monitorSchedule'} );
139 if( $report_runtime )
143 { 'label' => 'Running Time',
144 'varname' => 'RunningTime' },
146 { 'label' => 'Late Start',
147 'varname' => 'LateStart' },
149 { 'label' => 'Too Long',
150 'varname' => 'TooLong' },
152 { 'label' => 'RRD Queue',
153 'varname' => 'RRDQueue' },
155 { 'label' => 'Raw Queue',
156 'varname' => 'RawQueue' }
162 { 'label' => 'running cycles passed',
163 'varname' => 'NTimesRunningTime' },
165 { 'label' => 'late starts',
166 'varname' => 'NTimesLateStart' },
168 { 'label' => 'too long runs',
169 'varname' => 'NTimesTooLong' },
171 { 'label' => 'overrun periods',
172 'varname' => 'CountOverrunPeriods' },
174 { 'label' => 'missed periods',
175 'varname' => 'CountMissedPeriods' }
178 my $sInfo = new Torrus::SchedulerInfo( '-Tree' => $tree );
179 exit(1) if not defined( $sInfo );
181 my $stats = $sInfo->readStats();
184 printf("Scheduler runtime report\n\n");
186 my $periodicTasks = {};
187 foreach my $taskId ( keys %{$stats} )
189 my ($type, $taskName, $instance, $period, $offset) =
190 split( ':', $taskId );
193 $periodicTasks->{$taskName}{$instance}{$period}{$offset} = $taskId;
197 foreach my $taskName ( sort keys %{$periodicTasks} )
199 foreach my $instance ( sort {$a<=>$b}
200 keys %{$periodicTasks->{$taskName}} )
204 keys %{$periodicTasks->{$taskName}{$instance}} )
208 keys %{$periodicTasks->{$taskName}{$instance}{$period}} )
210 &Torrus::DB::checkInterrupted();
213 $periodicTasks->{$taskName}{$instance}{
215 my $ref = $stats->{$taskId};
217 printf("Task: %s, Instance: %d, " .
218 "Period: %d seconds, Offset: %d seconds\n",
219 $taskName, $instance, $period, $offset);
221 foreach my $format ( @counterFormats )
223 if( defined( $ref->{$format->{'varname'}} ) )
226 $ref->{$format->{'varname'}},
227 $format->{'label'} );
232 printf("%-15s%-10s%-10s%-10s%-10s\n",
233 '', 'Min', 'Max', 'Average', 'Exp Average');
235 foreach my $format ( @reportFormats )
237 my $varname = $format->{'varname'};
238 if( defined( $ref->{'Min' . $varname} ) )
240 printf("%-15s%-10d%-10d%-10.1f%-10.1f\n",
242 $ref->{'Min' . $varname},
243 $ref->{'Max' . $varname},
244 $ref->{'Avg' . $varname},
245 $ref->{'ExpAvg' . $varname});
263 my $config_tree = shift;
267 if( not defined( $token ) )
269 $token = $config_tree->token('/');
272 my @children = $config_tree->getChildren( $token );
274 foreach my $ctoken ( @children )
276 &Torrus::DB::checkInterrupted();
278 if( $config_tree->isSubtree( $ctoken ) )
280 collectStats( $config_tree, $stats, $ctoken );
282 elsif( $config_tree->isLeaf( $ctoken ) )
284 if( $config_tree->getNodeParam( $ctoken, 'ds-type' )
288 $config_tree->getNodeParam
289 ( $ctoken, 'collector-instance' );
291 $stats->{'collectorLeaves'}{$instance}++;
294 $config_tree->getNodeParam( $ctoken, 'collector-type' );
297 $config_tree->getNodeParam( $ctoken, 'collector-period' );
298 $period = int( $period ); # make sure we're talking integers
300 my $offset = $config_tree->
301 getNodeParam( $ctoken, 'collector-timeoffset' );
303 $stats->{'leavesPerType'}{$type}++;
304 $stats->{'collectorSchedule'}{$instance}{$period}{
308 if( defined( $config_tree->getNodeParam( $ctoken, 'monitor' ) ) )
310 $stats->{'monitorLeaves'}++;
311 my $type = 'monitor';
314 $config_tree->getNodeParam( $ctoken, 'monitor-period' );
315 $period = int( $period ); # make sure we're talking integers
317 my $offset = $config_tree->
318 getNodeParam( $ctoken, 'monitor-timeoffset' );
319 $offset = int($offset) % $period;
321 $stats->{'leavesPerType'}{$type}++;
322 $stats->{'monitorSchedule'}{$period}{$offset}{$type}++;
329 # caluclate and print the schedule
332 my $schedule = shift;
334 # calculate the common period length (least common multiple)
336 foreach my $period ( keys %{$schedule} )
359 $lcm = $lcm * $period / $a;
363 printf("Least common period: %d seconds\n", $lcm);
365 # populate the common period
368 foreach my $period ( keys %{$schedule} )
370 foreach my $offset ( keys %{$schedule->{$period}} )
373 foreach my $type ( keys %{$schedule->{$period}{$offset}} )
375 for( my $i = 0; $i < ($lcm / $period); $i++ )
377 $cp{$i * $period + $offset}{'col'}{$type} +=
378 $schedule->{$period}{$offset}{$type};
383 printf("Number of chunks: %d \n\n", $chunks );
385 # calculate interval lengths
389 foreach my $time ( sort { $a <=> $b } keys %cp )
391 if( not defined($first) )
397 $cp{$previous}{'endtime'} = $time;
401 $cp{$previous}{'endtime'} = $lcm + $first;
406 printf("%-10s%-10s%-20s%-10s\n",
407 'Offset', 'Interval', 'Type', 'Data');
408 printf("%-10s%-10s%-20s%-10s\n",
409 '(sec)', '(sec)', '', 'sources');
412 foreach my $time ( sort { $a <=> $b } keys %cp )
414 foreach my $type ( keys %{$cp{$time}{'col'}} )
416 printf("%-10d%-10d%-20s%-10d\n",
418 $cp{$time}{'endtime'} - $time,
420 $cp{$time}{'col'}{$type} );
430 foreach my $i ( 1..75 )
439 foreach my $i ( 1..70 )
452 # indent-tabs-mode: nil
453 # perl-indent-level: 4