iStats 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +14 -0
- data/ext/osx_stats/smc.h +2 -1
- data/integrations/zbx-istats-template.xml +246 -0
- data/integrations/zbx-istats.conf +9 -0
- data/lib/iStats/battery.rb +24 -15
- data/lib/iStats/command.rb +26 -1
- data/lib/iStats/cpu.rb +2 -1
- data/lib/iStats/extra.rb +8 -2
- data/lib/iStats/fan.rb +3 -2
- data/lib/iStats/printer.rb +127 -16
- data/lib/iStats/smc.rb +29 -2
- data/lib/iStats/utils.rb +12 -0
- data/lib/iStats/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3f68d9e125f87b545848c4f5b397c396636246ca
|
|
4
|
+
data.tar.gz: 5b224687a063e7dbc08fb7ab40b2a8b540ab8ce1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3cedfef4fe36306a824d385bce478a873e26cca1a5bfbc0d5b2262c9978a555ada8ce69b7a6941c68a5d8f6cb9196b908e1c015848bb36ce1966b3491c556599
|
|
7
|
+
data.tar.gz: a4ca2e631f26619a1431d6f14fb8637fb5ced576d7f970d6c2586218bf1be3d96c85c28489b8030589fca6646accfdf6b2327f40fd1ade00e642006435ec9479
|
data/README.md
CHANGED
|
@@ -42,12 +42,16 @@ If you are running an older version of OS X and the install fails you might want
|
|
|
42
42
|
|
|
43
43
|
istats scan Scans and print temperatures
|
|
44
44
|
istats scan [key] Print single SMC temperature key
|
|
45
|
+
istats scan [zabbix] JSON output for Zabbix discovery
|
|
45
46
|
istats enable [key | all] Enables key
|
|
46
47
|
istats disable [key | all] Disable key
|
|
47
48
|
istats list List available keys
|
|
48
49
|
|
|
49
50
|
# Arguments
|
|
50
51
|
--no-graphs Don't display sparklines graphs
|
|
52
|
+
--no-labels Don't display item names/labels
|
|
53
|
+
--no-scale Display just the stat value
|
|
54
|
+
--value-only No graph, label, or scale
|
|
51
55
|
-f, --fahrenheit Display temperatures in fahrenheit
|
|
52
56
|
|
|
53
57
|
for more help see: https://github.com/Chris911/iStats
|
|
@@ -82,3 +86,13 @@ Ruby: 1.9.3, 2.0.0, 2.1.1
|
|
|
82
86
|
MacBook Pro 2014
|
|
83
87
|
OS X: 10.10.3, 10.10.4
|
|
84
88
|
Ruby: 2.1.3
|
|
89
|
+
|
|
90
|
+
Mac Pro 2013
|
|
91
|
+
OS X: 10.12.6
|
|
92
|
+
Ruby: 2.0.0
|
|
93
|
+
|
|
94
|
+
#### Zabbix Integration
|
|
95
|
+
|
|
96
|
+
iStats has a "scan zabbix" mode which will emit JSON suitable for use with
|
|
97
|
+
[Zabbix](https://zabbix.com/) low-level discovery. See the accompanying
|
|
98
|
+
template and agent config in the `integrations` directory.
|
data/ext/osx_stats/smc.h
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
|
|
20
20
|
#ifndef __SMC_H__
|
|
21
21
|
#define __SMC_H__
|
|
22
|
-
#endif
|
|
23
22
|
|
|
24
23
|
#define VERSION "0.01"
|
|
25
24
|
|
|
@@ -113,3 +112,5 @@ VALUE method_get_battery_design_cycle_count(VALUE self);
|
|
|
113
112
|
VALUE method_get_battery_temp(VALUE self);
|
|
114
113
|
VALUE method_get_battery_time_remaining(VALUE self);
|
|
115
114
|
VALUE method_get_battery_charge(VALUE self);
|
|
115
|
+
|
|
116
|
+
#endif // __SMC_H__
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<zabbix_export>
|
|
3
|
+
<version>3.2</version>
|
|
4
|
+
<date>2017-08-14T03:21:42Z</date>
|
|
5
|
+
<groups>
|
|
6
|
+
<group>
|
|
7
|
+
<name>Templates</name>
|
|
8
|
+
</group>
|
|
9
|
+
</groups>
|
|
10
|
+
<templates>
|
|
11
|
+
<template>
|
|
12
|
+
<template>Template macOS iStats</template>
|
|
13
|
+
<name>Template macOS iStats</name>
|
|
14
|
+
<description/>
|
|
15
|
+
<groups>
|
|
16
|
+
<group>
|
|
17
|
+
<name>Templates</name>
|
|
18
|
+
</group>
|
|
19
|
+
</groups>
|
|
20
|
+
<applications>
|
|
21
|
+
<application>
|
|
22
|
+
<name>iStats</name>
|
|
23
|
+
</application>
|
|
24
|
+
</applications>
|
|
25
|
+
<items>
|
|
26
|
+
<item>
|
|
27
|
+
<name>Battery Remaining</name>
|
|
28
|
+
<type>7</type>
|
|
29
|
+
<snmp_community/>
|
|
30
|
+
<multiplier>0</multiplier>
|
|
31
|
+
<snmp_oid/>
|
|
32
|
+
<key>istats.battery</key>
|
|
33
|
+
<delay>30</delay>
|
|
34
|
+
<history>7</history>
|
|
35
|
+
<trends>30</trends>
|
|
36
|
+
<status>0</status>
|
|
37
|
+
<value_type>0</value_type>
|
|
38
|
+
<allowed_hosts/>
|
|
39
|
+
<units>%</units>
|
|
40
|
+
<delta>0</delta>
|
|
41
|
+
<snmpv3_contextname/>
|
|
42
|
+
<snmpv3_securityname/>
|
|
43
|
+
<snmpv3_securitylevel>0</snmpv3_securitylevel>
|
|
44
|
+
<snmpv3_authprotocol>0</snmpv3_authprotocol>
|
|
45
|
+
<snmpv3_authpassphrase/>
|
|
46
|
+
<snmpv3_privprotocol>0</snmpv3_privprotocol>
|
|
47
|
+
<snmpv3_privpassphrase/>
|
|
48
|
+
<formula>1</formula>
|
|
49
|
+
<delay_flex/>
|
|
50
|
+
<params/>
|
|
51
|
+
<ipmi_sensor/>
|
|
52
|
+
<data_type>0</data_type>
|
|
53
|
+
<authtype>0</authtype>
|
|
54
|
+
<username/>
|
|
55
|
+
<password/>
|
|
56
|
+
<publickey/>
|
|
57
|
+
<privatekey/>
|
|
58
|
+
<port/>
|
|
59
|
+
<description/>
|
|
60
|
+
<inventory_link>0</inventory_link>
|
|
61
|
+
<applications>
|
|
62
|
+
<application>
|
|
63
|
+
<name>iStats</name>
|
|
64
|
+
</application>
|
|
65
|
+
</applications>
|
|
66
|
+
<valuemap/>
|
|
67
|
+
<logtimefmt/>
|
|
68
|
+
</item>
|
|
69
|
+
<item>
|
|
70
|
+
<name>CPU Temp</name>
|
|
71
|
+
<type>7</type>
|
|
72
|
+
<snmp_community/>
|
|
73
|
+
<multiplier>0</multiplier>
|
|
74
|
+
<snmp_oid/>
|
|
75
|
+
<key>istats.cpu</key>
|
|
76
|
+
<delay>30</delay>
|
|
77
|
+
<history>7</history>
|
|
78
|
+
<trends>30</trends>
|
|
79
|
+
<status>0</status>
|
|
80
|
+
<value_type>0</value_type>
|
|
81
|
+
<allowed_hosts/>
|
|
82
|
+
<units>C</units>
|
|
83
|
+
<delta>0</delta>
|
|
84
|
+
<snmpv3_contextname/>
|
|
85
|
+
<snmpv3_securityname/>
|
|
86
|
+
<snmpv3_securitylevel>0</snmpv3_securitylevel>
|
|
87
|
+
<snmpv3_authprotocol>0</snmpv3_authprotocol>
|
|
88
|
+
<snmpv3_authpassphrase/>
|
|
89
|
+
<snmpv3_privprotocol>0</snmpv3_privprotocol>
|
|
90
|
+
<snmpv3_privpassphrase/>
|
|
91
|
+
<formula>1</formula>
|
|
92
|
+
<delay_flex/>
|
|
93
|
+
<params/>
|
|
94
|
+
<ipmi_sensor/>
|
|
95
|
+
<data_type>0</data_type>
|
|
96
|
+
<authtype>0</authtype>
|
|
97
|
+
<username/>
|
|
98
|
+
<password/>
|
|
99
|
+
<publickey/>
|
|
100
|
+
<privatekey/>
|
|
101
|
+
<port/>
|
|
102
|
+
<description/>
|
|
103
|
+
<inventory_link>0</inventory_link>
|
|
104
|
+
<applications>
|
|
105
|
+
<application>
|
|
106
|
+
<name>iStats</name>
|
|
107
|
+
</application>
|
|
108
|
+
</applications>
|
|
109
|
+
<valuemap/>
|
|
110
|
+
<logtimefmt/>
|
|
111
|
+
</item>
|
|
112
|
+
<item>
|
|
113
|
+
<name>Fan Speed</name>
|
|
114
|
+
<type>7</type>
|
|
115
|
+
<snmp_community/>
|
|
116
|
+
<multiplier>0</multiplier>
|
|
117
|
+
<snmp_oid/>
|
|
118
|
+
<key>istats.fan.speed</key>
|
|
119
|
+
<delay>30</delay>
|
|
120
|
+
<history>7</history>
|
|
121
|
+
<trends>30</trends>
|
|
122
|
+
<status>0</status>
|
|
123
|
+
<value_type>0</value_type>
|
|
124
|
+
<allowed_hosts/>
|
|
125
|
+
<units>RPM</units>
|
|
126
|
+
<delta>0</delta>
|
|
127
|
+
<snmpv3_contextname/>
|
|
128
|
+
<snmpv3_securityname/>
|
|
129
|
+
<snmpv3_securitylevel>0</snmpv3_securitylevel>
|
|
130
|
+
<snmpv3_authprotocol>0</snmpv3_authprotocol>
|
|
131
|
+
<snmpv3_authpassphrase/>
|
|
132
|
+
<snmpv3_privprotocol>0</snmpv3_privprotocol>
|
|
133
|
+
<snmpv3_privpassphrase/>
|
|
134
|
+
<formula>1</formula>
|
|
135
|
+
<delay_flex/>
|
|
136
|
+
<params/>
|
|
137
|
+
<ipmi_sensor/>
|
|
138
|
+
<data_type>0</data_type>
|
|
139
|
+
<authtype>0</authtype>
|
|
140
|
+
<username/>
|
|
141
|
+
<password/>
|
|
142
|
+
<publickey/>
|
|
143
|
+
<privatekey/>
|
|
144
|
+
<port/>
|
|
145
|
+
<description/>
|
|
146
|
+
<inventory_link>0</inventory_link>
|
|
147
|
+
<applications>
|
|
148
|
+
<application>
|
|
149
|
+
<name>iStats</name>
|
|
150
|
+
</application>
|
|
151
|
+
</applications>
|
|
152
|
+
<valuemap/>
|
|
153
|
+
<logtimefmt/>
|
|
154
|
+
</item>
|
|
155
|
+
</items>
|
|
156
|
+
<discovery_rules>
|
|
157
|
+
<discovery_rule>
|
|
158
|
+
<name>Thermal Items</name>
|
|
159
|
+
<type>0</type>
|
|
160
|
+
<snmp_community/>
|
|
161
|
+
<snmp_oid/>
|
|
162
|
+
<key>istats.temp.discovery</key>
|
|
163
|
+
<delay>3600</delay>
|
|
164
|
+
<status>0</status>
|
|
165
|
+
<allowed_hosts/>
|
|
166
|
+
<snmpv3_contextname/>
|
|
167
|
+
<snmpv3_securityname/>
|
|
168
|
+
<snmpv3_securitylevel>0</snmpv3_securitylevel>
|
|
169
|
+
<snmpv3_authprotocol>0</snmpv3_authprotocol>
|
|
170
|
+
<snmpv3_authpassphrase/>
|
|
171
|
+
<snmpv3_privprotocol>0</snmpv3_privprotocol>
|
|
172
|
+
<snmpv3_privpassphrase/>
|
|
173
|
+
<delay_flex/>
|
|
174
|
+
<params/>
|
|
175
|
+
<ipmi_sensor/>
|
|
176
|
+
<authtype>0</authtype>
|
|
177
|
+
<username/>
|
|
178
|
+
<password/>
|
|
179
|
+
<publickey/>
|
|
180
|
+
<privatekey/>
|
|
181
|
+
<port/>
|
|
182
|
+
<filter>
|
|
183
|
+
<evaltype>0</evaltype>
|
|
184
|
+
<formula/>
|
|
185
|
+
<conditions/>
|
|
186
|
+
</filter>
|
|
187
|
+
<lifetime>7</lifetime>
|
|
188
|
+
<description/>
|
|
189
|
+
<item_prototypes>
|
|
190
|
+
<item_prototype>
|
|
191
|
+
<name>{#NAME} ({#KEY}) Temp</name>
|
|
192
|
+
<type>7</type>
|
|
193
|
+
<snmp_community/>
|
|
194
|
+
<multiplier>0</multiplier>
|
|
195
|
+
<snmp_oid/>
|
|
196
|
+
<key>istats.scan[{#KEY}]</key>
|
|
197
|
+
<delay>30</delay>
|
|
198
|
+
<history>7</history>
|
|
199
|
+
<trends>30</trends>
|
|
200
|
+
<status>0</status>
|
|
201
|
+
<value_type>0</value_type>
|
|
202
|
+
<allowed_hosts/>
|
|
203
|
+
<units>C</units>
|
|
204
|
+
<delta>0</delta>
|
|
205
|
+
<snmpv3_contextname/>
|
|
206
|
+
<snmpv3_securityname/>
|
|
207
|
+
<snmpv3_securitylevel>0</snmpv3_securitylevel>
|
|
208
|
+
<snmpv3_authprotocol>0</snmpv3_authprotocol>
|
|
209
|
+
<snmpv3_authpassphrase/>
|
|
210
|
+
<snmpv3_privprotocol>0</snmpv3_privprotocol>
|
|
211
|
+
<snmpv3_privpassphrase/>
|
|
212
|
+
<formula>1</formula>
|
|
213
|
+
<delay_flex/>
|
|
214
|
+
<params/>
|
|
215
|
+
<ipmi_sensor/>
|
|
216
|
+
<data_type>0</data_type>
|
|
217
|
+
<authtype>0</authtype>
|
|
218
|
+
<username/>
|
|
219
|
+
<password/>
|
|
220
|
+
<publickey/>
|
|
221
|
+
<privatekey/>
|
|
222
|
+
<port/>
|
|
223
|
+
<description/>
|
|
224
|
+
<inventory_link>0</inventory_link>
|
|
225
|
+
<applications>
|
|
226
|
+
<application>
|
|
227
|
+
<name>iStats</name>
|
|
228
|
+
</application>
|
|
229
|
+
</applications>
|
|
230
|
+
<valuemap/>
|
|
231
|
+
<logtimefmt/>
|
|
232
|
+
<application_prototypes/>
|
|
233
|
+
</item_prototype>
|
|
234
|
+
</item_prototypes>
|
|
235
|
+
<trigger_prototypes/>
|
|
236
|
+
<graph_prototypes/>
|
|
237
|
+
<host_prototypes/>
|
|
238
|
+
</discovery_rule>
|
|
239
|
+
</discovery_rules>
|
|
240
|
+
<httptests/>
|
|
241
|
+
<macros/>
|
|
242
|
+
<templates/>
|
|
243
|
+
<screens/>
|
|
244
|
+
</template>
|
|
245
|
+
</templates>
|
|
246
|
+
</zabbix_export>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Low-level discovery item. This may take several seconds to complete, so
|
|
2
|
+
# make sure that the Timeout value in your zabbix config is high enough to
|
|
3
|
+
# handle this. Default is 3 seconds which is unlikely to be sufficient.
|
|
4
|
+
UserParameter=istats.temp.discovery,/usr/local/bin/istats scan zabbix
|
|
5
|
+
|
|
6
|
+
UserParameter=istats.cpu,/usr/local/bin/istats cpu temp --value-only
|
|
7
|
+
UserParameter=istats.battery,/usr/local/bin/istats battery charge --value-only
|
|
8
|
+
UserParameter=istats.fan.speed,/usr/local/bin/istats fan speed --value-only
|
|
9
|
+
UserParameter=istats.scan[*],/usr/local/bin/istats scan $1 --value-only
|
data/lib/iStats/battery.rb
CHANGED
|
@@ -49,13 +49,14 @@ module IStats
|
|
|
49
49
|
@ioreg_out ||= %x( ioreg -rn AppleSmartBattery )
|
|
50
50
|
cycle_count = @ioreg_out[/"CycleCount" = ([0-9]*)/, 1]
|
|
51
51
|
if cycle_count == nil
|
|
52
|
-
|
|
52
|
+
Printer.print_item_line("Cycle count", "unknown")
|
|
53
53
|
else
|
|
54
54
|
max_cycle_count = design_cycle_count
|
|
55
55
|
percentage = (cycle_count.to_f/max_cycle_count.to_f)*100
|
|
56
|
-
thresholds = [45, 65, 85, 95]
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
thresholds = Utils.abs_thresholds([0.45, 0.65, 0.85, 0.95], max_cycle_count)
|
|
57
|
+
|
|
58
|
+
Printer.print_item_line("Cycle count", cycle_count, "", thresholds, "#{percentage.round(1)}%")
|
|
59
|
+
Printer.print_item_line("Max cycles", max_cycle_count)
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
|
|
@@ -87,26 +88,34 @@ module IStats
|
|
|
87
88
|
# Print battery capacity info
|
|
88
89
|
#
|
|
89
90
|
def print_capacity_info
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
cur_max = cur_max_capacity.to_f
|
|
92
|
+
ori_max = ori_max_capacity.to_f
|
|
93
|
+
|
|
94
|
+
percentage = (cur_max / ori_max)*100
|
|
95
|
+
|
|
96
|
+
per_thresholds = [0.95, 0.85, 0.65, 0.45]
|
|
97
|
+
cur_thresholds = Utils.abs_thresholds(per_thresholds, cur_max)
|
|
98
|
+
ori_thresholds = Utils.abs_thresholds(per_thresholds, ori_max)
|
|
99
|
+
|
|
92
100
|
charge = get_battery_charge
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
101
|
+
result = charge ? "#{charge}%" : "Unknown"
|
|
102
|
+
Printer.print_item_line("Current charge", cur_capacity, " mAh", cur_thresholds, "#{result}")
|
|
103
|
+
Printer.print_item_line("Maximum charge", cur_max_capacity, " mAh", ori_thresholds, "#{percentage.round(1)}%")
|
|
104
|
+
Printer.print_item_line("Design capacity", ori_max_capacity, " mAh")
|
|
97
105
|
end
|
|
98
106
|
|
|
99
107
|
# Get the battery temperature
|
|
100
108
|
#
|
|
101
109
|
def battery_temperature
|
|
102
|
-
|
|
110
|
+
value, scale = Printer.parse_temperature(get_battery_temp)
|
|
111
|
+
Printer.print_item_line("Battery temp", value, scale)
|
|
103
112
|
end
|
|
104
113
|
|
|
105
114
|
# Get the battery health
|
|
106
115
|
# Calls a C method from BATTERY_STATS module
|
|
107
116
|
#
|
|
108
117
|
def battery_health
|
|
109
|
-
|
|
118
|
+
Printer.print_item_line("Battery health", get_battery_health)
|
|
110
119
|
end
|
|
111
120
|
|
|
112
121
|
def battery_time_remaining
|
|
@@ -119,13 +128,13 @@ module IStats
|
|
|
119
128
|
time = "%i:%02i" % [hours, minutes]
|
|
120
129
|
end
|
|
121
130
|
|
|
122
|
-
|
|
131
|
+
Printer.print_item_line("Battery time remaining", time)
|
|
123
132
|
end
|
|
124
133
|
|
|
125
134
|
def battery_charge
|
|
126
135
|
charge = get_battery_charge
|
|
127
|
-
result = charge ?
|
|
128
|
-
|
|
136
|
+
result = charge ? charge : "Unknown"
|
|
137
|
+
Printer.print_item_line("Battery charge", result, "%")
|
|
129
138
|
end
|
|
130
139
|
|
|
131
140
|
# Get the battery design cycle count
|
data/lib/iStats/command.rb
CHANGED
|
@@ -26,6 +26,8 @@ module IStats
|
|
|
26
26
|
#
|
|
27
27
|
def setup(options)
|
|
28
28
|
Printer.disable_graphs unless options[:display_graphs]
|
|
29
|
+
Printer.disable_labels unless options[:display_labels]
|
|
30
|
+
Printer.disable_scale unless options[:display_scale]
|
|
29
31
|
Printer.set_temperature_scale options[:temperature_scale]
|
|
30
32
|
end
|
|
31
33
|
|
|
@@ -82,7 +84,12 @@ module IStats
|
|
|
82
84
|
#
|
|
83
85
|
# returns nothing
|
|
84
86
|
def parse_options
|
|
85
|
-
options = {
|
|
87
|
+
options = {
|
|
88
|
+
:display_graphs => true,
|
|
89
|
+
:display_labels => true,
|
|
90
|
+
:display_scale => true,
|
|
91
|
+
:temperature_scale => 'celcius',
|
|
92
|
+
}
|
|
86
93
|
|
|
87
94
|
opt_parser = OptionParser.new do |opts|
|
|
88
95
|
opts.on('-v', '--version', 'Print Version') do
|
|
@@ -99,6 +106,20 @@ module IStats
|
|
|
99
106
|
options[:display_graphs] = false
|
|
100
107
|
end
|
|
101
108
|
|
|
109
|
+
opts.on('--no-labels', 'Don\'t display key names') do
|
|
110
|
+
options[:display_labels] = false
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
opts.on('--no-scale', 'Display just the stat value (number-only)') do
|
|
114
|
+
options[:display_scale] = false
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
opts.on('--value-only', 'No graph, label, or scale') do
|
|
118
|
+
options[:display_graphs] = false
|
|
119
|
+
options[:display_labels] = false
|
|
120
|
+
options[:display_scale] = false
|
|
121
|
+
end
|
|
122
|
+
|
|
102
123
|
opts.on('-f', '--fahrenheit', 'Display temperatures in fahrenheit') do
|
|
103
124
|
options[:temperature_scale] = 'fahrenheit'
|
|
104
125
|
end
|
|
@@ -143,12 +164,16 @@ module IStats
|
|
|
143
164
|
|
|
144
165
|
istats scan Scans and print temperatures
|
|
145
166
|
istats scan [key] Print single SMC temperature key
|
|
167
|
+
istats scan [zabbix] JSON output for Zabbix discovery
|
|
146
168
|
istats enable [key | all] Enables key
|
|
147
169
|
istats disable [key | all] Disable key
|
|
148
170
|
istats list List available keys
|
|
149
171
|
|
|
150
172
|
# Arguments
|
|
151
173
|
--no-graphs Don't display sparklines graphs
|
|
174
|
+
--no-labels Don't display item names/labels
|
|
175
|
+
--no-scale Display just the stat value
|
|
176
|
+
--value-only No graph, label, or scale
|
|
152
177
|
-f, --fahrenheit Display temperatures in fahrenheit
|
|
153
178
|
|
|
154
179
|
for more help see: https://github.com/Chris911/iStats
|
data/lib/iStats/cpu.rb
CHANGED
|
@@ -30,7 +30,8 @@ module IStats
|
|
|
30
30
|
def cpu_temperature
|
|
31
31
|
t = get_cpu_temp
|
|
32
32
|
thresholds = [50, 68, 80, 90]
|
|
33
|
-
|
|
33
|
+
value, scale = Printer.parse_temperature(t)
|
|
34
|
+
Printer.print_item_line("CPU temp", value, scale, thresholds)
|
|
34
35
|
end
|
|
35
36
|
end
|
|
36
37
|
end
|
data/lib/iStats/extra.rb
CHANGED
|
@@ -49,11 +49,17 @@ module IStats
|
|
|
49
49
|
# Pretty print sensor temperature
|
|
50
50
|
def display_temp(key, sensor, display)
|
|
51
51
|
t = SMC.is_key_supported(key).round(2);
|
|
52
|
+
value, scale = Printer.parse_temperature(t)
|
|
53
|
+
|
|
52
54
|
thresholds = sensor['thresholds'][1..-2].split(/, /).map { |s| s.to_i }
|
|
55
|
+
|
|
53
56
|
if (display)
|
|
54
|
-
|
|
57
|
+
# Invoked if settings has an AltDisplay?
|
|
58
|
+
puts "#{Printer.format_label("#{key}")}" +
|
|
59
|
+
"#{Printer.format_temperature(t)}#{Printer.gen_sparkline(t, thresholds)}" +
|
|
60
|
+
"#{Printer.format_label(" #{sensor['name']}")}"
|
|
55
61
|
else
|
|
56
|
-
|
|
62
|
+
Printer.print_item_line("#{key} #{sensor['name']} temp", value, scale, thresholds)
|
|
57
63
|
end
|
|
58
64
|
end
|
|
59
65
|
end
|
data/lib/iStats/fan.rb
CHANGED
|
@@ -38,7 +38,7 @@ module IStats
|
|
|
38
38
|
# Print number of fan(s)
|
|
39
39
|
#
|
|
40
40
|
def print_fan_number
|
|
41
|
-
|
|
41
|
+
Printer.print_item_line("Total fans in system", fan_number)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# Get and print the speed of each fan
|
|
@@ -47,6 +47,7 @@ module IStats
|
|
|
47
47
|
fanNum = fan_number
|
|
48
48
|
(0..(fanNum-1)).each do |n|
|
|
49
49
|
s = get_fan_speed(n)
|
|
50
|
+
s = s.round unless s.nil?
|
|
50
51
|
print_fan_speed(n, s)
|
|
51
52
|
end
|
|
52
53
|
end
|
|
@@ -58,7 +59,7 @@ module IStats
|
|
|
58
59
|
#
|
|
59
60
|
def print_fan_speed(fanNum, speed)
|
|
60
61
|
thresholds = [2500, 3500, 4500, 5500]
|
|
61
|
-
|
|
62
|
+
Printer.print_item_line("Fan #{fanNum} speed", speed, " RPM", thresholds)
|
|
62
63
|
end
|
|
63
64
|
end
|
|
64
65
|
end
|
data/lib/iStats/printer.rb
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
module IStats
|
|
2
2
|
class Printer
|
|
3
3
|
@display_graphs = true
|
|
4
|
+
@display_labels = true
|
|
5
|
+
@display_scale = true
|
|
4
6
|
@temperature_scale = 'celcius'
|
|
5
7
|
|
|
8
|
+
LABEL_WIDTH = 24
|
|
9
|
+
VALUE_WIDTH = 8
|
|
10
|
+
SCALE_WIDTH = 4
|
|
11
|
+
|
|
6
12
|
class << self
|
|
7
13
|
include IStats::Color
|
|
8
14
|
|
|
@@ -10,6 +16,14 @@ module IStats
|
|
|
10
16
|
@display_graphs = false
|
|
11
17
|
end
|
|
12
18
|
|
|
19
|
+
def disable_labels
|
|
20
|
+
@display_labels = false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def disable_scale
|
|
24
|
+
@display_scale = false
|
|
25
|
+
end
|
|
26
|
+
|
|
13
27
|
def set_temperature_scale(scale)
|
|
14
28
|
@temperature_scale = scale
|
|
15
29
|
end
|
|
@@ -19,41 +33,138 @@ module IStats
|
|
|
19
33
|
# thresholds - must be an array of size 4 containing the threshold values
|
|
20
34
|
# for the sparkline colors
|
|
21
35
|
#
|
|
36
|
+
# If the values in the thresholds array are descending, treat 100& as
|
|
37
|
+
# good (green) instead of bad (red)
|
|
38
|
+
#
|
|
22
39
|
def gen_sparkline(value, thresholds)
|
|
23
40
|
# Graphs can be disabled globally
|
|
24
41
|
return '' unless @display_graphs
|
|
25
42
|
|
|
26
43
|
return if thresholds.count < 4
|
|
27
44
|
|
|
45
|
+
value = value.to_f
|
|
46
|
+
|
|
28
47
|
list = [0, 30, 55, 80, 100, 130]
|
|
29
48
|
sparkline = Sparkr.sparkline(list) do |tick, count, index|
|
|
30
|
-
if
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
if thresholds[3] > thresholds[0]
|
|
50
|
+
#
|
|
51
|
+
# Normal sparkline where 100% is bad
|
|
52
|
+
#
|
|
53
|
+
if index.between?(0, 5) and value > thresholds[3]
|
|
54
|
+
flash_red(tick)
|
|
55
|
+
elsif index.between?(0, 1)
|
|
56
|
+
green(tick)
|
|
57
|
+
elsif index.between?(2, 3) and value > thresholds[0]
|
|
58
|
+
light_yellow(tick)
|
|
59
|
+
elsif index == 4 and value > thresholds[1]
|
|
60
|
+
yellow(tick)
|
|
61
|
+
elsif index == 5 and value > thresholds[2]
|
|
62
|
+
red(tick)
|
|
63
|
+
else
|
|
64
|
+
tick
|
|
65
|
+
end
|
|
40
66
|
else
|
|
41
|
-
|
|
67
|
+
#
|
|
68
|
+
# Reversed sparkline where 100% is good
|
|
69
|
+
#
|
|
70
|
+
if value < thresholds[3]
|
|
71
|
+
if index == 1
|
|
72
|
+
red(tick)
|
|
73
|
+
else
|
|
74
|
+
tick
|
|
75
|
+
end
|
|
76
|
+
elsif value < thresholds[2]
|
|
77
|
+
if index.between?(0, 2)
|
|
78
|
+
yellow(tick)
|
|
79
|
+
else
|
|
80
|
+
tick
|
|
81
|
+
end
|
|
82
|
+
elsif value < thresholds[1]
|
|
83
|
+
if index.between?(0, 3)
|
|
84
|
+
light_yellow(tick)
|
|
85
|
+
else
|
|
86
|
+
tick
|
|
87
|
+
end
|
|
88
|
+
elsif value < thresholds[0]
|
|
89
|
+
if index.between?(0, 4)
|
|
90
|
+
green(tick)
|
|
91
|
+
else
|
|
92
|
+
tick
|
|
93
|
+
end
|
|
94
|
+
else
|
|
95
|
+
green(tick)
|
|
96
|
+
end
|
|
42
97
|
end
|
|
43
98
|
end
|
|
44
99
|
end
|
|
45
100
|
|
|
101
|
+
def format_label(label)
|
|
102
|
+
if @display_labels == true
|
|
103
|
+
"#{label}\t"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def format_scale(scale)
|
|
108
|
+
if @display_scale == true
|
|
109
|
+
"#{scale}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Converts the value to the class temperature_scale with
|
|
114
|
+
# accompanying scale string.
|
|
115
|
+
#
|
|
116
|
+
def parse_temperature(temperature)
|
|
117
|
+
if @temperature_scale == 'celcius'
|
|
118
|
+
value = temperature
|
|
119
|
+
symbol = "C"
|
|
120
|
+
else
|
|
121
|
+
value = Utils.to_fahrenheit(temperature)
|
|
122
|
+
symbol = "F"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
return value.round(2), "#{Symbols.degree}#{symbol}"
|
|
126
|
+
end
|
|
127
|
+
|
|
46
128
|
# Pretty print temperature values.
|
|
47
|
-
#
|
|
129
|
+
# Returns the formatted temperature string.
|
|
48
130
|
#
|
|
49
|
-
# Returns the temperature string.
|
|
50
131
|
def format_temperature(temperature)
|
|
51
|
-
|
|
52
|
-
"#{
|
|
132
|
+
value, scale = Printer.format_temperature(temperature)
|
|
133
|
+
"#{value}#{scale}"
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Prints a standard item line with label, value, scale, and sparkline
|
|
137
|
+
# as determined by the runtime command-line arguments supplied by the
|
|
138
|
+
# user.
|
|
139
|
+
#
|
|
140
|
+
def print_item_line(label, value, scale="", thresholds=[], suffix="")
|
|
141
|
+
|
|
142
|
+
if @display_scale
|
|
143
|
+
full_value_width = VALUE_WIDTH + SCALE_WIDTH
|
|
144
|
+
full_value = value.to_s + scale.to_s
|
|
53
145
|
else
|
|
54
|
-
|
|
146
|
+
full_value_width = VALUE_WIDTH
|
|
147
|
+
full_value = value
|
|
55
148
|
end
|
|
149
|
+
|
|
150
|
+
if @display_labels
|
|
151
|
+
format = "%-"+LABEL_WIDTH.to_s + "s"
|
|
152
|
+
printf("%-" + LABEL_WIDTH.to_s + "s", label + ":")
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
printf("%-" + full_value_width.to_s + "s", full_value)
|
|
156
|
+
|
|
157
|
+
if @display_graphs
|
|
158
|
+
print "#{Printer.gen_sparkline(value, thresholds)}"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
if @display_labels && suffix != ""
|
|
162
|
+
print " #{suffix}"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
printf "\n"
|
|
56
166
|
end
|
|
167
|
+
|
|
57
168
|
end
|
|
58
169
|
end
|
|
59
170
|
end
|
data/lib/iStats/smc.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
module IStats
|
|
5
5
|
class SMC
|
|
6
|
+
require 'json'
|
|
6
7
|
extend SMC_INFO
|
|
7
8
|
class << self
|
|
8
9
|
# Delegate CLI command to function
|
|
@@ -11,6 +12,8 @@ module IStats
|
|
|
11
12
|
case stat
|
|
12
13
|
when 'all'
|
|
13
14
|
all
|
|
15
|
+
when 'zabbix'
|
|
16
|
+
zabbix_discover
|
|
14
17
|
else
|
|
15
18
|
scan_supported_key(stat)
|
|
16
19
|
end
|
|
@@ -111,8 +114,9 @@ module IStats
|
|
|
111
114
|
sensors['enabled'] = 0
|
|
112
115
|
|
|
113
116
|
Settings.addSensor(key, sensors)
|
|
117
|
+
value, scale = Printer.parse_temperature(t)
|
|
114
118
|
|
|
115
|
-
|
|
119
|
+
Printer.print_item_line("#{key} #{sensors['name']}", value, scale, sensors['thresholds'])
|
|
116
120
|
end
|
|
117
121
|
}
|
|
118
122
|
}
|
|
@@ -122,9 +126,32 @@ module IStats
|
|
|
122
126
|
puts "The enabled sensors will show up when running `istats` or `istats extra`."
|
|
123
127
|
end
|
|
124
128
|
|
|
129
|
+
def zabbix_discover
|
|
130
|
+
items = []
|
|
131
|
+
|
|
132
|
+
characters = [('a'..'z'), ('A'..'Z'),(0..9)].map { |i| i.to_a }.flatten
|
|
133
|
+
characters.each {|l1|
|
|
134
|
+
characters.each {|l2|
|
|
135
|
+
characters.each {|l3|
|
|
136
|
+
key = "T#{l1}#{l2}#{l3}"
|
|
137
|
+
if (name(key) != 'Unknown') && (name(key) != '')
|
|
138
|
+
t = is_key_supported(key);
|
|
139
|
+
if (t > 0)
|
|
140
|
+
item = {'{#KEY}' => key, '{#NAME}' => name(key)}
|
|
141
|
+
items.push(item)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
data = {:data => items}
|
|
149
|
+
puts JSON.generate(data)
|
|
150
|
+
end
|
|
151
|
+
|
|
125
152
|
def scan_supported_key(key)
|
|
126
153
|
t = is_key_supported(key)
|
|
127
|
-
puts "
|
|
154
|
+
puts "#{Printer.format_label("Scanned #{key} result = ")}#{t}";
|
|
128
155
|
end
|
|
129
156
|
end
|
|
130
157
|
end
|
data/lib/iStats/utils.rb
CHANGED
|
@@ -8,5 +8,17 @@ module IStats
|
|
|
8
8
|
def to_fahrenheit(temperature)
|
|
9
9
|
(temperature * (9.0 / 5.0)) + 32
|
|
10
10
|
end
|
|
11
|
+
|
|
12
|
+
# Produce a thresholds array containing absolute values based on supplied
|
|
13
|
+
# percentages applied to a literal max value.
|
|
14
|
+
#
|
|
15
|
+
def abs_thresholds(scale, max_value)
|
|
16
|
+
at = []
|
|
17
|
+
scale.each { |v|
|
|
18
|
+
at.push(v * max_value)
|
|
19
|
+
}
|
|
20
|
+
return at
|
|
21
|
+
end
|
|
22
|
+
|
|
11
23
|
end
|
|
12
24
|
end
|
data/lib/iStats/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: iStats
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris911
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2017-08-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: sparkr
|
|
@@ -100,6 +100,8 @@ files:
|
|
|
100
100
|
- ext/osx_stats/smc.c
|
|
101
101
|
- ext/osx_stats/smc.h
|
|
102
102
|
- iStats.gemspec
|
|
103
|
+
- integrations/zbx-istats-template.xml
|
|
104
|
+
- integrations/zbx-istats.conf
|
|
103
105
|
- lib/iStats.rb
|
|
104
106
|
- lib/iStats/battery.rb
|
|
105
107
|
- lib/iStats/color.rb
|
|
@@ -134,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
136
|
version: '0'
|
|
135
137
|
requirements: []
|
|
136
138
|
rubyforge_project:
|
|
137
|
-
rubygems_version: 2.
|
|
139
|
+
rubygems_version: 2.6.11
|
|
138
140
|
signing_key:
|
|
139
141
|
specification_version: 4
|
|
140
142
|
summary: Stats for your mac
|