1#!/usr/bin/perl 2 3# collectd - contrib/migrate-4-5.px 4# Copyright (C) 2010 Florian Forster 5# 6# Permission is hereby granted, free of charge, to any person obtaining a 7# copy of this software and associated documentation files (the "Software"), 8# to deal in the Software without restriction, including without limitation 9# the rights to use, copy, modify, merge, publish, distribute, sublicense, 10# and/or sell copies of the Software, and to permit persons to whom the 11# Software is furnished to do so, subject to the following conditions: 12# 13# The above copyright notice and this permission notice shall be included in 14# all copies or substantial portions of the Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22# DEALINGS IN THE SOFTWARE. 23# 24# Authors: 25# Florian Forster <octo at collectd.org> 26 27use strict; 28use warnings; 29 30use Getopt::Long ('GetOptions'); 31use Data::Dumper (); 32use File::Basename ('dirname'); 33 34our $InDir = '/var/lib/collectd'; 35our $RRDtool = 'rrdtool'; 36our $RRDFilter = 'rrd_filter.px'; 37 38our %TypesCounterToDerive = # {{{ 39( 40 apache_bytes => ["count"], 41 apache_requests => ["count"], 42 arc_counts => ["demand_data", "demand_metadata", "prefetch_data", "prefetch_metadata"], 43 arc_l2_bytes => ["read", "write"], 44 ath_stat => ["value"], 45 compression => ["uncompressed", "compressed"], 46 connections => ["value"], 47 cpu => ["value"], 48 current => ["value"], 49 disk_merged => ["read", "write"], 50 disk_octets => ["read", "write"], 51 disk_ops => ["read", "write"], 52 disk_ops_complex => ["value"], 53 disk_time => ["read", "write"], 54 dns_answer => ["value"], 55 dns_notify => ["value"], 56 dns_octets => ["queries", "responses"], 57 dns_opcode => ["value"], 58 dns_qtype => ["value"], 59 dns_query => ["value"], 60 dns_question => ["value"], 61 dns_rcode => ["value"], 62 dns_reject => ["value"], 63 dns_request => ["value"], 64 dns_resolver => ["value"], 65 dns_response => ["value"], 66 dns_transfer => ["value"], 67 dns_update => ["value"], 68 dns_zops => ["value"], 69 fscache_stat => ["value"], 70 fork_rate => ["value"], 71 http_request_methods => ["count"], 72 http_requests => ["count"], 73 http_response_codes => ["count"], 74 if_collisions => ["value"], 75 if_dropped => ["rx", "tx"], 76 if_errors => ["rx", "tx"], 77 if_multicast => ["value"], 78 if_octets => ["rx", "tx"], 79 if_packets => ["rx", "tx"], 80 if_rx_errors => ["value"], 81 if_tx_errors => ["value"], 82 io_octets => ["rx", "tx"], 83 io_packets => ["rx", "tx"], 84 ipt_bytes => ["value"], 85 ipt_packets => ["value"], 86 irq => ["value"], 87 memcached_command => ["value"], 88 memcached_octets => ["rx", "tx"], 89 memcached_ops => ["value"], 90 mysql_commands => ["value"], 91 mysql_handler => ["value"], 92 mysql_locks => ["value"], 93 mysql_log_position => ["value"], 94 mysql_octets => ["rx", "tx"], 95 nfs_procedure => ["value"], 96 nginx_requests => ["value"], 97 node_octets => ["rx", "tx"], 98 node_stat => ["value"], 99 operations => ["value"], 100 pg_blks => ["value"], 101 pg_n_tup_c => ["value"], 102 pg_scan => ["value"], 103 pg_xact => ["value"], 104 protocol_counter => ["value"], 105 ps_cputime => ["user", "syst"], 106 ps_pagefaults => ["minflt", "majflt"], 107 serial_octets => ["rx", "tx"], 108 swap_io => ["value"], 109 virt_cpu_total => ["ns"], 110 virt_vcpu => ["ns"], 111 vmpage_action => ["value"], 112 vmpage_faults => ["minflt", "majflt"], 113 vmpage_io => ["in", "out"], 114); # }}} %TypesCounterToDerive 115 116our %TypesRenameDataSource = # {{{ 117( 118 absolute => "count", 119 apache_bytes => "count", 120 apache_connections => "count", 121 apache_idle_workers => "count", 122 apache_requests => "count", 123 apache_scoreboard => "count", 124 conntrack => "entropy", 125 contextswitch => "contextswitches", 126 delay => "seconds", 127 entropy => "entropy", 128 file_size => "bytes", 129 frequency => "frequency", 130 frequency_offset => "ppm", 131 http_request_methods => "count", 132 http_requests => "count", 133 http_response_codes => "count", 134 percent => "percent", 135 ping => "ping", 136 records => "count", 137 time_dispersion => "seconds", 138 timeleft => "timeleft", 139 time_offset => "seconds", 140 users => "users", 141 virt_cpu_total => "ns", 142 virt_vcpu => "ns", 143); # }}} %TypesRenameDataSource 144 145sub handle_file # {{{ 146{ 147 my @path = @_; 148 my $path = join ('/', @path); 149 150 if (!($path =~ m/\.rrd$/)) 151 { 152 return; 153 } 154 155 my $tmp = pop (@path); 156 $tmp =~ s/\.rrd$//; 157 my ($type, $type_inst) = split (m/-/, $tmp, 2); 158 $type_inst ||= ''; 159 160 $tmp = pop (@path); 161 my ($plugin, $plugin_inst) = split (m/-/, $tmp, 2); 162 $plugin_inst ||= ''; 163 164 if ($TypesRenameDataSource{$type}) 165 { 166 my $old_ds = $TypesRenameDataSource{$type}; 167 print "$RRDtool tune \"$path\" --data-source-rename ${old_ds}:value\n"; 168 } 169 170 if ($TypesCounterToDerive{$type}) 171 { 172 my $ds_names = $TypesCounterToDerive{$type}; 173 174 for (@$ds_names) 175 { 176 my $name = $_; 177 print "$RRDtool tune \"$path\" --data-source-type ${name}:DERIVE --minimum ${name}:0 --maximum ${name}:U\n"; 178 } 179 } 180 181 if ((($plugin eq 'df') || ($plugin eq 'interface')) 182 && (!$plugin_inst) && ($type_inst)) 183 { 184 my $dir = join ('/', @path); 185 print "mkdir -p \"$dir/$plugin-$type_inst\"\n"; 186 if (($plugin eq 'df') and ($type eq 'df')) 187 { 188 print "$RRDFilter --infile=\"$path\" --outfile=\"$dir/$plugin-$type_inst/df_complex-free.rrd\" --map free:value\n"; 189 print "$RRDFilter --infile=\"$path\" --outfile=\"$dir/$plugin-$type_inst/df_complex-used.rrd\" --map used:value\n"; 190 } 191 else 192 { 193 print "mv \"$path\" \"$dir/$plugin-$type_inst/$type.rrd\"\n"; 194 } 195 } 196} # }}} sub handle_file 197 198sub scan_dir # {{{ 199{ 200 my @dir_parts = @_; 201 my $dir_str = join ('/', @dir_parts); 202 my $dh; 203 204 opendir ($dh, $dir_str) || die; 205 while (my $entry = readdir ($dh)) 206 { 207 my $entry_path = "$dir_str/$entry"; 208 209 if ($entry =~ m/^\./) 210 { 211 next; 212 } 213 214 if (-d $entry_path) 215 { 216 scan_dir (@dir_parts, $entry); 217 } 218 elsif (-f $entry_path) 219 { 220 handle_file (@dir_parts, $entry); 221 } 222 } 223 closedir ($dh); 224} # }}} sub scan_dir 225 226sub exit_usage # {{{ 227{ 228 print STDERR <<EOF; 229migrate-4-5.px [OPTIONS] 230 231Valid options are: 232 233 --indir <dir> Source directory 234 Default: $InDir 235 --rrdtool <path> Path to the RRDtool binary 236 Default: $RRDtool 237 --rrdfilter <path> Path to the rrd_filter.px script 238 Default: $RRDFilter 239 240EOF 241 exit (1); 242} # }}} sub exit_usage 243 244GetOptions ("indir|i=s" => \$InDir, 245 "rrdtool=s" => \$RRDtool, 246 "rrdfilter=s" => \$RRDFilter, 247 "help|h" => \&exit_usage) or exit_usage (); 248 249print "#!/bin/bash\n\n"; 250 251scan_dir ($InDir); 252 253# vim: set sw=2 sts=2 et fdm=marker : 254