Changeset 1293

Show
Ignore:
Timestamp:
08/28/07 00:01:07 (4 years ago)
Author:
jo
Message:

Second milestone on the big group change. munin-graph now works (roughly -- sum/stack/aliasing needs testing and probably fixing).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • people/jo/multilevel-groups/server/Munin.pm.in

    r1292 r1293  
    9494        "version", "tls_certificate", "tls_private_key", "tls_pem",  
    9595        "tls_verify_certificate", "tls_verify_depth", "graph_data_size", 
    96         "colour", "graph_printf", "ok", "unknown", "realservname" 
     96        "colour", "graph_printf", "ok", "unknown", "realservname", "cdef_name", 
     97        "graphable", "process", "realname" 
    9798    ); 
    9899 
     
    100101 
    101102# Fields to copy when "aliasing" a field 
    102 my @copy_fields    = ("label", "draw", "type", "rrdfile", "fieldname", "info");  
     103my @COPY_FIELDS    = ("label", "draw", "type", "rrdfile", "fieldname", "info");  
    103104 
    104105 
     
    121122} 
    122123 
     124# munin_draw_field: Check whether a field will be visible in the graph or not 
     125# Parameters: 
     126# - $hash: A ref to the hash node for the field 
     127# Returns: 
     128# - Success: Boolean; true if field will be graphed, false if not 
     129# - Failure: undef 
    123130sub munin_draw_field { 
    124     my $node    = shift; 
    125     my $service = shift; 
    126     my $field   = shift; 
    127  
    128     $field =~ s/=.*//; 
    129  
    130     print "DEBUG: munin_draw_field: Checking $service -> $field: " . &munin_get_bool_val ($node->{client}->{$service}->{$field.".graph"}, 1) . ".\n" if $DEBUG;; 
    131     return 0 if (exists $node->{client}->{$service}->{$field.".skipdraw"}); 
    132     return (&munin_get_bool_val ($node->{client}->{$service}->{$field.".graph"}, 1)); 
     131    my $hash   = shift; 
     132 
     133    return 0 if munin_get_bool ($hash, "skipdraw", 0); 
     134    return 0 if !munin_get_bool ($hash, "graph", 1); 
     135    return defined $hash->{"label"}; 
    133136} 
    134137 
     
    418421 
    419422    if (ref ($hash) eq "HASH") { 
     423        ::logger ("Debug: Searching for $field in " . join ('::', @{munin_get_node_loc ($hash)})); 
    420424        foreach my $key (keys %{$hash}) { 
    421425            next if $key =~ /^#%#/; 
     
    517521        $hash = $hash->{$tmpvar}; 
    518522    } 
     523} 
     524 
     525# munin_set_var: sets a variable in a hash 
     526# Parameters:  
     527# - $hash: A ref to the hash to set the variable in 
     528# - $var: The name of the variable 
     529# - $val: The value to set the variable to 
     530# Returns: 
     531# - Success: The $hash we were handed 
     532# - Failure: undef 
     533sub munin_set_var 
     534{ 
     535    my $hash = shift; 
     536    my $var  = shift; 
     537    my $val  = shift; 
     538 
     539    return munin_set_var_loc ($hash, [$var], $val); 
    519540} 
    520541 
     
    597618} 
    598619 
     620# munin_get_root_node: Get the root node of the hash tree 
     621# Parameters: 
     622# - $hash: A hash node to traverse up from 
     623# Returns: 
     624# - Success: A ref to the root hash node 
     625# - Failure: undef 
     626sub munin_get_root_node 
     627{ 
     628    my $hash = shift; 
     629 
     630    return undef if ref ($hash) ne "HASH"; 
     631 
     632    while (defined $hash->{'#%#parent'}) { 
     633        $hash = $hash->{'#%#parent'}; 
     634    } 
     635 
     636    return $hash; 
     637} 
     638 
    599639sub munin_writeconfig_loop  
    600640{ 
     
    608648        } else { 
    609649            next if !defined $pre and $key eq "version"; # Handled separately 
     650            next if !defined $hash->{$key} or !length $hash->{$key}; 
    610651            (my $outstring = $hash->{$key}) =~ s/([^\\])#/$1\\#/g; 
    611652            print "Writing: $path $outstring\n" if $DEBUG; 
     
    656697} 
    657698 
     699# munin_get_picture_filename: Get the full path+name of a picture file 
     700# Parameters: 
     701# - $hash: A ref to the service hash node 
     702# - $scale: The scale (day, week, year, month) 
     703# - $sum: [optional] Boolean value, whether it's a sum graph or not. 
     704# Returns: 
     705# - Success: The file name with full path 
     706# - Failure: undef 
    658707sub munin_get_picture_filename { 
    659     my $config  = shift; 
    660     my $domain  = shift; 
    661     my $name    = shift; 
    662     my $service = shift; 
     708    my $hash    = shift; 
    663709    my $scale   = shift; 
    664710    my $sum     = shift; 
    665     my $dir     = $config->{'htmldir'}; 
     711    my $loc     = munin_get_node_loc ($hash); 
     712    my $ret     = munin_get ($hash, 'htmldir'); 
    666713 
    667714    # Sanitise 
    668     $dir =~ s/[^\w_\/"'\[\]\(\)+=-]\./_/g; 
    669     $domain =~ s/[^\w_\/"'\[\]\(\)+=\.-]/_/g; 
    670     $name =~ s/[^\w_\/"'\[\]\(\)+=\.-]/_/g; 
    671     $service =~ s/[^\w_\/"'\[\]\(\)+=-]/_/g; 
     715    $ret =~ s/[^\w_\/"'\[\]\(\)+=-]\./_/g; 
     716    $hash =~ s/[^\w_\/"'\[\]\(\)+=-]/_/g; 
    672717    $scale =~ s/[^\w_\/"'\[\]\(\)+=-]/_/g; 
    673  
    674     if (defined $sum and $sum) 
    675     { 
    676             return "$dir/$domain/$name-$service-$scale-sum.png"; 
    677     } 
    678     else 
    679     { 
    680             return "$dir/$domain/$name-$service-$scale.png"; 
    681     } 
    682 
    683  
    684 # munin_get_filename: Get rrd filename for a field 
     718    @$loc = map { s/\//_/g; $_ } @$loc; 
     719    @$loc = map { s/^\./_/g; $_ } @$loc; 
     720         
     721    my $plugin = pop @$loc or return undef; 
     722    my $node   = pop @$loc or return undef; 
     723 
     724    if (@$loc) { # The rest is used as directory names... 
     725        $ret .= "/" . join ('/', @$loc); 
     726    } 
     727 
     728    if (defined $sum and $sum) { 
     729            return "$ret/$node-$plugin-$scale-sum.png"; 
     730    } else { 
     731            return "$ret/$node-$plugin-$scale-sum.png"; 
     732    } 
     733
     734 
     735# munin_path_to_loc: Returns a loc array from a path string 
     736# Parameters:  
     737# - $path: A path string 
     738# Returns: 
     739# - Success: A ref to an array with the loc 
     740# - Failure: undef 
     741sub munin_path_to_loc 
     742
     743    my $path = shift; 
     744 
     745    my $result = undef; 
     746 
     747    if ($path =~ /^\s*([^:]+):(\S+)\s*$/) { 
     748        my ($leftstring, $rightstring) = ($1, $2); 
     749 
     750        my @leftarr = split (/;/, $leftstring); 
     751        my @rightarr = split (/\./, $rightstring); 
     752        $result = [@leftarr, @rightarr]; 
     753    } elsif ($path =~ /^\s*([^;:\.]+)\s*$/) { 
     754        $result = [$1]; 
     755    } elsif ($path =~ /^\s*(.+)\.([^\.:;]+)$/) { 
     756        my ($leftstring, $rightstring) = ($1, $2); 
     757 
     758        my @leftarr = split (/;/, $leftstring); 
     759        my @rightarr = split (/\./, $rightstring); 
     760        $result = [@leftarr, @rightarr]; 
     761    } elsif ($path =~ /^\s*(\S+)\s*$/) { 
     762        my @leftarr = split (/;/, $1); 
     763        $result = [@leftarr]; 
     764    } else { 
     765        ::logger ("Error: munin_path_to_loc: Malformatted variable path \"$path\"."); 
     766    } 
     767 
     768    if (!defined $result) { 
     769        ::logger ("Error: munin_path_to_loc: Failed converting \"$path\"."); 
     770    } 
     771 
     772    return $result; 
     773
     774 
     775 
     776# munin_get_filename: Get rrd filename for a field, without any  
     777#                     bells or whistles. Used by munin-update to  
     778#                     figure out which file to update. 
    685779# Parameters: 
    686780# - $hash: Ref to hash field 
     
    10121106} 
    10131107 
     1108# munin_get_max_label_length: Get the length of the longest labe in a graph 
     1109# Parameters: 
     1110# - $hash: the graph in question 
     1111# - $order: A ref to an array of fields (graph_order) 
     1112# Returns: 
     1113# - Success: The length of the longest label in the graph 
     1114# - Failure: undef 
    10141115sub munin_get_max_label_length 
    10151116{ 
    1016     my $node    = shift; 
    1017     my $config  = shift; 
    1018     my $domain  = shift; 
    1019     my $host    = shift; 
    10201117    my $service = shift; 
    10211118    my $order   = shift; 
    10221119    my $result  = 0; 
     1120    my $tot     = munin_get ($service, "graph_total"); 
    10231121 
    10241122    for my $field (@$order) { 
    10251123        my $path = undef; 
    10261124        (my $f = $field) =~ s/=.+//; 
    1027         next if (exists $node->{client}->{$service}->{$f.".process"} and 
    1028                  $node->{client}->{$service}->{$f.".process"} ne "yes"); 
    1029         next if (exists $node->{client}->{$service}->{$f.".skipdraw"}); 
    1030         next unless (!exists $node->{client}->{$service}->{$f.".graph"} or 
    1031                         $node->{client}->{$service}->{$f.".graph"} eq "yes"); 
    1032         if ($result < length ($node->{client}->{$service}->{$f.".label"} || $f)) { 
    1033             $result = length ($node->{client}->{$service}->{$f.".label"} || $f); 
    1034         } 
    1035         if (exists $node->{client}->{$service}->{graph_total} and  
    1036                 length $node->{client}->{$service}->{graph_total} > $result) 
    1037         { 
    1038             $result = length $node->{client}->{$service}->{graph_total}; 
    1039         } 
     1125        next if (!munin_get_bool ($service->{$f}, "process", 1)); 
     1126        next if (munin_get_bool ($service->{$f}, "skipdraw", 0)); 
     1127        next if (!munin_get_bool ($service->{$f}, "graph", 1)); 
     1128 
     1129        my $len = length (munin_get ($service->{$f}, "label") || $f); 
     1130 
     1131        if ($result < $len) { 
     1132            $result = $len; 
     1133        } 
     1134    } 
     1135    if (defined $tot and length $tot > $result) { 
     1136        $result = length $tot; 
    10401137    } 
    10411138    return $result; 
    10421139} 
    10431140 
     1141# munin_get_field_order: Get the field order in a graph 
     1142# Parameters: 
     1143# - $hash: A hash ref to the service 
     1144# Returns: 
     1145# - Success: A ref to an array of the field names 
     1146# - Failure: undef 
    10441147sub munin_get_field_order 
    10451148{ 
    1046     my $node    = shift; 
    1047     my $config  = shift; 
    1048     my $domain  = shift; 
    1049     my $host    = shift; 
    1050     my $service = shift; 
     1149    my $hash = shift; 
    10511150    my $result  = []; 
    10521151 
    1053     if ($node->{client}->{$service}->{graph_sources})  
    1054     { 
    1055         foreach my $gs (split /\s+/, $node->{client}->{$service}->{'graph_sources'}) 
    1056         { 
     1152    return undef if !defined $hash or ref($hash) ne "HASH"; 
     1153 
     1154    my $order = munin_get ($hash, "graph_order"); 
     1155 
     1156    if (defined $hash->{graph_sources}) { 
     1157        foreach my $gs (split /\s+/, $hash->{'graph_sources'}) { 
    10571158            push (@$result, "-".$gs); 
    10581159        } 
    10591160    }  
    1060     if ($node->{client}->{$service}->{graph_order})  
    1061     { 
    1062         push (@$result, split /\s+/, $node->{client}->{$service}->{'graph_order'}); 
     1161    if (defined $order) { 
     1162        push (@$result, split /\s+/, $order); 
    10631163    }  
    10641164 
    1065     for my $key (keys %{$node->{client}->{$service}})  
    1066     { 
    1067         my ($client,$type)=""; 
    1068         ($client,$type) = split /\./,$key; 
    1069         if (defined $type and $type eq "label")  
    1070         { 
    1071             push @$result,$client if !grep /^\Q$client\E(?:=|$)/, @$result;; 
    1072         }  
     1165    for my $fieldnode (@{munin_find_field ($hash, "label")}) { 
     1166        my $fieldname = munin_get_node_name ($fieldnode); 
     1167        push @$result,$fieldname if !grep /^\Q$fieldname\E(?:=|$)/, @$result;; 
    10731168    } 
    10741169     
     
    10761171} 
    10771172 
     1173# munin_get_rrd_filename: Get the name of the rrd file corresponding to a  
     1174#                         field. Checks for lots of bells and whistles. 
     1175#                         This function is the correct one to use when  
     1176#                         figuring out where to fetch data from. 
     1177# Parameters: 
     1178# - $field: The hash object of the field 
     1179# - $path: [optional] The path to the field (as given in graph_order/sum/stack/et al) 
     1180# Returns: 
     1181# - Success: A string with the filename of the rrd file 
     1182# - Failure: undef 
    10781183sub munin_get_rrd_filename { 
    1079     my $node    = shift; 
    1080     my $config  = shift; 
    1081     my $domain  = shift; 
    1082     my $name    = shift; 
    1083     my $service = shift; 
    10841184    my $field   = shift; 
    10851185    my $path    = shift; 
    1086     my $result  = "unknown"; 
    1087  
    1088     if ($node->{client}->{$service}->{$field.".filename"}) 
    1089     { 
    1090         $result = $node->{client}->{$service}->{$field.".filename"}; 
    1091     } 
    1092     elsif ($path) 
    1093     { 
    1094         if (!defined ($node->{client}->{$service}->{$field.".label"})) 
    1095         { 
    1096             print "DEBUG: Setting label: $field\n" if $DEBUG; 
    1097             $node->{client}->{$service}->{$field.".label"} = $field; 
    1098         } 
    1099  
    1100         if ($path =~ /^\s*([^:;]+)[:;]([^:]+):([^:\.]+)[:\.]([^:\.]+)\s*$/) 
    1101         { 
    1102             $result = munin_get_filename ($config, $1, $2, $3, $4); 
    1103             print "\nDEBUG1: Expanding $path...\n" if $DEBUG; 
    1104             if (! defined $node->{client}->{$service}->{$field."label"}) 
    1105             { 
    1106                 for my $f (@copy_fields) 
    1107                 { 
    1108                     if (not exists $node->{client}->{$service}->{"$field.$f"} and 
    1109                             exists $config->{'domain'}->{$1}->{'node'}->{$2}->{'client'}->{$3}->{"$4.$f"}) 
    1110                     { 
    1111                         $node->{client}->{$service}->{"$field.$f"} = $config->{'domain'}->{$1}->{'node'}->{$2}->{'client'}->{$3}->{"$4.$f"}; 
    1112                     } 
    1113                 } 
    1114             } 
    1115         } 
    1116         elsif ($path =~ /^\s*([^:]+):([^:\.]+)[:\.]([^:\.]+)\s*$/) 
    1117         { 
    1118             print "\nDEBUG2: Expanding $path...\n" if $DEBUG; 
    1119             $result = munin_get_filename ($config, $domain, $1, $2, $3); 
    1120             for my $f (@copy_fields) 
    1121             { 
    1122                 if (not exists $node->{client}->{$service}->{"$field.$f"} and 
    1123                         exists $config->{'domain'}->{$domain}->{'node'}->{$1}->{'client'}->{$2}->{"$3.$f"}) 
    1124                 { 
    1125                     print "DEBUG: Copying $f...\n" if $DEBUG; 
    1126                     $node->{client}->{$service}->{"$field.$f"} = $config->{'domain'}->{$domain}->{'node'}->{$1}->{'client'}->{$2}->{"$3.$f"}; 
    1127                 } 
    1128             } 
    1129         } 
    1130         elsif ($path =~ /^\s*([^:\.]+)[:\.]([^:\.]+)\s*$/) 
    1131         { 
    1132             print "\nDEBUG3: Expanding $path...\n" if $DEBUG; 
    1133             $result = munin_get_filename ($config, $domain, $name, $1, $2); 
    1134             for my $f (@copy_fields) 
    1135             { 
    1136                 if (not exists $node->{client}->{$service}->{"$field.$f"} and 
    1137                         exists $node->{client}->{$1}->{"$2.$f"}) 
    1138                 { 
    1139                     $node->{client}->{$service}->{"$field.$f"} = $node->{client}->{$1}->{"$2.$f"}; 
    1140                 } 
    1141             } 
    1142         } 
    1143         elsif ($path =~ /^\s*([^:\.]+)\s*$/) 
    1144         { 
    1145             print "\nDEBUG4: Expanding $path...\n" if $DEBUG; 
    1146             $result = munin_get_filename ($config, $domain, $name, $service, $1); 
    1147             for my $f (@copy_fields) 
    1148             { 
    1149                 if (not exists $node->{client}->{$service}->{"$field.$f"} and 
    1150                         exists $node->{client}->{$service}->{"$1.$f"}) 
    1151                 { 
    1152                     $node->{client}->{$service}->{"$field.$f"} = $node->{client}->{$service}->{"$1.$f"}; 
    1153                 } 
    1154             } 
    1155         } 
    1156     } 
    1157     else 
    1158     { 
    1159         print "\nDEBUG5: Doing path...\n" if $DEBUG; 
    1160         $result = munin_get_filename($config, $domain,$name,$service,$field); 
     1186    my $result  = undef; 
     1187    my $name    = munin_get_node_name ($field); 
     1188 
     1189    # If the field has a .filename setting, use it 
     1190    return $result if $result = munin_get ($field, "filename"); 
     1191 
     1192    # Handle custom paths (used in .sum, .stack, graph_order, et al) 
     1193    if (defined $path and length $path) { 
     1194        if (!munin_get ($field, "label")) { 
     1195            print "DEBUG: Setting label: $name\n" if $DEBUG; 
     1196            munin_set_var_loc ($field, ["label"], $name); 
     1197        } 
     1198 
     1199        my $sourcenode = munin_get_node (munin_get_root_node ($field), munin_path_to_loc ($path)); 
     1200        $result = munin_get_filename ($sourcenode); 
     1201 
     1202        for my $f (@COPY_FIELDS) { 
     1203            if (not exists $field->{$f} and exists $sourcenode->{$f}) { 
     1204                print "DEBUG: Copying $f...\n" if $DEBUG; 
     1205                munin_set_var_loc ($field, [$f], $sourcenode->{$f}); 
     1206            } 
     1207        } 
     1208    } else { 
     1209        $result = munin_get_filename ($field); 
    11611210    } 
    11621211    return $result; 
     
    11771226    return $dirname if (-e $dirname); 
    11781227 
    1179     (my $prev = $dirname) =~ s/\/[^\/]+$//; 
    1180     if (mkdir_p ($prev, $umask)) { 
     1228 
     1229    ::logger ("Notice: Created directory \"$dirname\"."); 
     1230    (my $prev = $dirname) =~ s/\/[^\/]+\/?$//; 
     1231    if (munin_mkdir_p ($prev, $umask)) { 
    11811232        if (mkdir ($dirname, $umask)) { 
    11821233            return $dirname; 
  • people/jo/multilevel-groups/server/munin-graph.in

    r1214 r1293  
    3030use Getopt::Long; 
    3131use Time::HiRes; 
     32use Data::Dumper qw(Dumper); 
    3233 
    3334my $graph_time= Time::HiRes::time; 
     
    185186        ); 
    186187 
    187 for my $key ( keys %{$config->{domain}}) { 
    188     my $domain_time= Time::HiRes::time; 
    189     mkdir "$config->{htmldir}/$key",0777; 
    190     logger("Processing domain: $key"); 
    191     &process_domain($key); 
    192     $domain_time = sprintf ("%.2f",(Time::HiRes::time - $domain_time)); 
    193     logger("Processed domain: $key ($domain_time sec)"); 
    194     print STATS "GD|$key|$domain_time\n" unless $skip_stats; 
    195 
    196  
     188# Make array of what is probably needed to graph 
     189my $work_array = []; 
     190if (@limit_hosts) { # Limit what to update if needed 
     191    foreach my $nodename (@limit_hosts) { 
     192        push @$work_array, map { @{munin_find_field ($_->{$nodename}, "graph_title")} } @{munin_find_field($config, $nodename)}; 
     193    } 
     194} else { # ...else just search for all adresses to update 
     195    push @$work_array, @{munin_find_field($config, "graph_title")}; 
     196
     197 
     198 
     199for my $service (@$work_array) { 
     200    process_service ($service); 
     201
    197202 
    198203$graph_time = sprintf ("%.2f",(Time::HiRes::time - $graph_time)); 
     
    203208close $log; 
    204209 
    205 sub process_domain { 
    206     my ($domain) = @_; 
    207     for my $key ( keys %{$config->{domain}->{$domain}->{node}}) { 
    208         my $node_time= Time::HiRes::time; 
    209  
    210         process_node($domain,$key ,$config->{domain}->{$domain}->{node}->{$key} );       
    211         $node_time = sprintf ("%.2f",(Time::HiRes::time - $node_time)); 
    212         logger ("Processed node: $key ($node_time sec)"); 
    213         print STATS "GN|$domain|$key|$node_time\n" unless $skip_stats; 
    214          
    215     } 
    216 } 
    217  
    218210sub get_title { 
    219     my $node    = shift; 
    220211    my $service = shift; 
    221212    my $scale   = shift; 
    222213 
    223     return ($node->{client}->{$service}->{'graph_title'}? 
    224               $node->{client}->{$service}->{'graph_title'}:$service) . 
    225               " - by $scale"; 
     214    return (munin_get ($service, "graph_title", $service) . " - by $scale"); 
    226215} 
    227216 
    228217sub get_custom_graph_args 
    229218{ 
    230     my $node    = shift; 
    231219    my $service = shift; 
    232220    my $result  = []; 
    233221 
    234     if ($node->{client}->{$service}->{graph_args}) { 
    235         push @$result, split /\s/,$node->{client}->{$service}->{graph_args}; 
     222    my $args    = munin_get ($service, "graph_args"); 
     223    if (defined $args) { 
     224        push @$result, split /\s/,$args; 
    236225        return $result; 
    237     } 
    238     else 
    239     { 
     226    } else { 
    240227        return undef; 
    241228    } 
     
    244231sub get_vlabel 
    245232{ 
    246     my $node    = shift; 
    247233    my $service = shift; 
    248     my $scale   = shift; 
    249  
    250     if ($node->{client}->{$service}->{graph_vlabel}) { 
    251         (my $res = $node->{client}->{$service}->{graph_vlabel}) =~ s/\$\{graph_period\}/$scale/g; 
    252         return $res; 
    253     } 
    254     elsif ($node->{client}->{$service}->{graph_vtitle}) 
    255     { 
    256         return $node->{client}->{$service}->{graph_vtitle}; 
    257     } 
    258     return undef; 
     234    my $scale   = munin_get ($service, "graph_period", "second"); 
     235    my $res     = munin_get ($service, "graph_vlabel", munin_get ($service, "graph_vtitle")); 
     236 
     237    if (defined $res) { 
     238        $res =~ s/\$\{graph_period\}/$scale/g; 
     239    } 
     240    return $res; 
    259241} 
    260242 
    261243sub should_scale 
    262244{ 
    263     my $node    = shift; 
    264245    my $service = shift; 
    265  
    266     if (defined $node->{client}->{$service}->{graph_scale}) 
    267     { 
    268         return &munin_get_bool_val ($node->{client}->{$service}->{graph_scale}, 1); 
    269     } 
    270     elsif (defined $node->{client}->{$service}->{graph_noscale}) 
    271     { 
    272         return ! &munin_get_bool_val ($node->{client}->{$service}->{graph_noscale}, 0); 
    273     } 
    274  
    275     return 1; 
     246    my $ret; 
     247 
     248    if (!defined ($ret = munin_get_bool ($service, "graph_scale"))) { 
     249        $ret = !munin_get_bool ($service, "graph_noscale", 0); 
     250    } 
     251 
     252    return $ret; 
    276253} 
    277254 
    278255sub get_header { 
    279     my $node    = shift; 
    280     my $config  = shift; 
    281     my $domain  = shift; 
    282     my $host    = shift; 
    283256    my $service = shift; 
    284257    my $scale   = shift; 
     
    288261 
    289262    # Picture filename 
    290     push @$result, &munin_get_picture_filename ($config, $domain, $host, $service, $scale, $sum||undef); 
     263    push @$result, munin_get_picture_filename ($service, $scale, $sum||undef); 
    291264 
    292265    # Title 
    293     push @$result, ("--title", &get_title ($node, $service, $scale)); 
     266    push @$result, ("--title", get_title ($service, $scale)); 
    294267 
    295268    # When to start the graph 
     
    297270 
    298271    # Custom graph args, vlabel and graph title 
    299     if (defined ($tmp_field = &get_custom_graph_args ($node, $service))) { 
     272    if (defined ($tmp_field = get_custom_graph_args ($service))) { 
    300273        push (@$result, @{$tmp_field}); 
    301274    } 
    302     if (defined ($tmp_field = &get_vlabel ($node, $service, munin_get ($config, "graph_period", "second", $domain, $host, $service)))) { 
     275    if (defined ($tmp_field = get_vlabel ($service))) { 
    303276        push @$result, ("--vertical-label", $tmp_field); 
    304277    } 
    305278 
    306     push @$result,"--height", &munin_get ($config, "graph_height", "175", $domain, $host, $service); 
    307     push @$result,"--width", &munin_get ($config, "graph_width", "400", $domain, $host, $service); 
     279    push @$result,"--height", munin_get ($service, "graph_height", "175"); 
     280    push @$result,"--width", munin_get ($service, "graph_width", "400"); 
    308281    push @$result,"--imgformat", "PNG"; 
    309282    push @$result,"--lazy" if ($force_lazy); 
    310283 
    311     push (@$result, "--units-exponent", "0")  
    312         if (! &should_scale ($node, $service)); 
     284    push (@$result, "--units-exponent", "0") if (! should_scale ($service)); 
    313285 
    314286    return $result; 
     
    317289sub get_sum_command 
    318290{ 
    319     my $node    = shift; 
    320     my $service = shift; 
    321291    my $field   = shift; 
    322292 
    323     if (defined $node->{client}->{$service}->{$field.".special_sum"}) 
    324     { 
    325         return $node->{client}->{$service}->{$field.".special_sum"}; 
    326     } 
    327     elsif (defined $node->{client}->{$service}->{$field.".sum"}) 
    328     { 
    329         return $node->{client}->{$service}->{$field.".sum"}; 
    330     } 
    331  
    332     return undef; 
     293    if (defined $field->{"special_sum"}) { # Deprecated 
     294        return $field->{"special_sum"}; 
     295    } 
     296 
     297    return munin_get ($field, "sum"); 
    333298} 
    334299 
    335300sub get_stack_command 
    336301{ 
    337     my $node    = shift; 
    338     my $service = shift; 
    339302    my $field   = shift; 
    340303 
    341     if (defined $node->{client}->{$service}->{$field.".special_stack"}) 
    342     { 
    343         return $node->{client}->{$service}->{$field.".special_stack"}; 
    344     } 
    345     elsif (defined $node->{client}->{$service}->{$field.".stack"}) 
    346     { 
    347         return $node->{client}->{$service}->{$field.".stack"}; 
    348     } 
    349  
    350     return undef; 
     304    if (defined $field->{"special_stack"}) { # Deprecated 
     305        return $field->{"special_stack"};  
     306    }  
     307     
     308    return munin_get ($field, "stack"); 
    351309} 
    352310 
    353311sub expand_specials 
    354312{ 
    355     my $node    = shift; 
    356     my $config  = shift; 
    357     my $domain  = shift; 
    358     my $host    = shift; 
    359313    my $service = shift; 
    360314    my $preproc = shift; 
     
    366320    for my $field (@$order) { # Search for 'specials'... 
    367321 
    368         if ($field =~ /^-(.+)$/) 
    369         { 
     322        if ($field =~ /^-(.+)$/) { 
    370323            $field = $1; 
    371             unless (defined $node->{client}->{$service}->{$field.".graph"} or 
    372                     defined $node->{client}->{$service}->{$field.".skipdraw"}) 
    373             { 
    374                 $node->{client}->{$service}->{$field.".graph"} = "no"; 
    375             } 
     324            munin_set_var_loc ($service, [$field, "graph"], "no"); 
    376325        } 
    377326 
    378327        $fieldnum++; 
    379328        my $tmp_field; 
    380         if (defined ($tmp_field = &get_stack_command ($node, $service, $field))) 
    381         { 
     329        if (defined ($tmp_field = &get_stack_command ($service->{$field}))) { 
    382330            print "DEBUG: Doing special_stack...\n" if $DEBUG; 
    383331            my @spc_stack = (); 
    384             foreach my $pre (split (/\s+/, $tmp_field)) 
    385             { 
     332            foreach my $pre (split (/\s+/, $tmp_field)) { 
    386333                (my $name = $pre) =~ s/=.+//; 
    387                 if (!@spc_stack) 
    388                 { 
    389                     $node->{client}->{$service}->{$name.".draw"} = $node->{client}->{$service}->{$field.".draw"}; 
    390                     $node->{client}->{$service}->{$field.".process"} = "no"; 
    391                 } 
    392                 else 
    393                 { 
    394                     $node->{client}->{$service}->{$name.".draw"} = "STACK"; 
     334                if (!@spc_stack) { 
     335                    munin_set_var_loc ($service->{$name}, ["draw"], munin_get ($service->{$field}, "draw")); 
     336                    munin_set_var_loc ($service->{$field}, ["process"], "no"); 
     337                } else { 
     338                    munin_set_var_loc ($service->{$name}, ["draw"], "STACK"); 
    395339                } 
    396340                push (@spc_stack, $name); 
     
    400344                push @$result, "$name.cdef"; 
    401345 
    402                 $node->{client}->{$service}->{$name.".label"} = $name; 
    403                 $node->{client}->{$service}->{$name.".cdef"} = "$name,UN,0,$name,IF"; 
    404                 if (exists $node->{client}->{$service}->{$field.".cdef"} and !exists $node->{client}->{$service}->{$name.".onlynullcdef"}) 
    405                 { 
     346                munin_set_var_loc ($service->{$name}, ["label"], $name); 
     347                munin_set_var_loc ($service->{$name}, ["cdef"], "$name,UN,0,$name,IF"); 
     348                if (munin_get ($service->{$field}, "cdef") and !munin_get_bool ($service->{$name}, "onlynullcdef", 0)) { 
    406349                    print "NotOnlynullcdef ($field)...\n" if $DEBUG; 
    407                     $node->{client}->{$service}->{$name.".cdef"} .= "," . 
    408                         $node->{client}->{$service}->{$field.".cdef"}; 
    409                     $node->{client}->{$service}->{$name.".cdef"} =~ s/\b$field\b/$name/g; 
    410                 } 
    411                 else 
    412                 { 
     350                    $service->{$name}->{"cdef"} .= "," . $service->{$field}->{"cdef"}; 
     351                    $service->{$name}->{"cdef"} =~ s/\b$field\b/$name/g; 
     352                } else { 
    413353                    print "Onlynullcdef ($field)...\n" if $DEBUG; 
    414                     $node->{client}->{$service}->{$name.".onlynullcdef"} = 1
     354                    munin_set_var_loc ($service->{$name}, ["onlynullcdef"], 1)
    415355                    push @$result, "$name.onlynullcdef"; 
    416356                } 
    417357            } 
    418         } 
    419         elsif (defined ($tmp_field = &get_sum_command ($node, $service, $field))) 
    420         { 
     358        } elsif (defined ($tmp_field = &get_sum_command ($service->{$field}))) { 
    421359            my @spc_stack = (); 
    422360            my $last_name = ""; 
    423361            print "DEBUG: Doing special_sum...\n" if $DEBUG; 
    424362 
    425                 if (@$order == 1 or  
    426                         @$order == 2 && $node->{client}->{$service}->{$field.".negative"})  
    427                 { 
    428                         $single = 1; 
    429                 } 
     363            if (@$order == 1 or (@$order == 2 and munin_get {$field, "negative", 0})) { 
     364                    $single = 1; 
     365            } 
    430366                 
    431             foreach my $pre (split (/\s+/, $tmp_field)) 
    432             { 
     367            foreach my $pre (split (/\s+/, $tmp_field)) { 
    433368                (my $path = $pre) =~ s/.+=//; 
    434369                my $name = "z".$fieldnum."_".scalar (@spc_stack); 
    435370                $last_name = $name; 
    436371 
    437                 $node->{client}->{$service}->{$name.".cdef"}  = "$name,UN,0,$name,IF"
    438                 $node->{client}->{$service}->{$name.".graph"} = "no"
    439                 $node->{client}->{$service}->{$name.".label"} = $name
     372                munin_set_var_loc ($service, [$name, "cdef"], "$name,UN,0,$name,IF")
     373                munin_set_var_loc ($service, [$name, "graph"], "no")
     374                munin_set_var_loc ($service, [$name, "label"], $name)
    440375                push @$result, "$name.cdef"; 
    441376                push @$result, "$name.graph"; 
     
    445380                push (@$preproc, "$name=$pre"); 
    446381            } 
    447             $node->{client}->{$service}->{$last_name.".cdef"} .= 
    448                 "," . join (',+,', @spc_stack[0 .. @spc_stack-2]) . ',+'; 
    449             if (exists $node->{client}->{$service}->{$field.".cdef"} and  
    450                     length $node->{client}->{$service}->{$field.".cdef"}) 
    451             { # Oh bugger... 
    452                 my $tc = $node->{client}->{$service}->{$field.".cdef"}; 
     382            $service->{$last_name}->{"cdef"} .= "," . join (',+,', @spc_stack[0 .. @spc_stack-2]) . ',+'; 
     383 
     384            if (my $tc = munin_get ($service->{$field}, "cdef", 0)) { # Oh bugger... 
    453385                print "Oh bugger...($field)...\n" if $DEBUG; 
    454                 $tc =~ s/\b$field\b/$node->{client}->{$service}->{$last_name.".cdef"}/; 
    455                 $node->{client}->{$service}->{$last_name.".cdef"} = $tc; 
    456             } 
    457             $node->{client}->{$service}->{$field.".process"} = "no"; 
    458             $node->{client}->{$service}->{$last_name.".draw"} = $node->{client}->{$service}->{$field.".draw"}; 
    459             $node->{client}->{$service}->{$last_name.".label"} = $node->{client}->{$service}->{$field.".label"}; 
    460             if (defined $node->{client}->{$service}->{$field.".graph"}) 
    461             { 
    462                 $node->{client}->{$service}->{$last_name.".graph"} = $node->{client}->{$service}->{$field.".graph"}; 
    463             } 
    464             else 
    465             { 
    466                 $node->{client}->{$service}->{$last_name.".graph"} = "yes"; 
    467             } 
    468             if (defined $node->{client}->{$service}->{$field.".negative"}) 
    469             { 
    470                 $node->{client}->{$service}->{$last_name.".negative"} = $node->{client}->{$service}->{$field.".negative"};; 
    471             } 
    472             $node->{client}->{$service}->{$field.".realname"} = $last_name; 
    473             print "Setting node->{client}->{$service}->{$field} -> realname = $last_name...\n" if $DEBUG; 
    474         } 
    475         elsif (defined $node->{client}->{$service}->{$field.".negative"}) 
    476         { 
    477             my $nf = $node->{client}->{$service}->{$field.".negative"}; 
    478             unless (defined $node->{client}->{$service}->{$nf.".graph"} or 
    479                     defined $node->{client}->{$service}->{$nf.".skipdraw"}) 
    480             { 
    481                 $node->{client}->{$service}->{$nf.".graph"} = "no"; 
     386                $tc =~ s/\b$field\b/$service->{$last_name}->{"cdef"}/; 
     387                $service->{$last_name}->{"cdef"} = $tc; 
     388            } 
     389            munin_set_var_loc ($service, [$field, "process"], "no"); 
     390            munin_set_var_loc ($service, [$last_name, "draw"], munin_get ($service->{$field}, "draw")); 
     391            munin_set_var_loc ($service, [$last_name, "label"], munin_get ($service->{$field}, "label")); 
     392            munin_set_var_loc ($service, [$last_name, "graph"], munin_get ($service->{$field}, "graph", "yes")); 
     393 
     394            if (my $tmp = munin_get($service->{$field}, "negative")) { 
     395                munin_set_var_loc ($service, [$last_name, "negative"], $tmp); 
     396            } 
     397 
     398            munin_set_var_loc ($service, [$field, "realname"], $last_name); 
     399 
     400        } elsif (my $nf = munin_get ($service->{$field}, "negative", 0)) { 
     401            if (!munin_get_bool ($service->{$nf}, "graph", 1) or munin_get_bool ($service->{$nf}, "skipdraw", 0)) { 
     402                munin_set_var_loc ($service, [$nf, "graph"], "no"); 
    482403            } 
    483404        } 
     
    488409sub single_value 
    489410{ 
    490     my $node    = shift; 
    491     my $config  = shift; 
    492     my $domain  = shift; 
    493     my $host    = shift; 
    494411    my $service = shift; 
    495     my $field   = shift; 
    496     my $order   = shift; 
    497  
    498     return 1 if @$order == 1; 
    499     return 1 if (@$order == 2 and $node->{client}->{$service}->{$field.".negative"}); 
    500  
    501     my $graphable = 0; 
    502     if (!defined $node->{client}->{$service}->{"graphable"}) 
    503     { 
    504 #       foreach my $field (keys %{$node->{client}->{$service}}) 
    505         foreach my $field (&munin_get_field_order ($node, $config, $domain, $host, $service)) 
    506         { 
    507             print "DEBUG: single_value: Checking field \"$field\".\n" if $DEBUG; 
    508             if ($field =~ /^([^\.]+)\.label/ or $field =~ /=/) 
    509             { 
    510                 $graphable++ if &munin_draw_field ($node, $service, $1); 
    511             } 
    512         } 
    513         $node->{client}->{$service}->{"graphable"} = $graphable; 
    514     } 
    515     return 1 if ($node->{client}->{$service}->{"graphable"} == 1); 
    516      
    517     return 0; 
     412 
     413    my $graphable = munin_get ($service, "graphable", 0);; 
     414    if (!$graphable) { 
     415        foreach my $field (@{munin_get_field_order ($service)}) { 
     416            logger ("DEBUG: single_value: Checking field \"$field\"."); 
     417            $graphable++ if munin_draw_field ($service->{$field}); 
     418        } 
     419        munin_set_var_loc ($service, ["graphable"], $graphable); 
     420    } 
     421    logger ("Debug: service ". join (' :: ', @{munin_get_node_loc ($service)}) ." has $graphable elements."); 
     422    return ($graphable == 1); 
    518423} 
    519424 
     
    529434 
    530435sub process_field { 
    531     my $node    = shift; 
    532     my $service = shift; 
    533436    my $field   = shift; 
    534     return (&munin_get_bool_val ($node->{client}->{$service}->{$field.".process"}, 1)); 
    535 
    536  
    537 sub process_node { 
    538     my ($domain,$name,$node) = @_; 
    539  
    540     # See if we should skip it because of command-line arguments 
    541     return if (@limit_hosts and not grep (/^$name$/, @limit_hosts)); 
     437    return munin_get_bool ($field, "process", 1); 
     438
     439 
     440sub process_service { 
     441    my ($service) = @_; 
    542442 
    543443    # Make my graphs 
    544     logger ("Processing $name") if $DEBUG; 
    545     for my $service (keys %{$node->{client}}) { 
    546         my $service_time= Time::HiRes::time; 
    547         my $lastupdate = 0; 
    548         my $now  = time; 
    549         my $fnum = 0; 
    550         my @rrd; 
    551         my @added = (); 
    552  
    553         # See if we should skip the service 
    554         next if (&skip_service ($node, $service)); 
    555  
    556         my $field_count = 0; 
    557         my $max_field_len = 0; 
    558         my @field_order = (); 
    559         my $rrdname; 
    560         my $force_single_value; 
    561  
    562         # munin_set_context($node,$config,$domain,$name,$service); 
    563  
    564         @field_order =  
    565           @{&munin_get_field_order($node, $config, $domain, $name, 
    566                                    $service, \$force_single_value)}; 
    567  
    568         # Array to keep 'preprocess'ed fields. 
    569         my @rrd_preprocess = (); 
    570         print "DEBUG: Expanding specials \"", 
    571           join("\",\"", @field_order), "\".\n" 
    572             if $DEBUG; 
    573  
    574         @added =  
    575           @{&expand_specials ($node, $config, $domain, $name, 
    576                               $service, \@rrd_preprocess, \@field_order)}; 
    577  
    578         @field_order = (@rrd_preprocess, @field_order); 
    579         print "DEBUG: Checking field lengths \"", 
    580           join("\",\"", @rrd_preprocess), "\".\n" 
    581             if $DEBUG; 
    582  
    583         # Get max label length 
    584         $max_field_len = 
    585           &munin_get_max_label_length ($node, $config, $domain, $name, 
    586                                        $service, \@field_order); 
    587         # my $global_headers = ($max_field_len >= 16); 
    588         # Global headers makes the value tables easier to read no matter how 
    589         # wide the labels are. 
    590         my $global_headers = 1; 
    591  
    592         # Default format for printing under graph. 
    593         my $avgformat; 
    594         my $rrdformat=$avgformat="%6.2lf"; 
    595  
    596         if (exists $node->{client}->{$service}->{graph_args} and 
    597             $node->{client}->{$service}->{graph_args} =~ /--base\s+1024/) { 
    598             # If the base unit is 1024 then 1012.56 is a valid 
    599             # number to show.  That's 7 positions, not 6. 
    600             $rrdformat=$avgformat="%7.2lf"; 
    601         } 
    602  
    603         if (exists $node->{client}->{$service}->{graph_printf} ) { 
    604             # Plugin specified complete printf format 
    605             $rrdformat=$node->{client}->{$service}->{graph_printf}; 
    606         } 
    607  
    608         my $rrdscale = ''; 
    609         $rrdscale = '%s' 
    610           if munin_get_bool_val ($node->{client}->{$service}->{graph_scale},1); 
    611  
    612         # Array to keep negative data until we're finished with positive. 
    613         my @rrd_negatives = (); 
    614         my $filename = "unknown"; 
    615         my %total_pos; 
    616         my %total_neg; 
    617         my $autostacking=0; 
    618         print "DEBUG: Treating fields \"", join "\",\"", @field_order, "\".\n" if $DEBUG; 
    619         for my $field (@field_order) { 
    620             my $path  = undef; 
    621             if ($field =~ s/=(.+)//) { 
    622                 $path = $1; 
    623             } 
    624  
    625             next unless &process_field ($node, $service, $field); 
    626             print "DEBUG: Processing field \"$field\".\n" if $DEBUG; 
    627  
    628             my $fielddraw = munin_get ($config, "draw", "LINE2", $domain, 
    629                                        $name, $service, $field); 
    630  
    631             if ($field_count == 0 and $fielddraw eq 'STACK') { 
    632                 # Illegal -- first field is a STACK 
    633                 logger ("ERROR: First field (\"$field\") of graph \"$domain\"". 
    634                         ":: \"$name\" :: \"$service\" is STACK. STACK can ". 
    635                         "only be drawn after a LINEx or AREA."); 
    636                 $fielddraw = "LINE2"; 
    637             } 
    638  
    639             if ($fielddraw eq 'AREASTACK') { 
    640                 if ($autostacking==0) { 
    641                     $fielddraw='AREA'; 
    642                     $autostacking=1; 
    643                 } else { 
    644                     $fielddraw='STACK'; 
    645                 } 
    646             } 
    647  
    648             if ($fielddraw =~ /LINESTACK(\d+(?:.\d+)?)/ ) { 
    649                 if ($autostacking==0) { 
    650                     $fielddraw="LINE$1"; 
    651                     $autostacking=1; 
    652                 } else { 
    653                     $fielddraw='STACK'; 
    654                 } 
    655             } 
    656  
    657             # Getting name of rrd file 
    658             $filename = &munin_get_rrd_filename ($node, $config, $domain, 
    659                                                  $name, $service, $field, 
    660                                                  $path); 
    661  
    662             my $update = RRDs::last ($filename); 
    663             $update = 0 if ! defined $update; 
    664             if ($update > $lastupdate) { 
    665                 $lastupdate = $update; 
    666             } 
    667  
    668             # It does not look like $fieldname.rrdfield is possible to set 
    669             my $rrdfield = ($node->{client}->{$service}->{$field.".rrdfield"} 
    670                             || "42"); 
    671  
    672             my $single_value = $force_single_value || 
    673               &single_value ($node, $config, $domain, $name, 
    674                              $service, $field, \@field_order); 
    675  
    676             my $has_negative = 
    677               exists $node->{client}->{$service}->{$field.".negative"}; 
    678  
    679             # Trim the fieldname to make room for other field names. 
    680             $rrdname = &get_field_name ($field); 
    681             if ($rrdname ne $field) { 
    682                 # A change was made 
    683                 set_cdef_name ($node->{client}->{$service}, $field, $rrdname); 
    684             } 
    685  
    686             push (@rrd, "DEF:g$rrdname=" . 
    687                   $filename . ":" . $rrdfield . ":AVERAGE"); 
    688             push (@rrd, "DEF:i$rrdname=" . 
    689                   $filename . ":" . $rrdfield . ":MIN"); 
    690             push (@rrd, "DEF:a$rrdname=" . 
    691                   $filename . ":" . $rrdfield . ":MAX"); 
    692  
    693             if (exists $node->{client}->{$service}->{$field.".onlynullcdef"} 
    694                 and 
    695                 $node->{client}->{$service}->{$field.".onlynullcdef"}) { 
    696                 push (@rrd, "CDEF:c$rrdname=g$rrdname" . 
    697                       (($now-$update)>900 ? ",POP,UNKN" : "")); 
    698             } 
    699  
    700             if (($node->{client}->{$service}->{$field.".type"}||"GAUGE") 
    701                 ne "GAUGE" 
    702                 and graph_by_minute ($config, $domain, $name, $service)) { 
    703                 push (@rrd, &expand_cdef($node->{client}->{$service}, 
    704                                          \$rrdname, "$field,60,*")); 
    705             } 
    706  
    707             if ($node->{client}->{$service}->{$field.".cdef"}) { 
    708                 push (@rrd,&expand_cdef($node->{client}->{$service}, 
    709                                         \$rrdname, 
    710                                         $node->{client}->{$service}->{$field.".cdef"})); 
    711                 push (@rrd, "CDEF:c$rrdname=g$rrdname"); 
    712                 print "DEBUG: Field name after cdef set to $rrdname\n" if $DEBUG; 
    713             } elsif (!(exists $node->{client}->{$service}->{$field.".onlynullcdef"} 
    714                        and $node->{client}->{$service}->{$field.".onlynullcdef"})) { 
    715                 push (@rrd, "CDEF:c$rrdname=g$rrdname" . (($now-$update)>900 ? ",POP,UNKN" : "")); 
    716             } 
    717  
    718             next unless &munin_draw_field ($node, $service, $field); 
    719             print "DEBUG: Drawing field \"$field\".\n" if $DEBUG; 
     444    my $sname = munin_get_node_name ($service); 
     445    my $service_time= Time::HiRes::time; 
     446    my $lastupdate = 0; 
     447    my $now  = time; 
     448    my $fnum = 0; 
     449    my @rrd; 
     450    my @added = (); 
     451 
     452    # See if we should skip the service 
     453    next if (skip_service ($service)); 
     454 
     455    my $field_count = 0; 
     456    my $max_field_len = 0; 
     457    my @field_order = (); 
     458    my $rrdname; 
     459    my $force_single_value; 
     460 
     461    @field_order = @{munin_get_field_order($service)}; 
     462 
     463    # Array to keep 'preprocess'ed fields. 
     464    my @rrd_preprocess = (); 
     465    logger ("Debug: Expanding specials for $sname: \"" . join("\",\"", @field_order) . "\".") if $DEBUG; 
     466 
     467    @added = @{&expand_specials ($service, \@rrd_preprocess, \@field_order, \$force_single_value)}; 
     468 
     469    @field_order = (@rrd_preprocess, @field_order); 
     470    logger ("DEBUG: Checking field lengths for $sname: \"" . join("\",\"", @rrd_preprocess) . "\".") if $DEBUG; 
     471 
     472    # Get max label length 
     473    $max_field_len = &munin_get_max_label_length ($service, \@field_order); 
     474 
     475    # Global headers makes the value tables easier to read no matter how 
     476    # wide the labels are. 
     477    my $global_headers = 1; 
     478 
     479    # Default format for printing under graph. 
     480    my $avgformat; 
     481    my $rrdformat=$avgformat="%6.2lf"; 
     482 
     483    if (munin_get ($service, "graph_args", "") =~ /--base\s+1024/) { 
     484        # If the base unit is 1024 then 1012.56 is a valid 
     485        # number to show.  That's 7 positions, not 6. 
     486        $rrdformat=$avgformat="%7.2lf"; 
     487    } 
     488 
     489    # Plugin specified complete printf format 
     490    $rrdformat = munin_get ($service, "graph_printf", $rrdformat); 
     491 
     492    my $rrdscale = ''; 
     493    if (munin_get_bool ($service, "graph_scale", 1)) { 
     494        $rrdscale = '%s'; 
     495    } 
     496 
     497    # Array to keep negative data until we're finished with positive. 
     498    my @rrd_negatives = (); 
     499 
     500    my $filename = "unknown"; 
     501    my %total_pos; 
     502    my %total_neg; 
     503    my $autostacking=0; 
     504 
     505    logger ("DEBUG: Treating fields \"" . join ("\",\"", @field_order) . "\".") if $DEBUG; 
     506    for my $fname (@field_order) { 
     507        my $field = munin_get_node ($service, [$fname]); 
     508        my $path     = undef; 
     509 
     510        if ($fname =~ s/=(.+)//) { 
     511            $path = $1; 
     512        } 
     513 
     514        next if !process_field ($field); 
     515        logger ("DEBUG: Processing field \"$fname\".") if $DEBUG; 
     516 
     517        my $fielddraw = munin_get ($field, "draw", "LINE2"); 
     518 
     519        if ($field_count == 0 and $fielddraw eq 'STACK') { 
     520            # Illegal -- first field is a STACK 
     521            logger ("ERROR: First field (\"$fname\") of graph " . join (' :: ', munin_get_node_loc ($service)) . 
     522                    " is STACK. STACK can only be drawn after a LINEx or AREA."); 
     523            $fielddraw = "LINE2"; 
     524        } 
     525 
     526        if ($fielddraw eq 'AREASTACK') { 
     527            if ($autostacking==0) { 
     528                $fielddraw='AREA'; 
     529                $autostacking=1; 
     530            } else { 
     531                $fielddraw='STACK'; 
     532            } 
     533        } 
     534 
     535        if ($fielddraw =~ /LINESTACK(\d+(?:.\d+)?)/ ) { 
     536            if ($autostacking==0) { 
     537                $fielddraw="LINE$1"; 
     538                $autostacking=1; 
     539            } else { 
     540                $fielddraw='STACK'; 
     541            } 
     542        } 
     543 
     544        # Getting name of rrd file 
     545        $filename = munin_get_rrd_filename ($field, $path); 
     546 
     547        my $update = RRDs::last ($filename); 
     548        $update = 0 if ! defined $update; 
     549        if ($update > $lastupdate) { 
     550            $lastupdate = $update; 
     551        } 
     552 
     553        # It does not look like $fieldname.rrdfield is possible to set 
     554        my $rrdfield = munin_get ($field, "rrdfield", "42"); 
     555 
     556        my $single_value = $force_single_value || single_value ($service); 
     557 
     558        my $has_negative = munin_get ($field, "negative"); 
     559 
     560        # Trim the fieldname to make room for other field names. 
     561        $rrdname = &get_field_name ($fname); 
     562        if ($rrdname ne $fname) { 
     563            # A change was made 
     564            munin_set_var ($field, "cdef_name", $rrdname); 
     565        } 
     566 
     567        push (@rrd, "DEF:g$rrdname=" . 
     568              $filename . ":" . $rrdfield . ":AVERAGE"); 
     569        push (@rrd, "DEF:i$rrdname=" . 
     570              $filename . ":" . $rrdfield . ":MIN"); 
     571        push (@rrd, "DEF:a$rrdname=" . 
     572              $filename . ":" . $rrdfield . ":MAX"); 
     573 
     574        if (munin_get_bool ($field, "onlynullcdef", 0)) {  
     575            push (@rrd, "CDEF:c$rrdname=g$rrdname" . (($now-$update)>900 ? ",POP,UNKN" : "")); 
     576        } 
     577 
     578        if (munin_get ($field, "type", "GAUGE") ne "GAUGE" and graph_by_minute ($service)) { 
     579                push (@rrd, expand_cdef($service, \$rrdname, "$fname,60,*")); 
     580        } 
     581 
     582        if (my $tmpcdef = munin_get ($field, "cdef")) { 
     583            push (@rrd,expand_cdef($service, \$rrdname, $tmpcdef)); 
     584            push (@rrd, "CDEF:c$rrdname=g$rrdname"); 
     585            logger ("DEBUG: Field name after cdef set to $rrdname") if $DEBUG; 
     586        } elsif (!munin_get_bool ($field, "onlynullcdef", 0)) { 
     587            push (@rrd, "CDEF:c$rrdname=g$rrdname" . (($now-$update)>900 ? ",POP,UNKN" : "")); 
     588        } 
     589 
     590        next if !munin_draw_field ($field); 
     591        logger ("DEBUG: Drawing field \"$fname\".") if $DEBUG; 
     592 
     593        if ($single_value) { 
     594            # Only one field. Do min/max range.  
     595            push (@rrd, "CDEF:min_max_diff=a$rrdname,i$rrdname,-"); 
     596            push (@rrd, "CDEF:re_zero=min_max_diff,min_max_diff,-") if !munin_get ($field, "negative"); 
     597            push (@rrd, "AREA:i$rrdname#ffffff"); 
     598            push (@rrd, "STACK:min_max_diff$range_colour"); 
     599            push (@rrd, "LINE2:re_zero#000000") if !munin_get ($field, "negative"); 
     600        } 
     601 
     602        if ($has_negative and !@rrd_negatives) { # Push "global" headers... 
     603            push (@rrd, "COMMENT:" . (" " x $max_field_len)); 
     604            push (@rrd, "COMMENT:Cur (-/+)"); 
     605            push (@rrd, "COMMENT:Min (-/+)"); 
     606            push (@rrd, "COMMENT:Avg (-/+)"); 
     607            push (@rrd, "COMMENT:Max (-/+) \\j"); 
     608        } elsif ($global_headers == 1) { 
     609            push (@rrd, "COMMENT:" . (" " x $max_field_len)); 
     610            push (@rrd, "COMMENT: Cur$RRDkludge:"); 
     611            push (@rrd, "COMMENT:Min$RRDkludge:"); 
     612            push (@rrd, "COMMENT:Avg$RRDkludge:"); 
     613            push (@rrd, "COMMENT:Max$RRDkludge:  \\j"); 
     614            $global_headers++; 
     615        } 
     616 
     617        my $colour; 
     618 
     619        if (my $tmpcol = munin_get ($field, "colour")) { 
     620            $colour = "#" . $tmpcol; 
     621        } elsif ($single_value) { 
     622            $colour = $single_colour; 
     623        } else { 
     624            $colour = $COLOUR[$field_count%@COLOUR]; 
     625        } 
     626 
     627        $field_count++; 
     628 
     629        my $tmplabel = munin_get ($field, "label", $fname); 
     630 
     631        push (@rrd, $fielddraw . ":g$rrdname" . $colour . ":" . 
     632            escape ($tmplabel) . (" " x ($max_field_len + 1 - length $tmplabel))); 
     633 
     634        # Check for negative fields (typically network (or disk) traffic) 
     635        if ($has_negative) { 
     636            my $negfieldname = orig_to_cdef ($service, munin_get ($field, "negative")); 
     637            my $negfield     = $service->{$negfieldname}; 
     638            if (my $tmpneg = munin_get ($negfield, "realname")) { 
     639                $negfieldname = $tmpneg; 
     640                $negfield     = $service->{$negfieldname}; 
     641            } 
     642             
     643            if (!@rrd_negatives) { 
     644                # zero-line, to redraw zero afterwards. 
     645                push (@rrd_negatives, "CDEF:re_zero=g$negfieldname,UN,0,0,IF"); 
     646            } 
     647 
     648            push (@rrd_negatives, "CDEF:ng$negfieldname=g$negfieldname,-1,*"); 
    720649 
    721650            if ($single_value) { 
    722651                # Only one field. Do min/max range.      
    723                 push (@rrd, "CDEF:min_max_diff=a$rrdname,i$rrdname,-"); 
    724                 push (@rrd, "CDEF:re_zero=min_max_diff,min_max_diff,-")  
    725                     unless ($node->{client}->{$service}->{$field.".negative"}); 
    726                 push (@rrd, "AREA:i$rrdname#ffffff"); 
    727                 push (@rrd, "STACK:min_max_diff$range_colour"); 
    728                 push (@rrd, "LINE2:re_zero#000000") 
    729                     unless ($node->{client}->{$service}->{$field.".negative"}); 
    730             } 
    731  
    732             if ($has_negative and !@rrd_negatives) { # Push "global" headers... 
    733                 push (@rrd, "COMMENT:" . (" " x $max_field_len)); 
    734                 push (@rrd, "COMMENT:Cur (-/+)"); 
    735                 push (@rrd, "COMMENT:Min (-/+)"); 
    736                 push (@rrd, "COMMENT:Avg (-/+)"); 
    737                 push (@rrd, "COMMENT:Max (-/+) \\j"); 
    738             } elsif ($global_headers == 1) { 
    739                 push (@rrd, "COMMENT:" . (" " x $max_field_len)); 
    740                 push (@rrd, "COMMENT: Cur$RRDkludge:"); 
    741                 push (@rrd, "COMMENT:Min$RRDkludge:"); 
    742                 push (@rrd, "COMMENT:Avg$RRDkludge:"); 
    743                 push (@rrd, "COMMENT:Max$RRDkludge:  \\j"); 
    744                 $global_headers++; 
    745             } 
    746  
    747             my $colour; 
    748  
    749             if (exists $node->{client}->{$service}->{$field.".colour"}) { 
    750                 $colour = "#". 
    751                   $node->{client}->{$service}->{$field.".colour"}; 
    752             } elsif ($single_value) { 
    753                 $colour = $single_colour; 
    754             } else { 
    755                 $colour = $COLOUR[$field_count%@COLOUR]; 
    756             } 
    757  
    758             $field_count++; 
    759  
    760             push (@rrd, $fielddraw . ":g$rrdname" . $colour . ":" . 
    761                   (escape ($node->{client}->{$service}->{"$field.label"}) || escape ($field)) 
    762                   . (" " x ($max_field_len + 1 - 
    763                             length ($node->{client}->{$service}->{"$field.label"} || $field)))); 
    764  
    765             # Check for negative fields (typically network (or disk) traffic) 
    766             if ($has_negative) { 
    767                 my $negfield = &orig_to_cdef ($node->{client}->{$service}, $node->{client}->{$service}->{$field.".negative"}); 
    768                 print "DEBUG: negfield = $negfield\n" if $DEBUG; 
    769                 if (exists $node->{client}->{$service}->{$negfield.".realname"}) { 
    770                     $negfield = $node->{client}->{$service}->{$negfield.".realname"}; 
    771                 } 
    772                  
    773                 if (!@rrd_negatives) { 
    774                     # zero-line, to redraw zero afterwards. 
    775                     push (@rrd_negatives, "CDEF:re_zero=g$negfield,UN,0,0,IF"); 
    776                 } 
    777  
    778                 push (@rrd_negatives, "CDEF:ng$negfield=g$negfield,-1,*"); 
    779  
    780                 if ($single_value) { 
    781                     # Only one field. Do min/max range.  
    782                     push (@rrd, "CDEF:neg_min_max_diff=i$negfield,a$negfield,-"); 
    783                     push (@rrd, "CDEF:ni$negfield=i$negfield,-1,*"); 
    784                     push (@rrd, "AREA:ni$negfield#ffffff"); 
    785                     push (@rrd, "STACK:neg_min_max_diff$range_colour"); 
    786                 } 
    787  
    788                 push (@rrd_negatives, $fielddraw . ":ng$negfield" . $colour ); 
    789  
    790                 # Draw HRULEs 
    791                 my $linedef = munin_get ($config, "line", undef, $domain, $name, $service, $node->{client}->{$service}->{$field.".negative"}); 
    792                 if ($linedef) { 
    793                     my ($number, $ldcolour, $label) = split (/:/, $linedef, 3); 
    794                     push (@rrd_negatives, "HRULE:".$number. 
    795                         ($ldcolour ? "#$ldcolour" : $colour)); 
    796  
    797                 } elsif ($node->{client}->{$service}->{"$negfield.warn"}) { 
    798                     push (@rrd_negatives, "HRULE:".$node->{client}->{$service}->{$node->{client}->{$service}->{$field.".negative"}.".warn"}. 
    799                           (defined $single_value and $single_value) ? "#ff0000" : $colour); 
    800                 } 
    801  
    802                 push (@rrd, "GPRINT:c$negfield:LAST:$rrdformat" . $rrdscale . "/\\g"); 
    803                 push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 
    804                 push (@rrd, "GPRINT:i$negfield:MIN:$rrdformat" . $rrdscale . "/\\g"); 
    805                 push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 
    806                 push (@rrd, "GPRINT:g$negfield:AVERAGE:$avgformat" . $rrdscale . "/\\g"); 
    807                 push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 
    808                 push (@rrd, "GPRINT:a$negfield:MAX:$rrdformat" . $rrdscale . "/\\g"); 
    809                 push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 
    810                 push (@{$total_pos{'min'}}, "i$rrdname"); 
    811                 push (@{$total_pos{'avg'}}, "g$rrdname"); 
    812                 push (@{$total_pos{'max'}}, "a$rrdname"); 
    813                 push (@{$total_neg{'min'}}, "i$negfield"); 
    814                 push (@{$total_neg{'avg'}}, "g$negfield"); 
    815                 push (@{$total_neg{'max'}}, "a$negfield"); 
    816             } else { 
    817                 push (@rrd, "COMMENT: Cur$RRDkludge:") unless $global_headers; 
    818                 push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 
    819                 push (@rrd, "COMMENT: Min$RRDkludge:") unless $global_headers; 
    820                 push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 
    821                 push (@rrd, "COMMENT: Avg$RRDkludge:") unless $global_headers; 
    822                 push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 
    823                 push (@rrd, "COMMENT: Max$RRDkludge:") unless $global_headers; 
    824                 push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 
    825                 push (@{$total_pos{'min'}}, "i$rrdname"); 
    826                 push (@{$total_pos{'avg'}}, "g$rrdname"); 
    827                 push (@{$total_pos{'max'}}, "a$rrdname"); 
    828             } 
     652                push (@rrd, "CDEF:neg_min_max_diff=i$negfieldname,a$negfieldname,-"); 
     653                push (@rrd, "CDEF:ni$negfieldname=i$negfieldname,-1,*"); 
     654                push (@rrd, "AREA:ni$negfieldname#ffffff"); 
     655                push (@rrd, "STACK:neg_min_max_diff$range_colour"); 
     656            } 
     657 
     658            push (@rrd_negatives, $fielddraw . ":ng$negfieldname" . $colour ); 
    829659 
    830660            # Draw HRULEs 
    831             my $linedef = munin_get ($config, "line", undef, $domain, $name, $service, $field); 
     661            my $linedef = munin_get ($negfield, "line"); 
    832662            if ($linedef) { 
    833663                my ($number, $ldcolour, $label) = split (/:/, $linedef, 3); 
    834                 $label =~ s/:/\\:/g if defined $label; 
    835                 push (@rrd, "HRULE:".$number. 
    836                     ($ldcolour ? "#$ldcolour" : 
    837                       ((defined $single_value and $single_value) ? 
    838                        "#ff0000" : $colour)). 
    839                       ((defined $label and length ($label)) ? ":$label" : ""), 
    840                       "COMMENT: \\j" 
    841                     ); 
    842             } elsif ($node->{client}->{$service}->{"$field.warn"}) { 
    843                 push (@rrd,"HRULE:". 
    844                       $node->{client}->{$service}->{"$field.warn"}. 
    845                       ($single_value ? "#ff0000" : $colour)); 
    846             } 
    847         } 
    848  
    849         if (@rrd_negatives) { 
    850             push (@rrd, @rrd_negatives); 
    851             push (@rrd, "LINE2:re_zero#000000"); # Redraw zero. 
    852             if (exists $node->{client}->{$service}->{graph_total} and 
    853                 exists $total_pos{'min'} and exists $total_neg{'min'} and 
    854                 @{$total_pos{'min'}} and @{$total_neg{'min'}}) { 
    855  
    856                 push (@rrd, "CDEF:ipostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'min'}}).(",+" x (@{$total_pos{'min'}}-1))); 
    857                 push (@rrd, "CDEF:gpostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'avg'}}).(",+" x (@{$total_pos{'avg'}}-1))); 
    858                 push (@rrd, "CDEF:apostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'max'}}).(",+" x (@{$total_pos{'max'}}-1))); 
    859                 push (@rrd, "CDEF:inegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'min'}}).(",+" x (@{$total_neg{'min'}}-1))); 
    860                 push (@rrd, "CDEF:gnegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'avg'}}).(",+" x (@{$total_neg{'avg'}}-1))); 
    861                 push (@rrd, "CDEF:anegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'max'}}).(",+" x (@{$total_neg{'max'}}-1))); 
    862                 push (@rrd, "CDEF:dpostotal=ipostotal,UN,ipostotal,UNKN,IF"); 
    863                 push (@rrd, "LINE1:dpostotal#000000:" . $node->{client}->{$service}->{graph_total} . (" " x ($max_field_len - length ($node->{client}->{$service}->{graph_total}) + 1))); 
    864                 push (@rrd, "GPRINT:gnegtotal:LAST:$rrdformat" . $rrdscale . "/\\g"); 
    865                 push (@rrd, "GPRINT:gpostotal:LAST:$rrdformat" . $rrdscale . ""); 
    866                 push (@rrd, "GPRINT:inegtotal:MIN:$rrdformat" . $rrdscale . "/\\g"); 
    867                 push (@rrd, "GPRINT:ipostotal:MIN:$rrdformat" . $rrdscale . ""); 
    868                 push (@rrd, "GPRINT:gnegtotal:AVERAGE:$avgformat" . $rrdscale . "/\\g"); 
    869                 push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale . ""); 
    870                 push (@rrd, "GPRINT:anegtotal:MAX:$rrdformat" . $rrdscale . "/\\g"); 
    871                 push (@rrd, "GPRINT:apostotal:MAX:$rrdformat" . $rrdscale . "\\j"); 
    872             } 
    873         } 
    874         elsif (exists $node->{client}->{$service}->{graph_total} and exists $total_pos{'min'} and @{$total_pos{'min'}}) { 
     664                push (@rrd_negatives, "HRULE:".$number. 
     665                    ($ldcolour ? "#$ldcolour" : $colour)); 
     666 
     667            } elsif (my $tmpwarn = munin_get ($negfield, "warn")) { 
     668                push (@rrd_negatives, "HRULE:".$negfieldname. 
     669                    (defined $single_value and $single_value) ? "#ff0000" : $colour); 
     670            } 
     671 
     672            push (@rrd, "GPRINT:c$negfieldname:LAST:$rrdformat" . $rrdscale . "/\\g"); 
     673            push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 
     674            push (@rrd, "GPRINT:i$negfieldname:MIN:$rrdformat" . $rrdscale . "/\\g"); 
     675            push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 
     676            push (@rrd, "GPRINT:g$negfieldname:AVERAGE:$avgformat" . $rrdscale . "/\\g"); 
     677            push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 
     678            push (@rrd, "GPRINT:a$negfieldname:MAX:$rrdformat" . $rrdscale . "/\\g"); 
     679            push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 
     680            push (@{$total_pos{'min'}}, "i$rrdname"); 
     681            push (@{$total_pos{'avg'}}, "g$rrdname"); 
     682            push (@{$total_pos{'max'}}, "a$rrdname"); 
     683            push (@{$total_neg{'min'}}, "i$negfieldname"); 
     684            push (@{$total_neg{'avg'}}, "g$negfieldname"); 
     685            push (@{$total_neg{'max'}}, "a$negfieldname"); 
     686        } else { 
     687            push (@rrd, "COMMENT: Cur$RRDkludge:") unless $global_headers; 
     688            push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 
     689            push (@rrd, "COMMENT: Min$RRDkludge:") unless $global_headers; 
     690            push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 
     691            push (@rrd, "COMMENT: Avg$RRDkludge:") unless $global_headers; 
     692            push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 
     693            push (@rrd, "COMMENT: Max$RRDkludge:") unless $global_headers; 
     694            push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 
     695            push (@{$total_pos{'min'}}, "i$rrdname"); 
     696            push (@{$total_pos{'avg'}}, "g$rrdname"); 
     697            push (@{$total_pos{'max'}}, "a$rrdname"); 
     698        } 
     699 
     700        # Draw HRULEs 
     701        my $linedef = munin_get ($field, "line"); 
     702        if ($linedef) { 
     703            my ($number, $ldcolour, $label) = split (/:/, $linedef, 3); 
     704            $label =~ s/:/\\:/g if defined $label; 
     705            push (@rrd, "HRULE:".$number. 
     706                ($ldcolour ? "#$ldcolour" : 
     707                  ((defined $single_value and $single_value) ? 
     708                   "#ff0000" : $colour)). 
     709                  ((defined $label and length ($label)) ? ":$label" : ""), 
     710                  "COMMENT: \\j" 
     711                ); 
     712        } elsif (my $tmpwarn = munin_get ($field, "warn")) { 
     713            push (@rrd,"HRULE:".$tmpwarn.($single_value ? "#ff0000" : $colour)); 
     714        } 
     715    } 
     716 
     717    my $graphtotal = munin_get ($service, "graph_total"); 
     718    if (@rrd_negatives) { 
     719        push (@rrd, @rrd_negatives); 
     720        push (@rrd, "LINE2:re_zero#000000"); # Redraw zero. 
     721        if (defined $graphtotal and exists $total_pos{'min'} and  
     722            exists $total_neg{'min'} and 
     723            @{$total_pos{'min'}} and @{$total_neg{'min'}}) { 
     724 
    875725            push (@rrd, "CDEF:ipostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'min'}}).(",+" x (@{$total_pos{'min'}}-1))); 
    876726            push (@rrd, "CDEF:gpostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'avg'}}).(",+" x (@{$total_pos{'avg'}}-1))); 
    877727            push (@rrd, "CDEF:apostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'max'}}).(",+" x (@{$total_pos{'max'}}-1))); 
    878  
     728            push (@rrd, "CDEF:inegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'min'}}).(",+" x (@{$total_neg{'min'}}-1))); 
     729            push (@rrd, "CDEF:gnegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'avg'}}).(",+" x (@{$total_neg{'avg'}}-1))); 
     730            push (@rrd, "CDEF:anegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'max'}}).(",+" x (@{$total_neg{'max'}}-1))); 
    879731            push (@rrd, "CDEF:dpostotal=ipostotal,UN,ipostotal,UNKN,IF"); 
    880             push (@rrd, "LINE1:dpostotal#000000:" . $node->{client}->{$service}->{graph_total} . (" " x ($max_field_len - length ($node->{client}->{$service}->{graph_total}) + 1))); 
    881             push (@rrd, "COMMENT: Cur$RRDkludge:") unless $global_headers
     732            push (@rrd, "LINE1:dpostotal#000000:$graphtotal" . (" " x ($max_field_len - length ($graphtotal) + 1))); 
     733            push (@rrd, "GPRINT:gnegtotal:LAST:$rrdformat" . $rrdscale . "/\\g")
    882734            push (@rrd, "GPRINT:gpostotal:LAST:$rrdformat" . $rrdscale . ""); 
    883             push (@rrd, "COMMENT: Min$RRDkludge:") unless $global_headers
     735            push (@rrd, "GPRINT:inegtotal:MIN:$rrdformat" . $rrdscale . "/\\g")
    884736            push (@rrd, "GPRINT:ipostotal:MIN:$rrdformat" . $rrdscale . ""); 
    885             push (@rrd, "COMMENT: Avg$RRDkludge:") unless $global_headers
    886             push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale .""); 
    887             push (@rrd, "COMMENT: Max$RRDkludge:") unless $global_headers
     737            push (@rrd, "GPRINT:gnegtotal:AVERAGE:$avgformat" . $rrdscale . "/\\g")
     738            push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale . ""); 
     739            push (@rrd, "GPRINT:anegtotal:MAX:$rrdformat" . $rrdscale . "/\\g")
    888740            push (@rrd, "GPRINT:apostotal:MAX:$rrdformat" . $rrdscale . "\\j"); 
    889741        } 
    890  
    891         for my $time (keys %times) { 
    892             next unless ($draw{$time}); 
    893             my @complete = (); 
    894             if ($RRDkludge) { 
    895                 push (@complete, 
    896                       '--font' ,'LEGEND:7:@@LIBDIR@@/VeraMono.ttf', 
    897                       '--font' ,'UNIT:7:@@LIBDIR@@/VeraMono.ttf', 
    898                       '--font' ,'AXIS:7:@@LIBDIR@@/VeraMono.ttf'); 
    899             } 
    900  
    901             logger ("Processing $name -> $time") if $DEBUG; 
    902  
    903             # Do the header (title, vtitle, size, etc...) 
    904             push @complete, @{&get_header ($node, $config, $domain, $name, $service, $time)}; 
    905             if ($LINEkluge) { 
    906                 @rrd = map { s/LINE3:/LINE2.2:/; $_; } @rrd; 
    907                 @rrd = map { s/LINE2:/LINE1.6:/; $_; } @rrd; 
    908                 # LINE1 is thin enough. 
    909             } 
    910             push @complete, @rrd; 
    911  
    912             push (@complete, "COMMENT:Last update$RRDkludge: " .  
    913                   RRDescape(scalar localtime($lastupdate)) .  "\\r"); 
     742    } elsif (defined $graphtotal and exists $total_pos{'min'} and @{$total_pos{'min'}}) { 
     743        push (@rrd, "CDEF:ipostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'min'}}).(",+" x (@{$total_pos{'min'}}-1))); 
     744        push (@rrd, "CDEF:gpostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'avg'}}).(",+" x (@{$total_pos{'avg'}}-1))); 
     745        push (@rrd, "CDEF:apostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'max'}}).(",+" x (@{$total_pos{'max'}}-1))); 
     746 
     747        push (@rrd, "CDEF:dpostotal=ipostotal,UN,ipostotal,UNKN,IF"); 
     748        push (@rrd, "LINE1:dpostotal#000000:$graphtotal" . (" " x ($max_field_len - length ($graphtotal) + 1))); 
     749        push (@rrd, "COMMENT: Cur$RRDkludge:") unless $global_headers; 
     750        push (@rrd, "GPRINT:gpostotal:LAST:$rrdformat" . $rrdscale . ""); 
     751        push (@rrd, "COMMENT: Min$RRDkludge:") unless $global_headers; 
     752        push (@rrd, "GPRINT:ipostotal:MIN:$rrdformat" . $rrdscale . ""); 
     753        push (@rrd, "COMMENT: Avg$RRDkludge:") unless $global_headers; 
     754        push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale .""); 
     755        push (@rrd, "COMMENT: Max$RRDkludge:") unless $global_headers; 
     756        push (@rrd, "GPRINT:apostotal:MAX:$rrdformat" . $rrdscale . "\\j"); 
     757    } 
     758 
     759    for my $time (keys %times) { 
     760        next unless ($draw{$time}); 
     761        my $picfilename = munin_get_picture_filename ($service, $time); 
     762        (my $picdirname = $picfilename) =~ s/\/[^\/]+$//; 
     763 
     764        my @complete = (); 
     765        if ($RRDkludge) { 
     766            push (@complete, 
     767                  '--font' ,'LEGEND:7:@@LIBDIR@@/VeraMono.ttf', 
     768                  '--font' ,'UNIT:7:@@LIBDIR@@/VeraMono.ttf', 
     769                  '--font' ,'AXIS:7:@@LIBDIR@@/VeraMono.ttf'); 
     770        } 
     771 
     772        # Do the header (title, vtitle, size, etc...) 
     773        push @complete, @{get_header ($service, $time)}; 
     774        if ($LINEkluge) { 
     775            @rrd = map { s/LINE3:/LINE2.2:/; $_; } @rrd; 
     776            @rrd = map { s/LINE2:/LINE1.6:/; $_; } @rrd; 
     777            # LINE1 is thin enough. 
     778        } 
     779        push @complete, @rrd; 
     780 
     781        push (@complete, "COMMENT:Last update$RRDkludge: " .  
     782              RRDescape(scalar localtime($lastupdate)) .  "\\r"); 
     783 
     784        if (time - 300 < $lastupdate) { 
     785            push @complete, "--end", 
     786              (int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 
     787        } 
     788        print "\n\nrrdtool \"graph\" \"", 
     789          join ("\"\n\t\"",@complete), "\"\n" if $DEBUG; 
     790 
     791        # Make sure directory exists 
     792        munin_mkdir_p ($picdirname, 0777); 
     793 
     794        RRDs::graph (@complete); 
     795        if (my $ERROR = RRDs::error) { 
     796            logger ("Unable to graph $filename: $ERROR"); 
     797        } elsif ($list_images) { 
     798            # Command-line option to list images created 
     799            print munin_get_picture_filename ($service, $time),"\n"; 
     800        } 
     801    } 
     802 
     803    if (munin_get_bool ($service, "graph_sums", 0)) { 
     804        foreach my $time (keys %sumtimes) { 
     805            my $picfilename = munin_get_picture_filename ($service, $time, 1); 
     806            (my $picdirname = $picfilename) =~ s/\/[^\/]+$//; 
     807            next unless ($draw{"sum".$time}); 
     808            my @rrd_sum; 
     809            push @rrd_sum, @{get_header ($service, $time, 1)}; 
    914810 
    915811            if (time - 300 < $lastupdate) { 
    916                 push @complete, "--end", 
    917                   (int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 
    918             } 
    919             print "\n\nrrdtool \"graph\" \"", 
    920               join ("\"\n\t\"",@complete), "\"\n" if $DEBUG; 
    921             RRDs::graph (@complete); 
     812                push @rrd_sum, "--end",(int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 
     813            } 
     814            push @rrd_sum, @rrd; 
     815            push (@rrd_sum, "COMMENT:Last update$RRDkludge: " . RRDescape(scalar localtime($lastupdate)) .  "\\r"); 
     816 
     817            my $labelled = 0; 
     818            my @defined = (); 
     819            for (my $index = 0; $index <= $#rrd_sum; $index++) { 
     820                if ($rrd_sum[$index] =~ /^(--vertical-label|-v)$/) { 
     821                    (my $label = munin_get ($service, "graph_vlabel")) =~ s/\$\{graph_period\}/$sumtimes{$time}[0]/g; 
     822                    splice (@rrd_sum, $index, 2, ("--vertical-label", $label)); 
     823                    $index++; 
     824                    $labelled++; 
     825                } elsif ($rrd_sum[$index] =~ /^(LINE[123]|STACK|AREA|GPRINT):([^#:]+)([#:].+)$/) { 
     826                    my ($pre, $fname, $post) = ($1, $2, $3); 
     827                    next if $fname eq "re_zero"; 
     828                    if ($post =~ /^:AVERAGE/) { 
     829                        splice (@rrd_sum, $index, 1, $pre . ":x$fname" . $post); 
     830                        $index++; 
     831                        next; 
     832                    } 
     833                    next if grep /^x$fname$/, @defined; 
     834                    push @defined, "x$fname"; 
     835                    my @replace; 
     836 
     837                    if (munin_get ($service->{$fname}, "type", "GAUGE") ne "GAUGE") { 
     838                        if ($time eq "week") { 
     839                            # Every plot is half an hour. Add two plots and multiply, to get per hour 
     840                            if (graph_by_minute ($service)) { 
     841                                # Already multiplied by 60 
     842                                push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,5,*,6,*"; 
     843                            } else { 
     844                                push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,300,*,6,*"; 
     845                            } 
     846                        } else { 
     847                            # Every plot is one day exactly. Just multiply. 
     848                            if (graph_by_minute ($service)) { 
     849                                # Already multiplied by 60 
     850                                push @replace, "CDEF:x$fname=$fname,5,*,288,*"; 
     851                            } else { 
     852                                push @replace, "CDEF:x$fname=$fname,300,*,288,*"; 
     853                            } 
     854                        } 
     855                    } 
     856                    push @replace, $pre . ":x$fname" . $post; 
     857                    splice (@rrd_sum, $index, 1, @replace); 
     858                    $index++; 
     859                } elsif ($rrd_sum[$index] =~ /^(--lower-limit|--upper-limit|-l|-u)$/) { 
     860                    $index++; 
     861                    $rrd_sum[$index] = $rrd_sum[$index] * 300 * $sumtimes{$time}->[1]; 
     862                } 
     863            } 
     864 
     865            unless ($labelled) { 
     866                my $label = munin_get ($service, "graph_vlabel_sum_$time", $sumtimes{$time}->[0]); 
     867                unshift @rrd_sum, "--vertical-label", $label; 
     868            } 
     869 
     870            print "\n\nrrdtool \"graph\" \"", join ("\"\n\t\"",@rrd_sum), "\"\n" if $DEBUG; 
     871 
     872            # Make sure directory exists 
     873            munin_mkdir_p ($picdirname, 0777); 
     874 
     875            RRDs::graph (@rrd_sum); 
     876 
    922877            if (my $ERROR = RRDs::error) { 
    923878                logger ("Unable to graph $filename: $ERROR"); 
    924879            } elsif ($list_images) { 
    925880                # Command-line option to list images created 
    926                 print &munin_get_picture_filename ($config, $domain, $name, 
    927                                                    $service, $time),"\n"; 
    928             } 
    929         } 
    930  
    931         if (&munin_get_bool_val ($node->{client}->{$service}->{"graph_sums"}, 0)) { 
    932             foreach my $time (keys %sumtimes) { 
    933                 next unless ($draw{"sum".$time}); 
    934                 my @rrd_sum; 
    935                 push @rrd_sum, @{&get_header ($node, $config, $domain, $name, $service, $time, 1)}; 
    936  
    937                 if (time - 300 < $lastupdate) { 
    938                     push @rrd_sum, "--end",(int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 
    939                 } 
    940                 push @rrd_sum, @rrd; 
    941                 push (@rrd_sum, "COMMENT:Last update$RRDkludge: " . RRDescape(scalar localtime($lastupdate)) .  "\\r"); 
    942  
    943                 my $labelled = 0; 
    944                 my @defined = (); 
    945                 for (my $index = 0; $index <= $#rrd_sum; $index++) { 
    946                     if ($rrd_sum[$index] =~ /^(--vertical-label|-v)$/) { 
    947                         (my $label = $node->{client}->{$service}->{graph_vlabel}) =~ s/\$\{graph_period\}/$sumtimes{$time}[0]/g; 
    948                         splice (@rrd_sum, $index, 2, ("--vertical-label", $label)); 
    949                         $index++; 
    950                         $labelled++; 
    951                     } elsif ($rrd_sum[$index] =~ /^(LINE[123]|STACK|AREA|GPRINT):([^#:]+)([#:].+)$/) { 
    952                         my ($pre, $fname, $post) = ($1, $2, $3); 
    953                         next if $fname eq "re_zero"; 
    954                         if ($post =~ /^:AVERAGE/) { 
    955                             splice (@rrd_sum, $index, 1, $pre . ":x$fname" . $post); 
    956                             $index++; 
    957                             next; 
    958                         } 
    959                         next if grep /^x$fname$/, @defined; 
    960                         push @defined, "x$fname"; 
    961                         my @replace; 
    962  
    963                         if (!defined ($node->{client}->{$service}->{$fname.".type"}) or 
    964                             $node->{client}->{$service}->{$fname.".type"} ne "GAUGE") { 
    965                             if ($time eq "week") { 
    966                                 # Every plot is half an hour. Add two plots and multiply, to get per hour 
    967                                 if (graph_by_minute ($config, $domain, $name, $service)) { 
    968                                     # Already multiplied by 60 
    969                                     push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,5,*,6,*"; 
    970                                 } else { 
    971                                     push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,300,*,6,*"; 
    972                                 } 
    973                             } else { 
    974                                 # Every plot is one day exactly. Just multiply. 
    975                                 if (graph_by_minute ($config, $domain, $name, $service)) { 
    976                                     # Already multiplied by 60 
    977                                     push @replace, "CDEF:x$fname=$fname,5,*,288,*"; 
    978                                 } else { 
    979                                     push @replace, "CDEF:x$fname=$fname,300,*,288,*"; 
    980                                 } 
    981                             } 
    982                         } 
    983                         push @replace, $pre . ":x$fname" . $post; 
    984                         splice (@rrd_sum, $index, 1, @replace); 
    985                         $index++; 
    986                     } elsif ($rrd_sum[$index] =~ /^(--lower-limit|--upper-limit|-l|-u)$/) { 
    987                         $index++; 
    988                         $rrd_sum[$index] = $rrd_sum[$index] * 300 * $sumtimes{$time}->[1]; 
    989                     } 
    990                 } 
    991  
    992                 unless ($labelled) { 
    993                     my $label = $node->{client}->{$service}->{"graph_vlabel_sum_$time"} || $sumtimes{$time}->[0]; 
    994                     unshift @rrd_sum, "--vertical-label", $label; 
    995                 } 
    996  
    997                 print "\n\nrrdtool \"graph\" \"", join ("\"\n\t\"",@rrd_sum), "\"\n" if $DEBUG; 
    998                 RRDs::graph (@rrd_sum); 
    999  
    1000                 if (my $ERROR = RRDs::error) { 
    1001                     logger ("Unable to graph $filename: $ERROR"); 
    1002                 } elsif ($list_images) { 
    1003                     # Command-line option to list images created 
    1004                     print &munin_get_picture_filename ($config, $domain, $name, $service, $time, 1), "\n"; 
    1005                 } 
    1006             } 
    1007         } 
    1008  
    1009         $service_time = sprintf ("%.2f",(Time::HiRes::time - $service_time)); 
    1010         logger ("Graphed service : $service ($service_time sec * 4)"); 
    1011         print STATS "GS|$domain|$name|$service|$service_time\n" unless $skip_stats; 
    1012  
    1013         foreach (@added) { 
    1014             delete $node->{client}->{$service}->{$_} 
    1015               if exists $node->{client}->{$service}->{$_}; 
    1016         } 
    1017         @added = (); 
    1018     } 
     881                print munin_get_picture_filename ($service, $time, 1),"\n"; 
     882            } 
     883        } 
     884    } 
     885 
     886    $service_time = sprintf ("%.2f",(Time::HiRes::time - $service_time)); 
     887    logger ("Graphed service : $sname ($service_time sec * 4)"); 
     888    print STATS "GS|$service_time\n" unless $skip_stats; 
     889 
     890    foreach (@added) { 
     891        delete $service->{$_} if exists $service->{$_}; 
     892    } 
     893    @added = (); 
    1019894} 
    1020895 
    1021896sub graph_by_minute { 
    1022     my $config  = shift; 
    1023     my $domain  = shift; 
    1024     my $name    = shift; 
    1025897    my $service = shift; 
    1026898 
    1027     return (munin_get ($config, "graph_period", "second", $domain, $name, $service) eq "minute"); 
     899    return (munin_get ($service, "graph_period", "second") eq "minute"); 
    1028900} 
    1029901 
    1030902sub orig_to_cdef { 
     903    my $service   = shift; 
     904    my $fieldname = shift; 
     905 
     906    return undef unless ref ($service) eq "HASH"; 
     907 
     908    if (defined $service->{$fieldname}->{"cdef_name"}) { 
     909        return orig_to_cdef ($service, $service->{$fieldname}->{"cdef_name"}); 
     910    } 
     911    return $fieldname; 
     912} 
     913 
     914sub skip_service { 
    1031915    my $service = shift; 
    1032     my $field   = shift; 
    1033  
    1034     if (defined $service->{$field.".cdef_name"}) 
    1035     { 
    1036         return &orig_to_cdef ($service, $service->{$field.".cdef_name"}); 
    1037     } 
    1038     return $field; 
    1039 
    1040  
    1041 sub set_cdef_name { 
    1042     my $service = shift; 
    1043     my $field   = shift; 
    1044     my $new     = shift; 
    1045  
    1046     $service->{$field.".cdef_name"} = $new; 
    1047     print "DEBUG: set_cdef_name from $field to $new.\n" if $DEBUG; 
    1048 
    1049  
    1050 sub skip_service { 
    1051     my $node = shift; 
    1052     my $service = shift; 
    1053  
    1054     # Check to make sure that service exists 
    1055     return 1 unless (ref $node->{client}->{$service}); 
     916 
     917    # Always graph if --force is present 
     918    return 0 if $force_graphing; 
    1056919 
    1057920    # See if we should skip it because of conf-options 
    1058     return 1 if ($node->{client}->{$service}->{'graph'} and  
    1059         ($node->{client}->{$service}->{'graph'} eq "no" || 
    1060         ($node->{client}->{$service}->{'graph'} eq "on-demand") && !$force_graphing)); 
    1061  
    1062     # See if we should skip it because of command-line arguments 
    1063     return 1 if (@limit_services and not grep (/^$service$/, @limit_services)); 
     921    return 1 if (munin_get ($service, "graph", "yes") eq "on-demand" or 
     922            !munin_get_bool ($service, "graph", 1)); 
    1064923 
    1065924    # Don't skip 
     
    1089948    } 
    1090949 
    1091     &set_cdef_name ($service, $$cfield_ref, $new_field); 
     950    munin_set_var_loc ($service, [$$cfield_ref, "cdef_name"], $new_field); 
    1092951    $$cfield_ref = $new_field; 
    1093952 
  • people/jo/multilevel-groups/server/munin-update.in

    r1292 r1293  
    10101010            } 
    10111011        } 
    1012         munin_set_var_loc ($newconf, ["graph_order"], join(' ',@graph_order)); 
     1012        munin_set_var_loc ($newconf, [$servname, "graph_order"], join(' ',@graph_order)); 
    10131013    } 
    10141014    return 0 unless $socket;