]> arthur.barton.de Git - netdata.git/blob - charts.d/sensors.chart.sh
Merge pull request #2021 from ktsaou/master
[netdata.git] / charts.d / sensors.chart.sh
1 # no need for shebang - this file is loaded from charts.d.plugin
2
3 # netdata
4 # real-time performance and health monitoring, done right!
5 # (C) 2016 Costa Tsaousis <costa@tsaousis.gr>
6 # GPL v3+
7 #
8
9 # sensors docs
10 # https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
11
12 # if this chart is called X.chart.sh, then all functions and global variables
13 # must start with X_
14
15 # the directory the kernel keeps sensor data
16 sensors_sys_dir="${NETDATA_HOST_PREFIX}/sys/devices"
17
18 # how deep in the tree to check for sensor data
19 sensors_sys_depth=10
20
21 # if set to 1, the script will overwrite internal
22 # script functions with code generated ones
23 # leave to 1, is faster
24 sensors_source_update=1
25
26 # how frequently to collect sensor data
27 # the default is to collect it at every iteration of charts.d
28 sensors_update_every=
29
30 sensors_priority=90000
31
32 declare -A sensors_excluded=()
33
34 sensors_find_all_files() {
35         find $1 -maxdepth $sensors_sys_depth -name \*_input -o -name temp 2>/dev/null
36 }
37
38 sensors_find_all_dirs() {
39         sensors_find_all_files $1 | while read
40         do
41                 dirname $REPLY
42         done | sort -u
43 }
44
45 # _check is called once, to find out if this chart should be enabled or not
46 sensors_check() {
47
48         # this should return:
49         #  - 0 to enable the chart
50         #  - 1 to disable the chart
51
52         [ -z "$( sensors_find_all_files $sensors_sys_dir )" ] && error "no sensors found in '$sensors_sys_dir'." && return 1
53         return 0
54 }
55
56 sensors_check_files() {
57         # we only need sensors that report a non-zero value
58         # also remove not needed sensors
59
60         local f= v= excluded=
61         for f in $*
62         do
63                 [ ! -f "$f" ] && continue
64                 for ex in ${sensors_excluded[@]}; do
65                         [[ $f =~ .*$ex$ ]] && excluded='1' && break
66                 done
67
68                 [ "$excluded" != "1" ] && v="$( cat $f )" || v=0
69                 v=$(( v + 1 - 1 ))
70                 [ $v -ne 0 ] && echo "$f" && continue
71                 excluded=
72
73                 error "$f gives zero values"
74         done
75 }
76
77 sensors_check_temp_type() {
78         # valid temp types are 1 to 6
79         # disabled sensors have the value 0
80
81         local f= t= v=
82         for f in $*
83         do
84                 t=$( echo $f | sed "s|_input$|_type|g" )
85                 [ "$f" = "$t" ] && echo "$f" && continue
86                 [ ! -f "$t" ] && echo "$f" && continue
87
88                 v="$( cat $t )"
89                 v=$(( v + 1 - 1 ))
90                 [ $v -ne 0 ] && echo "$f" && continue
91
92                 error "$f is disabled"
93         done
94 }
95
96 # _create is called once, to create the charts
97 sensors_create() {
98         local path= dir= name= x= file= lfile= labelname= labelid= device= subsystem= id= type= mode= files= multiplier= divisor=
99
100         # we create a script with the source of the
101         # sensors_update() function
102         # - the highest speed we can achieve -
103         [ $sensors_source_update -eq 1 ] && echo >$TMP_DIR/sensors.sh "sensors_update() {"
104
105         for path in $( sensors_find_all_dirs $sensors_sys_dir | sort -u )
106         do
107                 dir=$( basename $path )
108                 device=
109                 subsystem=
110                 id=
111                 type=
112                 name=
113
114                 [ -h $path/device ] && device=$( readlink -f $path/device )
115                 [ ! -z "$device" ] && device=$( basename $device )
116                 [ -z "$device" ] && device="$dir"
117
118                 [ -h $path/subsystem ] && subsystem=$( readlink -f $path/subsystem )
119                 [ ! -z "$subsystem" ] && subsystem=$( basename $subsystem )
120                 [ -z "$subsystem" ] && subsystem="$dir"
121
122                 [ -f $path/name ] && name=$( cat $path/name )
123                 [ -z "$name" ] && name="$dir"
124
125                 [ -f $path/type ] && type=$( cat $path/type )
126                 [ -z "$type" ] && type="$dir"
127
128                 id="$( fixid "$device.$subsystem.$dir" )"
129
130                 debug "path='$path', dir='$dir', device='$device', subsystem='$subsystem', id='$id', name='$name'"
131
132                 for mode in temperature voltage fans power current energy humidity
133                 do
134                         files=
135                         multiplier=1
136                         divisor=1
137                         algorithm="absolute"
138
139                         case $mode in
140                                 temperature)
141                                         files="$( ls $path/temp*_input 2>/dev/null; ls $path/temp 2>/dev/null )"
142                                         files="$( sensors_check_files $files )"
143                                         files="$( sensors_check_temp_type $files )"
144                                         [ -z "$files" ] && continue
145                                         echo "CHART sensors.temp_$id '' '$name Temperature' 'Celsius' 'temperature' 'sensors.temp' line $((sensors_priority + 1)) $sensors_update_every"
146                                         echo >>$TMP_DIR/sensors.sh "echo \"BEGIN sensors.temp_$id \$1\""
147                                         divisor=1000
148                                         ;;
149
150                                 voltage)
151                                         files="$( ls $path/in*_input 2>/dev/null )"
152                                         files="$( sensors_check_files $files )"
153                                         [ -z "$files" ] && continue
154                                         echo "CHART sensors.volt_$id '' '$name Voltage' 'Volts' 'voltage' 'sensors.volt' line $((sensors_priority + 2)) $sensors_update_every"
155                                         echo >>$TMP_DIR/sensors.sh "echo \"BEGIN sensors.volt_$id \$1\""
156                                         divisor=1000
157                                         ;;
158
159                                 current)
160                                         files="$( ls $path/curr*_input 2>/dev/null )"
161                                         files="$( sensors_check_files $files )"
162                                         [ -z "$files" ] && continue
163                                         echo "CHART sensors.curr_$id '' '$name Current' 'Ampere' 'current' 'sensors.curr' line $((sensors_priority + 3)) $sensors_update_every"
164                                         echo >>$TMP_DIR/sensors.sh "echo \"BEGIN sensors.curr_$id \$1\""
165                                         divisor=1000
166                                         ;;
167
168                                 power)
169                                         files="$( ls $path/power*_input 2>/dev/null )"
170                                         files="$( sensors_check_files $files )"
171                                         [ -z "$files" ] && continue
172                                         echo "CHART sensors.power_$id '' '$name Power' 'Watt' 'power' 'sensors.power' line $((sensors_priority + 4)) $sensors_update_every"
173                                         echo >>$TMP_DIR/sensors.sh "echo \"BEGIN sensors.power_$id \$1\""
174                                         divisor=1000000
175                                         ;;
176
177                                 fans)
178                                         files="$( ls $path/fan*_input 2>/dev/null )"
179                                         files="$( sensors_check_files $files )"
180                                         [ -z "$files" ] && continue
181                                         echo "CHART sensors.fan_$id '' '$name Fans Speed' 'Rotations / Minute' 'fans' 'sensors.fans' line $((sensors_priority + 5)) $sensors_update_every"
182                                         echo >>$TMP_DIR/sensors.sh "echo \"BEGIN sensors.fan_$id \$1\""
183                                         ;;
184
185                                 energy)
186                                         files="$( ls $path/energy*_input 2>/dev/null )"
187                                         files="$( sensors_check_files $files )"
188                                         [ -z "$files" ] && continue
189                                         echo "CHART sensors.energy_$id '' '$name Energy' 'Joule' 'energy' 'sensors.energy' areastack $((sensors_priority + 6)) $sensors_update_every"
190                                         echo >>$TMP_DIR/sensors.sh "echo \"BEGIN sensors.energy_$id \$1\""
191                                         algorithm="incremental"
192                                         divisor=1000000
193                                         ;;
194
195                                 humidity)
196                                         files="$( ls $path/humidity*_input 2>/dev/null )"
197                                         files="$( sensors_check_files $files )"
198                                         [ -z "$files" ] && continue
199                                         echo "CHART sensors.humidity_$id '' '$name Humidity' 'Percent' 'humidity' 'sensors.humidity' line $((sensors_priority + 7)) $sensors_update_every"
200                                         echo >>$TMP_DIR/sensors.sh "echo \"BEGIN sensors.humidity_$id \$1\""
201                                         divisor=1000
202                                         ;;
203
204                                 *)
205                                         continue
206                                         ;;
207                         esac
208
209                         for x in $files
210                         do
211                                 file="$x"
212                                 fid="$( fixid "$file" )"
213                                 lfile="$( basename $file | sed "s|_input$|_label|g" )"
214                                 labelname="$( basename $file | sed "s|_input$||g" )"
215
216                                 if [ ! "$path/$lfile" = "$file" -a -f "$path/$lfile" ]
217                                         then
218                                         labelname="$( cat "$path/$lfile" )"
219                                 fi
220
221                                 echo "DIMENSION $fid '$labelname' $algorithm $multiplier $divisor"
222                                 echo >>$TMP_DIR/sensors.sh "echo \"SET $fid = \"\$(< $file )"
223                         done
224
225                         echo >>$TMP_DIR/sensors.sh "echo END"
226                 done
227         done
228
229         [ $sensors_source_update -eq 1 ] && echo >>$TMP_DIR/sensors.sh "}"
230
231         # ok, load the function sensors_update() we created
232         [ $sensors_source_update -eq 1 ] && . $TMP_DIR/sensors.sh
233
234         return 0
235 }
236
237 # _update is called continiously, to collect the values
238 sensors_update() {
239         # the first argument to this function is the microseconds since last update
240         # pass this parameter to the BEGIN statement (see bellow).
241
242         # do all the work to collect / calculate the values
243         # for each dimension
244         # remember: KEEP IT SIMPLE AND SHORT
245
246         [ $sensors_source_update -eq 0 ] && . $TMP_DIR/sensors.sh $1
247
248         return 0
249 }
250