Changeset 3404
- Timestamp:
- 03/07/10 13:45:47 (5 months ago)
- Files:
-
- trunk (modified) (1 prop)
- trunk/Makefile (modified) (6 diffs)
- trunk/common (modified) (1 prop)
- trunk/common/lib/Munin/Common/Config.pm (modified) (1 diff)
- trunk/common/lib/Munin/Common/Defaults.pm (modified) (1 diff)
- trunk/master (modified) (1 prop)
- trunk/master/_bin/munin-cgi-graph.in (modified) (9 diffs)
- trunk/master/_bin/munin-fastcgi-graph.in (deleted)
- trunk/master/lib/Munin/Master/GraphOld.pm (modified) (26 diffs)
- trunk/master/lib/Munin/Master/HTMLOld.pm (modified) (4 diffs)
- trunk/master/lib/Munin/Master/Logger.pm (modified) (2 diffs)
- trunk/master/lib/Munin/Master/Node.pm (modified) (9 diffs)
- trunk/master/lib/Munin/Master/UpdateWorker.pm (modified) (7 diffs)
- trunk/master/lib/Munin/Master/Utils.pm (modified) (2 diffs)
- trunk/master/www/dynazoom.html (copied) (copied from people/snide/pre_1.5/master/www/dynazoom.html)
- trunk/master/www/formatdate.js (copied) (copied from people/snide/pre_1.5/master/www/formatdate.js)
- trunk/master/www/munin-serviceview.tmpl (modified) (1 diff)
- trunk/master/www/querystring.js (copied) (copied from people/snide/pre_1.5/master/www/querystring.js)
- trunk/node (modified) (1 prop)
- trunk/node/lib/Munin/Node/Server.pm (modified) (2 diffs)
- trunk/plugins (modified) (1 prop)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk
- Property svn:ignore changed from
*-stamp
build
*.class
to
*-stamp
build
*.class
debian
- Property svn:ignore changed from
trunk/Makefile
r3265 r3404 33 33 test clean \ 34 34 clean-% test-% build-% install-% \ 35 tags 35 tags \ 36 infiles 36 37 37 38 .SECONDARY: node/Build master/Build plugins/Build … … 87 88 $(CHMOD) 0755 $(DBDIR) 88 89 89 for p in master/www/*.tmpl master/www/*.png master/www/*.css resources/favicon.ico; do \90 for p in master/www/*.tmpl master/www/*.png master/www/*.css master/www/*.js resources/favicon.ico; do \ 90 91 $(INSTALL) -m 0644 "$$p" $(CONFDIR)/templates/ ; \ 91 92 done … … 96 97 97 98 $(INSTALL) -m 0644 master/www/definitions.html $(CONFDIR)/templates/ 99 $(INSTALL) -m 0644 master/www/dynazoom.html $(CONFDIR)/templates/ 98 100 $(INSTALL) -m 0755 master/DejaVuSansMono.ttf $(LIBDIR)/ 99 101 $(INSTALL) -m 0755 master/DejaVuSans.ttf $(LIBDIR)/ … … 108 110 $(INSTALL) -m 0755 build/master/_bin/munin-html $(LIBDIR)/ 109 111 $(INSTALL) -m 0755 build/master/_bin/munin-limits $(LIBDIR)/ 110 $(INSTALL) -m 0755 build/master/_bin/munin-cgi-graph $(CGIDIR)/ 111 $(INSTALL) -m 0755 build/master/_bin/munin-fastcgi-graph $(CGIDIR)/ 112 $(INSTALL) -m 0755 build/master/_bin/munin-cgi-graph $(CGIDIR)/munin-cgi-graph 112 113 113 114 # Not ready to be installed yet … … 180 181 ###################################################################### 181 182 183 # Dummy rule to enable parallel building 184 infiles: $(INFILES) 185 182 186 ifeq ($(JCVALID),yes) 183 build: $(INFILES)build-master build-common-prime build-node build-plugins build-plugins-java build-man187 build: infiles build-master build-common-prime build-node build-plugins build-plugins-java build-man 184 188 else 185 build: $(INFILES)build-master build-common-prime build-node build-plugins build-man189 build: infiles build-master build-common-prime build-node build-plugins build-man 186 190 endif 187 191 … … 226 230 build-common-pre: common/Build 227 231 cd common && $(PERL) Build code 232 233 common/blib/lib/Munin/Common/Defaults.pm: common/lib/Munin/Common/Defaults.pm build-common-pre 228 234 rm -f common/blib/lib/Munin/Common/Defaults.pm 229 230 common/blib/lib/Munin/Common/Defaults.pm: common/lib/Munin/Common/Defaults.pm build-common-pre231 235 $(PERL) -pe 's{(PREFIX \s+=\s).*}{\1q{$(PREFIX)};}x; \ 232 236 s{(CONFDIR \s+=\s).*}{\1q{$(CONFDIR)};}x; \ trunk/common
- Property svn:ignore set to
Build
_build
blib
- Property svn:ignore set to
trunk/common/lib/Munin/Common/Config.pm
r3378 r3404 38 38 "onlynullcdef", "group_order", "pipe", "pipe_command", 39 39 "unknown_limit", "num_unknowns", "dropdownlimit", 40 "max_graph_jobs", "munin_cgi_graph_jobs" ); 40 "max_graph_jobs", "munin_cgi_graph_jobs", 41 "cgitmpdir", 42 ); 41 43 42 44 my %bools = map { $_ => 1} qw(yes no true false on off 1 0); trunk/common/lib/Munin/Common/Defaults.pm
r2951 r3404 26 26 our $MUNIN_HTMLDIR = ''; 27 27 our $MUNIN_CGIDIR = ''; 28 our $MUNIN_CGITMPDIR = ''; 28 29 our $MUNIN_DBDIR = ''; 29 30 our $MUNIN_PLUGSTATE = ''; trunk/master
- Property svn:ignore set to
Build
_build
blib
- Property svn:ignore set to
trunk/master/_bin/munin-cgi-graph.in
r3304 r3404 1 #!@@PERL@@ -Tw1 #!@@PERL@@ -Tw 2 2 # -*- perl -*- 3 3 # 4 # Copyright (C) 2004 Jimmy Olsen4 # Copyright (C) 2004-2009 Jimmy Olsen, 5 5 # 6 6 # This program is free software; you can redistribute it and/or … … 20 20 # $Id$ 21 21 # 22 # Please see http://munin.projects.linpro.no/wiki/CgiHowto for how to 23 # use this, and how to convert it to fastcgi which will improve speed. 22 24 23 # 25 24 … … 32 31 use POSIX qw(strftime); 33 32 use IPC::SysV qw(IPC_CREAT); 33 use CGI::Fast; 34 use CGI::Carp 'fatalsToBrowser'; 34 35 35 36 my $GRAPHER = "$Munin::Common::Defaults::MUNIN_LIBDIR/munin-graph"; … … 58 59 my $dom = ""; 59 60 my $lock = ""; 60 my $IPC_KEY = 89340; 61 61 my $IPC_KEY = 9340; 62 63 # NOTE: You need to restart apache if the config file changes! 62 64 my $config = &munin_readconfig ($conffile); 63 65 64 my $path = $ENV{PATH_INFO} || ""; 65 $path =~ s/^\///; 66 ($dom, $host, $serv) = split /\//, $path; 67 ($serv, $scale) = split /-/, $serv, 2; 68 $scale =~ s/\.png$//; 69 70 &verify_parameters ($dom, $host, $serv, $scale); 71 72 my $filename = get_picture_filename ($config, $dom, $host, $serv, $scale); 73 74 my $time = time; 75 76 # Get semaphore handle - Before graphing as recommended by snide. 77 my $semid = undef; 78 79 sem_setup(); 80 81 my $no_cache = defined($ENV{HTTP_CACHE_CONTROL}) && $ENV{HTTP_CACHE_CONTROL} =~ /no-cache/i; 82 83 if ($no_cache or (! &graph_usable($filename,$time) )) { 84 exit 0 unless draw_graph_or_complain($host, $serv, $TIMES{$scale}); 85 goto draw; 86 } 87 88 # At this time the file exists. But may be old. Or not. 89 90 my @stats = stat ($filename); 91 my $last_modified = strftime ("%a, %d %b %Y %H:%M:%S %Z", localtime ($stats[9])); 92 # "Expires" has to use last modified time as base: 93 my $expires = strftime ("%a, %d %b %Y %H:%M:%S GMT", 94 gmtime($stats[9]+($period{$scale}-($stats[9]%$period{$scale})))); 95 96 # Check for If-Modified-Since and send 304 if not changed: 97 if (defined $ENV{HTTP_IF_MODIFIED_SINCE} and 98 !&modified ($ENV{HTTP_IF_MODIFIED_SINCE}, $stats[9]-1)) { 99 print "Status: 304\n"; 66 # BEGIN FAST-CGI LOOP: 67 while (new CGI::Fast) { 68 my $path = $ENV{PATH_INFO} || ""; 69 ($dom, $host, $serv, $scale) = $path =~ m#^/(.*)/([^/]+)/(\w+)-([\w=,]+)\.png#; ## avoid bug in vim 70 71 my $pinpoint; 72 if ($scale =~ /pinpoint=(\d+),(\d+)/) { 73 $pinpoint = [ $1, $2, ]; 74 } 75 76 if (! &verify_parameters ($dom, $host, $serv, $scale)) { 77 print "Status: 500\n"; 78 print "Content-Type: text/html\n"; 79 print "\n"; 80 print "Invalid parameters!"; 81 next; 82 } 83 84 my $filename = get_picture_filename ($config, $dom, $host, $serv, $scale); 85 86 my $time = time; 87 88 # If a "Cache-Control: no-cache" header gets send, we regenerate the image in every case: 89 my $no_cache = $pinpoint || defined($ENV{HTTP_CACHE_CONTROL}) && $ENV{HTTP_CACHE_CONTROL} =~ /no-cache/i; 90 print STDERR "no_cache:$no_cache\n"; 91 92 # Compute the cache values 93 my $graph_ttl = $pinpoint ? 1 : $period{$scale}; 94 my $graph_last_expires = $time - $time % $graph_ttl; 95 96 my $graph_epoch = (! $no_cache) && file_newer_than($filename, $graph_last_expires); 97 if ($graph_epoch) { 98 # The graph is fresh enough. Sending either IMS if asked, or just skip generation 99 # Check for If-Modified-Since and send 304 if not changed: 100 if (defined $ENV{HTTP_IF_MODIFIED_SINCE} && 101 ! rfctime_newer_than($ENV{HTTP_IF_MODIFIED_SINCE}, $graph_epoch)) { 102 print "Status: 304\n"; 103 print "Content-Type: image/png\n"; 104 print "\n"; 105 106 # We replied, continue with the next request 107 next; 108 } 109 } else { 110 # Should generate it 111 my $scale_options; 112 if ($pinpoint) { 113 $scale_options = [ "--pinpoint=" . $pinpoint->[0] . "," . $pinpoint->[1] ]; 114 } else { 115 $scale_options = $TIMES{$scale}; 116 } 117 next unless draw_graph_or_complain($dom, $host, $serv, $scale_options, $filename, "$config->{logdir}/munin-cgi-graph.log"); 118 } 119 120 # At this time the file exists and should be served 121 my @stats = stat ($filename); 122 my $mtime_epoch = $stats[9]; 123 my $last_modified = get_w3c_date_from_epoch($mtime_epoch); 124 125 # "Expires" has to use last modified time as base: 126 my $graph_next_expires = $mtime_epoch - ($mtime_epoch % $graph_ttl) + $graph_ttl; 127 my $expires = get_w3c_date_from_epoch($graph_next_expires); 128 129 130 # Sending headers 131 print "Status: 200\n"; 100 132 print "Content-Type: image/png\n"; 101 print "Expires: ", $expires, "\n"; 102 print "Last-Modified: $last_modified\n"; 133 print "Content-Length: $stats[7]\n"; 134 135 # Conditionaly add timing informations 136 print "Expires: $expires\n" if $expires; 137 print "Last-Modified: $last_modified\n" if $last_modified; 103 138 print "\n"; 104 exit 0; 105 } 106 107 draw: 108 109 @stats = stat ($filename) unless @stats; 110 111 $last_modified = strftime ("%a, %d %b %Y %H:%M:%S %Z", localtime ($stats[9])) 112 unless defined($last_modified); 113 114 $expires = strftime ("%a, %d %b %Y %H:%M:%S GMT", 115 gmtime($stats[9]+($period{$scale}-($stats[9]%$period{$scale})))) 116 unless defined($expires); 117 118 print "Content-Type: image/png\n"; 119 print "Expires: ", strftime ("%a, %d %b %Y %H:%M:%S GMT", gmtime(time+($period{$scale}-($time%$period{$scale})))), "\n"; 120 print "Last-Modified: $last_modified\n"; 121 print "\n"; 122 123 &graph ($filename); 124 125 # # # # # # # # # # END OF MAIN 126 127 sub sem_setup { 128 # Try to police the number of concurrent rrdgraph instances. 129 130 # Fox kindly submitted a patch to convert to SysV IPC semaphores. 131 # Lovely! (ticket #499). 132 133 $semid = semget($IPC_KEY, 0, 0 ); 134 135 if(!defined($semid)) { 136 # Or create it if needed 137 $semid = semget($IPC_KEY, 1 , oct(666) | IPC_CREAT ); 138 139 die "Creating semaphore: $!" unless defined($semid); 140 141 my $max_cgi_graph_jobs = &munin_get ($config, "max_cgi_graph_jobs" , 6, $dom); 142 143 # And initialize to max_cgi_graph_jobs 144 my $opstring = pack("s!s!s!",0, $max_cgi_graph_jobs,0); 145 semop($semid,$opstring) || die "$!"; 146 } 147 } 148 149 150 sub sem_get { 151 # Call this before doing heavy work. 152 # Decrement, or lock/hang/yield if already 0 153 my $opstring = pack("s!s!s!",0, -1, 0); 154 semop($semid,$opstring); 155 } 156 157 158 sub sem_release { 159 # Call this after doing heavy work. 160 # Increment (and release waiting processes). 161 my $opstring = pack("s!s!s!",0, 1, 0); 162 semop($semid,$opstring); 163 } 164 165 166 sub graph { 167 # This just serves the file, no file is made. 139 140 # Sending graph data 141 send_graph_data($filename); 142 } 143 # END FAST-CGI LOOP 144 145 sub get_w3c_date_from_epoch { 146 my $epoch = shift; 147 print STDERR "get_w3c_date_from_epoch($epoch)\n"; 148 return strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime($epoch)); 149 } 150 151 sub send_graph_data { 152 # Serve the graph contents. 168 153 my $filename = shift; 169 154 170 open (my $GRAPH, '<', $filename) 171 or die "Warning: Could not open picture file \"$filename\" for reading: $!\n"; 172 print while (<$GRAPH>); 173 close ($GRAPH); 155 open (GRAPH_PNG_FILE, '<', $filename) or die "Warning: Could not open picture file \"$filename\" for reading: $!\n"; 156 print while (<GRAPH_PNG_FILE>); 157 close (GRAPH_PNG_FILE) 174 158 } 175 159 … … 182 166 my $scale = shift; 183 167 184 return "$config->{'htmldir'}/$domain/$name/$service-$scale.png"; 185 } 186 187 188 sub logger_open { 189 my $dirname = shift; 190 191 if (!$log->opened) 192 { 193 unless (open ($log, '>>', "$dirname/munin-cgi-graph.log")) 194 { 195 print STDERR "Warning: Could not open log file \"$dirname/munin-cgi-graph.log\" for writing: $!"; 196 } 197 } 168 my $cgi_tmp_dir = $config->{cgitmpdir} || "/tmp/munin-cgi-tmp"; 169 170 return "$cgi_tmp_dir/$domain/$name/$service-$scale.png"; 198 171 } 199 172 … … 240 213 { 241 214 print STDERR "Warning: Request for graph without specifying domain. Bailing out.\n"; 242 exit 1;215 return 0; 243 216 } 244 217 if (!$host) 245 218 { 246 219 print STDERR "Warning: Request for graph without specifying host. Bailing out.\n"; 247 exit 1;220 return 0; 248 221 } 249 222 if (!$serv) 250 223 { 251 224 print STDERR "Warning: Request for graph without specifying service. Bailing out.\n"; 252 exit 1;225 return 0; 253 226 } 254 227 … … 256 229 { 257 230 print STDERR "Warning: Request for graph without specifying scale. Bailing out.\n"; 258 exit 1;231 return 0; 259 232 } 260 233 else 261 234 { 262 if (!defined $TIMES{$scale} )235 if (!defined $TIMES{$scale} && $scale !~ /pinpoint=\d+,\d+/) 263 236 { 264 237 print STDERR "Warning: Weird scale setting \"$scale\". Bailing out.\n"; 265 exit 1;238 return 0; 266 239 } 267 240 } 268 } 269 270 271 sub graph_usable { 272 # Check how old the graph is and return 1 if it's new enough and 0 otherwise. 273 my ($filename, $time) = @_; 241 return 1; 242 } 243 244 245 sub file_newer_than { 246 my $filename = shift; 247 my $time = shift; 274 248 275 249 if (-f $filename) { 276 250 my @stats = stat (_); 277 # $stats[9] holds the "last update" time and this needs to be in the last update period: 278 if ($stats[9] > ($time - $time%$period{$scale})) { 279 #print STDERR ("Graph unexpired for $scale. ($stats[9] , $time, ". ($time%$period{$scale}). ", ". ($time - $time%$period{$scale}). ").\n"); 280 return 1; 251 # $stats[9] holds the "last update" time and this needs 252 # to be in the last update period 253 my $last_update = $stats[9]; 254 if ($last_update > $time) { 255 return $last_update; 281 256 } else { 282 #print STDERR ("Graph expired for $scale. ($stats[9] , $time, ". ($time%$period{$scale}). ", ". ($time - $time%$period{$scale}). ").\n");283 257 return 0; 284 258 } 285 259 } 260 261 # No file found 286 262 return 0; 287 263 } … … 289 265 290 266 sub draw_graph { 267 # Draw a new graph - use semaphore to avoid too many concurrent munin-graph calls. 268 my $dom = shift; 291 269 my $host = shift; 292 270 my $serv = shift; 293 271 my $scale = shift; 294 272 295 $serv =~ s{[^\w_/"'\[\]\(\)\+=-]}{_}g; $serv =~ /^(.+)$/; $serv = $1; #" 273 my $filename = shift; 274 my $logfile = shift; 275 276 $serv =~ s{[^\w_\/"'\[\]\(\)+=-]}{_}g; $serv =~ /^(.+)$/; $serv = $1; #" 296 277 # . needs to be legal in host names 297 $host =~ s{[^\w_/"'\[\]\(\)\.+=-]}{_}g; $host =~ /^(.+)$/; $host = $1; #" 298 299 my @params = ($GRAPHER); 278 $host =~ s{[^\w_\/"'\[\]\(\)\.+=-]}{_}g; $host =~ /^(.+)$/; $host = $1; #" 279 280 my $fqn = "root/$dom/$host/$serv"; 281 282 my @params = (); 300 283 push @params, @$scale; 301 push @params, "--skip-locking", "--skip-stats", "--nolazy", "--list-images"; 302 push @params, "--host", $host, "--service", $serv; 303 push @params, "STDERR>&STDOUT"; 284 push @params, "--host", $host, "--only-fqn", $fqn; 285 push @params, "--no-fork"; # FastCgi forks for us 286 push @params, "--skip-locking", "--skip-stats", "--nolazy"; 287 push @params, "--output-file", $filename; 288 push @params, "--log-file", $logfile; 289 290 push @params, "--size_x", CGI::param("size_x") if (CGI::param("size_x")); 291 push @params, "--size_y", CGI::param("size_y") if (CGI::param("size_y")); 292 293 push @params, "--upper_limit", CGI::param("upper_limit") if (CGI::param("upper_limit")); 294 push @params, "--lower_limit", CGI::param("lower_limit") if (CGI::param("lower_limit")); 295 296 304 297 305 298 my $file = "/dev/null"; 306 my $IN; 307 sem_get(); 308 309 # Note: This open is an implicit fork 310 if (! open ($IN, "-|")) { 311 %ENV=(); 312 exec @params; 313 } 314 $file = join (' ', <$IN>); 315 chomp($file); 316 317 close ($IN); 318 sem_release(); 319 320 return $file; 299 300 # Use directly GraphOld; 301 use Munin::Master::GraphOld; 302 303 graph_startup(\@params); 304 graph_main(); 305 306 return $filename; 321 307 } 322 308 323 309 324 310 sub draw_graph_or_complain { 311 use Time::HiRes qw(gettimeofday tv_interval); 312 my $t0 = [ gettimeofday ]; 325 313 my $ret = draw_graph(@_); 314 my $graph_duration = tv_interval($t0); 326 315 327 316 if (! -f $ret) { 328 ::logger ("Warning: Could not draw graph \"$host-$serv-$scale.png\": $ret");317 ::logger("Warning: Could not draw graph \"$host-$serv-$scale.png\": $ret"); 329 318 print "Status: 500\n"; 330 319 print "Content-Type: image/png\n"; 331 320 print "\n"; 332 return 0;321 return 0; 333 322 } else { 323 print "X-Graph-Duration: $graph_duration\n"; 334 324 return $ret; 335 325 } … … 337 327 338 328 339 sub modified { 340 # See if file has been modified since "the last time". 341 329 sub rfctime_newer_than { 330 # See if the file has been modified since "the last time". 342 331 # Format of since_string If-Modified-Since: Wed, 23 Jun 2004 16:11:06 GMT 343 344 332 my $since_string = shift; 345 333 my $created = shift; trunk/master/lib/Munin/Master/GraphOld.pm
r3288 r3404 87 87 my $cron = 0; 88 88 my $list_images = 0; 89 my $output_file = undef; 90 my $log_file = undef; 89 91 my $skip_locking = 0; 90 92 my $skip_stats = 0; … … 100 102 "sumweek" => 1 101 103 ); 104 $draw{"pinpoint"} = 0; # XXX - Add a dummy pinpoint value 105 106 my ($size_x, $size_y); 107 my ($lower_limit, $upper_limit); 102 108 103 109 my %PALETTE; # Hash of available palettes … … 129 135 "week" => "-8d", 130 136 "month" => "-33d", 131 "year" => "-400d" 137 "year" => "-400d", 138 "pinpoint" => "dummy", 132 139 ); 133 140 … … 146 153 my @limit_hosts = (); 147 154 my @limit_services = (); 155 my $only_fqn; 148 156 149 157 my $watermark = "Munin " . $Munin::Common::Defaults::MUNIN_VERSION; … … 158 166 # stats file handle 159 167 my $STATS; 160 my $DEBUG; 168 my $DEBUG = 0; 169 my $pinpoint = undef; 170 171 my %init_draw = %draw; 172 my @init_limit_hosts = @limit_hosts; 173 my @init_limit_services = @limit_services; 161 174 162 175 sub graph_startup { … … 166 179 # Do once pr. run, pr possebly once pr. graph in the case of 167 180 # munin-cgi-graph 181 182 # Localise the stuff, overwise it will be stacked up with CGI 183 %draw = %init_draw; 184 @limit_hosts = @init_limit_hosts; 185 @limit_services = @init_limit_services; 168 186 169 187 # Get options … … 176 194 "host=s" => \@limit_hosts, 177 195 "service=s" => \@limit_services, 196 "only-fqn=s" => \$only_fqn, 178 197 "config=s" => \$conffile, 179 198 "stdout!" => \$stdout, … … 182 201 "month!" => \$draw{'month'}, 183 202 "year!" => \$draw{'year'}, 203 "pinpoint=s" => \$draw{'pinpoint'}, 184 204 "sumweek!" => \$draw{'sumweek'}, 185 205 "sumyear!" => \$draw{'sumyear'}, 206 "size_x=i" => \$size_x, 207 "size_y=i" => \$size_y, 208 "upper_limit=s" => \$upper_limit, 209 "lower_limit=s" => \$lower_limit, 186 210 "list-images!" => \$list_images, 211 "o|output-file=s" => \$output_file, 212 "l|log-file=s" => \$log_file, 187 213 "skip-locking!" => \$skip_locking, 188 214 "skip-stats!" => \$skip_stats, … … 207 233 $config = &munin_config($conffile); 208 234 209 logger_open($config->{'logdir'}); 235 # untaint the $log_file variable 236 $log_file = $1 if ($log_file && $log_file =~ m/(.*)/); 237 238 logger_open($config->{'logdir'}, $log_file); 210 239 logger_debug() if $DEBUG; 240 241 # XXX - Special hack^h^h^h^h treatment for --pinpoint 242 if ($draw{'pinpoint'} && $draw{'pinpoint'} =~ m/^(\d+),(\d+)$/ ) { 243 %draw = ( "pinpoint" => $draw{'pinpoint'} ); # "pinpoint" replaces all the other timing options 244 $pinpoint = { "start" => $1, "end" => $2, }; # preparsed values 245 } 211 246 212 247 my $palette = &munin_get($config, "palette", "default"); … … 282 317 my $scale = shift; 283 318 284 return (munin_get($service, "graph_title", $service) . " - by $scale"); 319 my $scale_text; 320 if ($pinpoint) { 321 my $start_text = localtime($pinpoint->{"start"}); 322 my $end_text = localtime($pinpoint->{"end"}); 323 $scale_text = "from $start_text to $end_text"; 324 } else { 325 $scale_text = "by " . $scale; 326 } 327 328 return (munin_get($service, "graph_title", $service) . " - $scale_text"); 285 329 } 286 330 … … 330 374 331 375 # Picture filename 332 push @$result, munin_get_picture_filename($service, $scale, $sum || undef);376 push @$result, get_picture_filename($service, $scale, $sum || undef); 333 377 334 378 # Title … … 336 380 337 381 # When to start the graph 338 push @$result, "--start", $times{$scale}; 382 if ($pinpoint) { 383 push @$result, "--start", $pinpoint->{start}; 384 push @$result, "--end", $pinpoint->{end}; 385 } else { 386 push @$result, "--start", $times{$scale}; 387 } 339 388 340 389 # Custom graph args, vlabel and graph title … … 346 395 } 347 396 348 push @$result, "--height", munin_get($service, "graph_height", "175"); 349 push @$result, "--width", munin_get($service, "graph_width", "400"); 397 push @$result, "--height", ($size_y || munin_get($service, "graph_height", "175")); 398 push @$result, "--width", ($size_x || munin_get($service, "graph_width", "400")); 399 400 push @$result,"--rigid" if (defined $lower_limit || defined $upper_limit); 401 350 402 push @$result, "--imgformat", "PNG"; 351 403 push @$result, "--lazy" if ($force_lazy); … … 1088 1140 } 1089 1141 1142 my $nb_graphs_drawn = 0; 1090 1143 for my $time (keys %times) { 1091 1144 next unless ($draw{$time}); 1092 my $picfilename = munin_get_picture_filename($service, $time);1145 my $picfilename = get_picture_filename($service, $time); 1093 1146 (my $picdirname = $picfilename) =~ s/\/[^\/]+$//; 1094 1147 … … 1119 1172 . "\\r"); 1120 1173 1121 if (time - 300 < $lastupdate ) {1174 if (time - 300 < $lastupdate && ! $pinpoint) { 1122 1175 if (@added) { # stop one period earlier if it's a .sum or .stack 1123 1176 push @complete, "--end", … … 1146 1199 } 1147 1200 1201 # Surcharging the graphing limits 1202 my ($upper_limit_overrided, $lower_limit_overrided); 1203 for (my $index = 0; $index <= $#complete; $index++) { 1204 if ($complete[$index] =~ /^(--upper-limit|-u)$/ && (defined $upper_limit)) { 1205 $upper_limit = get_scientific($upper_limit); 1206 $complete[$index + 1] = $upper_limit; 1207 $upper_limit_overrided = 1; 1208 } 1209 if ($complete[$index] =~ /^(--lower-limit|-l)$/ && (defined $lower_limit)) { 1210 $lower_limit = get_scientific($lower_limit); 1211 $complete[$index + 1] = $lower_limit; 1212 $lower_limit_overrided = 1; 1213 } 1214 } 1215 1216 # Add the limit if not present 1217 if (defined $upper_limit && ! $upper_limit_overrided) { 1218 push @complete, "--upper-limit", $upper_limit; 1219 } 1220 if (defined $lower_limit && ! $lower_limit_overrided) { 1221 push @complete, "--lower-limit", $lower_limit; 1222 } 1223 1224 $nb_graphs_drawn ++; 1148 1225 RRDs::graph(@complete); 1149 1226 if (my $ERROR = RRDs::error) { … … 1162 1239 1163 1240 # utime $lastupdate, $lastupdate, 1164 # munin_get_picture_filename($service, $time);1241 # et_picture_filename($service, $time); 1165 1242 1166 1243 if ($list_images) { 1167 1244 # Command-line option to list images created 1168 print munin_get_picture_filename ($service, $time), "\n";1245 print get_picture_filename ($service, $time), "\n"; 1169 1246 } 1170 1247 } … … 1173 1250 if (munin_get_bool($service, "graph_sums", 0)) { 1174 1251 foreach my $time (keys %sumtimes) { 1175 my $picfilename = munin_get_picture_filename($service, $time, 1);1252 my $picfilename = get_picture_filename($service, $time, 1); 1176 1253 (my $picdirname = $picfilename) =~ s/\/[^\/]+$//; 1177 1254 next unless ($draw{"sum" . $time}); … … 1179 1256 push @rrd_sum, @{get_header($service, $time, 1)}; 1180 1257 1181 if (time - 300 < $lastupdate ) {1258 if (time - 300 < $lastupdate && ! $pinpoint) { 1182 1259 if (@added) { # stop 5 minutes earlier if it's a .sum or .stack 1183 1260 push @rrd_sum, "--end", … … 1271 1348 # Make sure directory exists 1272 1349 munin_mkdir_p($picdirname, oct(777)); 1273 1350 1351 $nb_graphs_drawn ++; 1274 1352 RRDs::graph(@rrd_sum); 1275 1353 1276 1354 if (my $ERROR = RRDs::error) { 1277 1355 ERROR "[RRD ERROR(sum)] Unable to graph " 1278 . munin_get_picture_filename($service, $time)1356 . get_picture_filename($service, $time) 1279 1357 . ": $ERROR"; 1280 1358 } 1281 1359 elsif ($list_images) { 1282 1360 # Command-line option to list images created 1283 print munin_get_picture_filename ($service, $time, 1), "\n";1361 print get_picture_filename ($service, $time, 1), "\n"; 1284 1362 } 1285 1363 } # foreach (keys %sumtimes) … … 1287 1365 1288 1366 $service_time = sprintf("%.2f", (Time::HiRes::time - $service_time)); 1289 INFO "Graphed service : $sname ($service_time sec * 4)";1367 INFO "Graphed service : $sname ($service_time sec for $nb_graphs_drawn graphs)"; 1290 1368 print $STATS "GS|$service_time\n" unless $skip_stats; 1291 1369 … … 1340 1418 } 1341 1419 1420 sub ends_with { 1421 my ($src, $searched) = @_; 1422 DEBUG "[DEBUG] ends_with($src, $searched)\n"; 1423 1424 my $is_ending = (substr($src, - length($searched)) eq $searched); 1425 return $is_ending; 1426 } 1427 1342 1428 1343 1429 sub skip_service { 1344 1430 my $service = shift; 1345 my $sname = munin_get_node_name($service); 1431 my $fqn = munin_get_node_fqn($service); 1432 1433 # Skip if we've limited services with the omnipotent cli option only-fqn 1434 return 1 if ($only_fqn and ! ends_with($fqn, $only_fqn)); 1435 DEBUG "[DEBUG] $fqn is in ($only_fqn)\n"; 1346 1436 1347 1437 # Skip if we've limited services with cli options 1348 return 1 if (@limit_services and !grep /^$sname$/, @limit_services); 1438 return 1 if (@limit_services and ! (grep { ends_with($fqn, $_) } @limit_services)); 1439 DEBUG "[DEBUG] $fqn is in (" . join(",", @limit_services) . ")\n"; 1349 1440 1350 1441 # Always graph if --force is present … … 1407 1498 } 1408 1499 1500 # Wrapper for munin_get_picture_filename to handle pinpoint 1501 sub get_picture_filename { 1502 if (defined $output_file) { return $output_file; } 1503 # delegate if not overriden 1504 return munin_get_picture_filename(@_); 1505 } 1506 1409 1507 sub escape { 1410 1508 my $text = shift; … … 1413 1511 $text =~ s/:/\\:/g; 1414 1512 return $text; 1513 } 1514 1515 sub get_scientific { 1516 my $value = shift; 1517 $value =~ s/m/e-03/; 1518 $value =~ s/k/e+03/; 1519 $value =~ s/M/e+06/; 1520 $value =~ s/G/e+09/; 1521 return $value; 1415 1522 } 1416 1523 … … 1444 1551 --[no]list-images List the filenames of the images created. 1445 1552 [--nolist-images] 1553 --output-file -o Output graph file. (used for CGI graphing) 1554 --log-file -l Output log file. (used for CGI graphing) 1446 1555 --[no]day Create day-graphs. [--day] 1447 1556 --[no]week Create week-graphs. [--week] … … 1451 1560 --[no]sumyear Create summarised year-graphs. [--sumyear] 1452 1561 1562 --pinpoint <start,stop> Create custom-graphs. <start,stop> is the standard unix Epoch. [not active] 1563 --size_x <pixels> Sets the X size of the graph in pixels [175] 1564 --size_y <pixels> Sets the Y size of the graph in pixels [400] 1565 --lower_limit <lim> Sets the lower limit of the graph 1566 --upper_limit <lim> Sets the upper limit of the graph 1567 1453 1568 "; 1454 1569 exit 0; trunk/master/lib/Munin/Master/HTMLOld.pm
r3302 r3404 415 415 # NOTE: The templates have hardcoded path to definitions.html, and it is not right, esp. when 416 416 # we have nested groups and nested services. 417 my @files = ("style.css", "logo.png", "logo-h.png", "definitions.html", "favicon.ico"); 417 my @files = ( 418 "style.css", "logo.png", "logo-h.png", "definitions.html", "favicon.ico", 419 "dynazoom.html", "formatdate.js", "querystring.js", 420 ); 418 421 419 422 foreach my $file ((@files)) { … … 933 936 $srv{'imgyear'} = $config->{'cgiurl_graph'} . "/$path-year.png"; 934 937 938 $srv{'cimgday'} = $config->{'cgiurl_graph'} . "/$path-day.png"; 939 $srv{'cimgweek'} = $config->{'cgiurl_graph'} . "/$path-week.png"; 940 $srv{'cimgmonth'} = $config->{'cgiurl_graph'} . "/$path-month.png"; 941 $srv{'cimgyear'} = $config->{'cgiurl_graph'} . "/$path-year.png"; 942 935 943 if (munin_get_bool($service, "graph_sums", 0)) { 936 944 $srv{'imgweeksum'} … … 957 965 } 958 966 967 # Compute the ZOOM urls 968 { 969 my $epoch_now = time; 970 # The intervals are a bit larger, just like the munin-graph 971 my $start_day = $epoch_now - (3600 * 30); 972 my $start_week = $epoch_now - (3600 * 24 * 8); 973 my $start_month = $epoch_now - (3600 * 24 * 33); 974 my $start_year = $epoch_now - (3600 * 24 * 400); 975 my $size_x = 800; 976 my $size_y = 400; 977 my $common_url = "$root_path/dynazoom.html?plugin_name=$path&size_x=$size_x&size_y=$size_y"; 978 $srv{zoomday} = "$common_url&start_epoch=$start_day&stop_epoch=$epoch_now"; 979 $srv{zoomweek} = "$common_url&start_epoch=$start_week&stop_epoch=$epoch_now"; 980 $srv{zoommonth} = "$common_url&start_epoch=$start_month&stop_epoch=$epoch_now"; 981 $srv{zoomyear} = "$common_url&start_epoch=$start_year&stop_epoch=$epoch_now"; 982 } 983 959 984 for my $scale (@times) { 985 # Don't try to find the size if cgi is enabled, 986 # otherwise old data might pollute 987 next if ($method eq "cgi"); 960 988 if (my ($w, $h) 961 989 = get_png_size(munin_get_picture_filename($service, $scale))) { … … 969 997 $srv{imgyearsum} = "$srv{node}-year-sum.png"; 970 998 for my $scale (["week", "year"]) { 999 next if ($method eq "cgi"); 971 1000 if (my ($w, $h) 972 1001 = get_png_size(munin_get_picture_filename($service, $scale, 1))) trunk/master/lib/Munin/Master/Logger.pm
r3091 r3404 73 73 my $logdir = undef; 74 74 my $logopened = 0; 75 my $me = basename($PROGRAM_NAME);75 my $me = $1 if basename($PROGRAM_NAME) =~ m/(.*)/; # Fast untaint $PROGRAM_NAME 76 76 77 77 sub _warn_catcher { … … 93 93 } 94 94 95 my $log_filename = shift || "$dirname/$me.log"; 96 95 97 if (!$logopened) { 96 98 # I'm a bit uncertain about the :utf8 bit. 97 99 Log::Log4perl->easy_init( { level => $INFO, 98 file => ":utf8>>$ dirname/$me.log" } );100 file => ":utf8>>$log_filename" } ); 99 101 # warn "Logging to $dirname/$me.log"; 100 102 $logopened = 1; trunk/master/lib/Munin/Master/Node.pm
r3271 r3404 29 29 host => $host, 30 30 tls => undef, 31 socket => undef, 32 master_capabilities => qw(multigraph), 31 reader => undef, 32 writer => undef, 33 master_capabilities => "multigraph dirtyconfig", 33 34 io_timeout => 120, 34 35 configref => $configref, … … 59 60 if !defined($self->{address}); 60 61 61 if (! ( $self->{socket} = IO::Socket::INET->new( 62 PeerAddr => $self->{address}, 63 PeerPort => $self->{port}, 62 # Check if it's an URI or a plain host 63 use URI; 64 65 my $uri = new URI($self->{address}); 66 67 # If the scheme is not defined, it's a plain host. 68 # Prefix it with munin:// to be able to parse it like others 69 $uri = new URI("munin://" . $self->{address}) unless $uri->scheme; 70 LOGCROAK("[FATAL] '$self->{address}' is not a valid address!") unless $uri->scheme; 71 72 if ($uri->scheme eq "munin") { 73 $self->{reader} = $self->{writer} = IO::Socket::INET->new( 74 PeerAddr => $uri->host, 75 PeerPort => ($uri->port || $self->{port}), 64 76 LocalAddr => $config->{local_address}, 65 77 Proto => 'tcp', 66 Timeout => $config->{timeout}) ) ) { 67 ERROR "Failed to connect to node $self->{address}:$self->{port}/tcp : $!"; 68 return 0; 78 Timeout => $config->{timeout} 79 ); 80 if (! $self->{reader} ) { 81 ERROR "Failed to connect to node $self->{address}:$self->{port}/tcp : $!"; 82 return 0; 83 } 84 } elsif ($uri->scheme eq "ssh") { 85 my $user_part = ($uri->user) ? ($uri->user . "@") : ""; 86 my $remote_connection_cmd = "/usr/bin/ssh $user_part" . $uri->host ." " . $uri->path; 87 # Open a double pipe 88 use IPC::Open2; 89 90 $self->{reader} = new IO::Handle(); 91 $self->{writer} = new IO::Handle(); 92 93 my $pid = open2($self->{reader}, $self->{writer}, $remote_connection_cmd); 94 ERROR "Failed to connect to node $self->{address} : $!" unless $pid; 95 } else { 96 ERROR "Unknown scheme : " . $uri->scheme; 97 return 0; 69 98 } 70 99 … … 98 127 DEBUG => $config->{debug}, 99 128 logger => \&logger, 100 read_fd => fileno($self->{ socket}),129 read_fd => fileno($self->{reader}), 101 130 read_func => sub { _node_read_single($self) }, 102 131 tls_ca_cert => $config->{tls_ca_certificate}, … … 106 135 tls_vdepth => $config->{tls_verify_depth}, 107 136 tls_verify => $config->{tls_verify_certificate}, 108 write_fd => fileno($self->{ socket}),137 write_fd => fileno($self->{writer}), 109 138 write_func => sub { _write_socket_single($self, @_) }, 110 139 }); … … 122 151 my ($self) = @_; 123 152 124 close $self->{socket}; 125 $self->{socket} = undef; 153 close $self->{reader}; 154 close $self->{writer}; 155 $self->{reader} = undef; 156 $self->{writer} = undef; 126 157 } 127 158 … … 437 468 } 438 469 else { 439 print { $self->{ socket} } $text;470 print { $self->{writer} } $text; 440 471 } 441 472 }); … … 457 488 } 458 489 else { 459 $res = readline $self->{ socket};490 $res = readline $self->{reader}; 460 491 } 461 492 chomp $res if defined $res; … … 483 514 my $line = $self->{tls} && $self->{tls}->session_started() 484 515 ? $self->{tls}->read() 485 : readline $self->{ socket};516 : readline $self->{reader}; 486 517 last unless defined $line; 487 518 last if $line =~ /^\.\n$/; … … 496 527 return @array; 497 528 } 529 530 # Defines the URL::scheme for munin 531 package URI::munin; 532 533 # We are like telnet 534 require URI::telnet; 535 @URI::munin::ISA=qw(URI::telnet); 536 537 # munin://HOST[:PORT] 538 539 sub default_port { 4949 } 498 540 499 541 1; trunk/master/lib/Munin/Master/UpdateWorker.pm
r3254 r3404 84 84 } 85 85 86 my %service_data = $self->{node}->fetch_service_data($plugin); 86 # Check if this plugin has already sent its data via a dirtyconfig 87 my %service_data = $self->handle_dirty_config(\%service_config); 88 89 # Check if this plugin has to be updated 90 my $update_rate = get_global_service_value(\%service_config, $plugin, "update_rate", 0); 91 my ($update_rate_in_seconds, $is_update_aligned) = parse_update_rate($update_rate); 92 # default is 0 sec : always update when asked 93 DEBUG "[DEBUG] update_rate $update_rate_in_seconds for $plugin on $nodedesignation"; 94 if ($update_rate_in_seconds 95 && is_fresh_enough($nodedesignation, $plugin, $update_rate_in_seconds)) { 96 # It's fresh enough, skip this $service 97 DEBUG "[DEBUG] $plugin is fresh enough, not updating it"; 98 next; 99 } 100 101 if (! %service_data) { 102 %service_data = $self->{node}->fetch_service_data($plugin); 103 } 104 105 # If update_rate is aligned, round the "when" for alignement 106 if ($is_update_aligned) { 107 foreach my $service (keys %service_data) { 108 my $current_service_data = $service_data{$service}; 109 foreach my $field (keys %$current_service_data) { 110 my $when = $current_service_data->{$field}->{when}; 111 my $rounded_when = round_to_granularity($when, $update_rate_in_seconds); 112 $current_service_data->{$field}->{when} = $rounded_when; 113 } 114 } 115 } 116 87 117 88 118 # Since different plugins can populate multiple … … 148 178 service_configs => \%all_service_configs, 149 179 } 180 } 181 182 sub get_global_service_value { 183 my ($service_config, $service, $conf_field_name, $default) = @_; 184 foreach my $array (@{$service_config->{global}{$service}}) { 185 my ($field_name, $field_value) = @$array; 186 if ($field_name eq $conf_field_name) { 187 return $field_value; 188 } 189 } 190 191 return $default; 192 } 193 194 sub is_fresh_enough { 195 my ($nodedesignation, $service, $update_rate_in_seconds) = @_; 196 197 my $key = "$nodedesignation/$service"; 198 DEBUG "is_fresh_enough asked for $key with a rate of $update_rate_in_seconds"; 199 200 my %last_updated; 201 # XXX - ugly hack. Should be refactored to use a a common state provider 202 203 use Fcntl; # For O_RDWR, O_CREAT, etc. 204 use NDBM_File; 205 tie(%last_updated, 'NDBM_File', '/tmp/munin_plugins_last_updated', O_RDWR|O_CREAT, 0666) or ERROR "$!"; 206 DEBUG "last_updated{$key}: " . $last_updated{$key}; 207 my @last = split(/ /, $last_updated{$key}); 208 209 use Time::HiRes qw(gettimeofday tv_interval); 210 my $now = [ gettimeofday ]; 211 212 my $age = tv_interval(\@last, $now); 213 DEBUG "last: " . Dumper(\@last) . ", now: " . Dumper($now) . ", age: $age"; 214 my $is_fresh_enough = ($age < $update_rate_in_seconds); 215 DEBUG "is_fresh_enough $is_fresh_enough"; 216 217 if (! $is_fresh_enough) { 218 DEBUG "new value: " . join(" ", @$now); 219 $last_updated{$key} = join(" ", @$now); 220 } 221 222 untie(%last_updated); 223 224 return $is_fresh_enough; 225 } 226 227 sub parse_update_rate { 228 my ($update_rate_config) = @_; 229 230 my ($is_update_aligned, $update_rate_in_sec); 231 if ($update_rate_config =~ m/(\d+[a-z]?) (aligned)?/) { 232 $update_rate_in_sec = to_sec($1); 233 $is_update_aligned = $2; 234 } else { 235 return (0, 0); 236 } 237 238 return ($update_rate_in_sec, $is_update_aligned); 239 } 240 241 sub round_to_granularity { 242 my ($when, $granularity_in_sec) = @_; 243 $when = time if ($when eq "N"); # N means "now" 244 245 my $rounded_when = $when - ($when % $granularity_in_sec); 246 return $rounded_when; 247 } 248 249 sub handle_dirty_config { 250 my ($self, $service_config) = @_; 251 252 my %service_data; 253 254 my $services = $service_config->{global}{multigraph}; 255 foreach my $service (@$services) { 256 my $service_data_source = $service_config->{"data_source"}->{$service}; 257 foreach my $field (keys %$service_data_source) { 258 my $field_value = $service_data_source->{$field}->{"value"}; 259 # If not present, ignore 260 next if (! defined $field_value); 261 262 DEBUG "[DEBUG] handle_dirty_config:$service, $field, $field_value"; 263 # Moves the "value" to the service_data 264 $service_data{$service}->{$field} = { 265 "value" => $field_value, 266 "when" => "N", 267 }; 268 269 delete($service_data_source->{$field}{value}); 270 } 271 } 272 273 return %service_data; 150 274 } 151 275 … … 345 469 for my $ds_name (keys %{$service_config}) { 346 470 $self->_set_rrd_data_source_defaults($service_config->{$ds_name}); 347 348 unless (defined($service_config->{$ds_name}{label})) { 471 my $ds_config = $service_config->{$ds_name}; 472 473 unless (defined($ds_config->{label})) { 349 474 ERROR "[ERROR] Unable to update $service on $nodedesignation -> $ds_name: Missing data source configuration attribute: label"; 350 475 next; 351 476 } 352 353 my $rrd_file 354 = $self->_create_rrd_file_if_needed($service, $ds_name, 355 $service_config->{$ds_name}); 477 478 # Sets the DS resolution, searching in that order : 479 # - per field 480 # - per plugin 481 # - globally 482 my $configref = $self->{node}{configref}; 483 $ds_config->{graph_data_size} ||= $configref->{"$service.$ds_name.graph_data_size"}; 484 $ds_config->{graph_data_size} ||= $configref->{"$service.graph_data_size"}; 485 $ds_config->{graph_data_size} ||= $config->{graph_data_size}; 486 487 DEBUG "[DEBUG] asking for a rrd of size : " . $ds_config->{graph_data_size}; 488 my $rrd_file = $self->_create_rrd_file_if_needed($service, $ds_name, $ds_config); 356 489 357 490 if (defined($service_data) and defined($service_data->{$ds_name})) { … … 414 547 $file); 415 548 416 DEBUG "[DEBUG] Maderrd filename: $file\n";549 DEBUG "[DEBUG] rrd filename: $file\n"; 417 550 418 551 return $file; … … 430 563 $ds_config->{type}, $ds_config->{min}, $ds_config->{max}), 431 564 ); 432 433 my $resolution = $config->{graph_data_size}; 565 566 my $resolution = $ds_config->{graph_data_size}; 567 my $update_rate = $ds_config->{update_rate} || 300; # 5 min per default 434 568 if ($resolution eq 'normal') { 435 569 push (@args, … … 452 586 "RRA:MIN:0.5:1:115200", 453 587 "RRA:MAX:0.5:1:115200"); 454 } 588 } elsif ($resolution =~ /^custom (.+)/) { 589 # Parsing resolution to achieve computer format as defined on the RFC : 590 # FULL_NB, MULTIPLIER_1 MULTIPLIER_1_NB, ... MULTIPLIER_NMULTIPLIER_N_NB 591 my @resolutions_computer = parse_custom_resolution($1, $update_rate); 592 foreach my $resolution_computer(@resolutions_computer) { 593 my ($multiplier, $multiplier_nb) = @{$resolution_computer}; 594 # Always add 10% to the RRA size, as specified in 595 # http://munin.projects.linpro.no/wiki/format-graph_data_size 596 $multiplier_nb += int ($multiplier_nb / 10) || 1; 597 push (@args, 598 "RRA:AVERAGE:0.5:$multiplier:$multiplier_nb", 599 "RRA:MIN:0.5:$multiplier:$multiplier_nb", 600 "RRA:MAX:0.5:$multiplier:$multiplier_nb" 601 ); 602 } 603 } 604 DEBUG "[DEBUG] RRDs::create @args"; 455 605 RRDs::create @args; 456 606 if (my $ERROR = RRDs::error) { … … 459 609 } 460 610 611 sub parse_custom_resolution { 612 my @elems = split(',\s*', shift); 613 my $update_rate = shift; 614 615 DEBUG "[DEBUG] update_rate: $update_rate"; 616 617 my @computer_format; 618 foreach my $elem (@elems) { 619 if ($elem =~ m/(\d+) (\d+)/) { 620 # nothing to do, already in computer format 621 push @computer_format, [$1, $2]; 622 } elsif ($elem =~ m/(\w+) for (\w+)/) { 623 my $nb_sec = to_sec($1); 624 my $for_sec = to_sec($2); 625 626 my $multiplier = int ($nb_sec / $update_rate); 627 my $multiplier_nb = int ($for_sec / $nb_sec); 628 629 DEBUG "[DEBUG] $elem" 630 . " -> nb_sec:$nb_sec, for_sec:$for_sec" 631 . " -> multiplier:$multiplier, multiplier_nb:$multiplier_nb" 632 ; 633 push @computer_format, [$multiplier, $multiplier_nb]; 634 } 635 } 636 637 return @computer_format; 638 } 639 640 # return the number of seconds 641 # for the human readable format 642 # s : second, m : minute, h : hour 643 # d : day, w : week, t : month, y : year 644 sub to_sec { 645 my $secs_table = { 646 "s" => 1, 647 "m" => 60, 648 "h" => 60 * 60, 649 "d" => 60 * 60 * 24, 650 "w" => 60 * 60 * 24 * 7, 651 "t" => 60 * 60 * 24 * 31, # a month always has 31 days 652 "y" => 60 * 60 * 24 * 365, # a year always has 365 days 653 }; 654 655 my ($target) = @_; 656 if ($target =~ m/(\d+)([smhdwty])/i) { 657 return $1 * $secs_table->{$2}; 658 } else { 659 # no recognised unit, return the int value as seconds 660 return int $target; 661 } 662 } 663 664 sub to_mul { 665 my ($base, $target) = @_; 666 my $target_sec = to_sec($target); 667 if ($target %% $base != 0) { 668 return 0; 669 } 670 671 return round($target / $base); 672 } 673 674 sub to_mul_nb { 675 my ($base, $target) = @_; 676 my $target_sec = to_sec($target); 677 if ($target %% $base != 0) { 678 return 0; 679 } 680 } 461 681 462 682 sub _update_rrd_file { trunk/master/lib/Munin/Master/Utils.pm
r3236 r3404 55 55 'munin_get_node_name', 56 56 'munin_get_parent_name', 57 'munin_get_node_fqn', 57 58 'munin_get_node_loc', 58 59 'munin_get_node', … … 518 519 } 519 520 521 sub munin_get_node_fqn 522 { 523 my $hash = shift; 524 525 if (ref ($hash) eq "HASH") { 526 my $fqn = ""; 527 if (defined $hash->{'#%#name'}) { 528 $fqn = $hash->{'#%#name'}; 529 } 530 if (defined $hash->{'#%#parent'}) { 531 # Recursively prepend the parent, concatenation with / 532 $fqn = munin_get_node_fqn ($hash->{'#%#parent'}) . "/" . $fqn; 533 } 534 return $fqn; 535 } else { 536 return; 537 } 538 } 520 539 521 540 sub munin_get_picture_loc { trunk/master/www/munin-serviceview.tmpl
r2956 r3404 15 15 <!-- Table row: Day image --> 16 16 <!-- Note, the class of the img does not work to set border width and color. Could be something to do with the table? --> 17 <td>< img src="<TMPL_VAR NAME="IMGDAY">" alt="daily graph" <TMPL_IF NAME="IMGDAYWIDTH">width="<TMPL_VAR NAME="IMGDAYWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGDAYHEIGHT">height="<TMPL_VAR NAME="IMGDAYHEIGHT">"</TMPL_IF>/></td>17 <td><a href="<TMPL_VAR NAME="ZOOMDAY">"><img src="<TMPL_VAR NAME="IMGDAY">" alt="daily graph" <TMPL_IF NAME="IMGDAYWIDTH">width="<TMPL_VAR NAME="IMGDAYWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGDAYHEIGHT">height="<TMPL_VAR NAME="IMGDAYHEIGHT">"</TMPL_IF>/></a></td> 18 18 <!-- cont'd: Week image --> 19 <td>< img src="<TMPL_VAR NAME="IMGWEEK">" alt="weekly graph" <TMPL_IF NAME="IMGWEEKWIDTH">width="<TMPL_VAR NAME="IMGWEEKWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGWEEKHEIGHT">height="<TMPL_VAR NAME="IMGWEEKHEIGHT">"</TMPL_IF>/></td>19 <td><a href="<TMPL_VAR NAME="ZOOMWEEK">"><img src="<TMPL_VAR NAME="IMGWEEK">" alt="weekly graph" <TMPL_IF NAME="IMGWEEKWIDTH">width="<TMPL_VAR NAME="IMGWEEKWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGWEEKHEIGHT">height="<TMPL_VAR NAME="IMGWEEKHEIGHT">"</TMPL_IF>/></a></td> 20 20 </tr> 21 21 <tr> 22 22 <!-- New table row: Month image --> 23 <td>< img src="<TMPL_VAR NAME="IMGMONTH">" alt="monthly graph" <TMPL_IF NAME="IMGMONTHWIDTH">width="<TMPL_VAR NAME="IMGMONTHWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGMONTHHEIGHT">height="<TMPL_VAR NAME="IMGMONTHHEIGHT">"</TMPL_IF>/></td>23 <td><a href="<TMPL_VAR NAME="ZOOMMONTH">"><img src="<TMPL_VAR NAME="IMGMONTH">" alt="monthly graph" <TMPL_IF NAME="IMGMONTHWIDTH">width="<TMPL_VAR NAME="IMGMONTHWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGMONTHHEIGHT">height="<TMPL_VAR NAME="IMGMONTHHEIGHT">"</TMPL_IF>/></a></td> 24 24 <!-- cont'd: Year image --> 25 <td>< img src="<TMPL_VAR NAME="IMGYEAR">" alt="yearly graph" <TMPL_IF NAME="IMGYEARWIDTH">width="<TMPL_VAR NAME="IMGYEARWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGYEARHEIGHT">height="<TMPL_VAR NAME="IMGYEARHEIGHT">"</TMPL_IF>/></td>25 <td><a href="<TMPL_VAR NAME="ZOOMYEAR">"><img src="<TMPL_VAR NAME="IMGYEAR">" alt="yearly graph" <TMPL_IF NAME="IMGYEARWIDTH">width="<TMPL_VAR NAME="IMGYEARWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGYEARHEIGHT">height="<TMPL_VAR NAME="IMGYEARHEIGHT">"</TMPL_IF>/></a></td> 26 26 </tr> 27 27 <!-- .sum graphs. One of the least used features of munin? --> trunk/node
- Property svn:ignore set to
Build
_build
blib
- Property svn:ignore set to
trunk/node/lib/Munin/Node/Server.pm
r3164 r3404 89 89 || (split /\s+/, ($host_name || ''))[1] 90 90 || $config->{fqdn}; 91 92 # hostname checks are case in-sensitive, 93 # so store everything in lowercase 94 $node = lc($node); 91 95 92 96 print STDERR "\tAdding to node $node\n" if $config->{DEBUG}; … … 164 168 logger ("DEBUG: Running command \"$_\".") if $config->{DEBUG}; 165 169 if (/^list\s*([0-9a-zA-Z\.\-]+)?/i) { 166 _list_services($session, $1);170 _list_services($session, lc($1)); 167 171 } 168 172 elsif (/^cap\s?(.*)/i) { trunk/plugins
- Property svn:ignore set to
Build
_build
blib
- Property svn:ignore set to
