├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .mdl_style.rb
├── .mdlrc
├── .travis.yml
├── CACTI-THOLD-MIB
├── CHANGELOG.md
├── INFO
├── LICENSE
├── README.md
├── cli_import.php
├── cli_thresholds.php
├── extras
├── apply_realms.php
├── index.php
└── upgrade.php
├── images
├── disable_thold.png
├── edit_object.png
├── enable_thold.png
├── graph_create_thold.png
├── index.php
├── reddot.png
├── tab_thold.gif
├── tab_thold_down.gif
├── view_graphs.gif
└── view_log.gif
├── includes
├── arrays.php
├── database.php
├── index.php
├── polling.php
├── settings.php
└── tab.php
├── index.php
├── locales
├── LC_MESSAGES
│ ├── ar-SA.mo
│ ├── bg-BG.mo
│ ├── de-DE.mo
│ ├── el-GR.mo
│ ├── es-ES.mo
│ ├── fr-FR.mo
│ ├── he-IL.mo
│ ├── hi-IN.mo
│ ├── index.php
│ ├── it-IT.mo
│ ├── ja-JP.mo
│ ├── ko-KR.mo
│ ├── nl-NL.mo
│ ├── pl-PL.mo
│ ├── pt-BR.mo
│ ├── pt-PT.mo
│ ├── ru-RU.mo
│ ├── sv-SE.mo
│ ├── tr-TR.mo
│ ├── uk-UA.mo
│ ├── uk.mo
│ ├── vi-VN.mo
│ ├── zh-CN.mo
│ └── zh-TW.mo
├── build_gettext.sh
├── index.php
└── po
│ ├── ar-SA.po
│ ├── bg-BG.po
│ ├── cacti.pot
│ ├── de-DE.po
│ ├── el-GR.po
│ ├── es-ES.po
│ ├── fr-FR.po
│ ├── he-IL.po
│ ├── hi-IN.po
│ ├── index.php
│ ├── it-IT.po
│ ├── ja-JP.po
│ ├── ko-KR.po
│ ├── nl-NL.po
│ ├── pl-PL.po
│ ├── pt-BR.po
│ ├── pt-PT.po
│ ├── ru-RU.po
│ ├── sv-SE.po
│ ├── tr-TR.po
│ ├── uk-UA.po
│ ├── vi-VN.po
│ ├── zh-CN.po
│ └── zh-TW.po
├── notify_lists.php
├── notify_queue.php
├── poller_thold.php
├── service
├── README.md
├── index.php
└── systemd
│ ├── index.php
│ └── thold_daemon.service
├── setup.php
├── themes
├── classic
│ ├── index.php
│ └── main.css
├── dark
│ ├── index.php
│ └── main.css
├── index.php
├── midwinter
│ └── main.css
├── modern
│ ├── index.php
│ └── main.css
├── paper-plane
│ ├── index.php
│ └── main.css
├── paw
│ ├── index.php
│ └── main.css
└── sunrise
│ ├── index.php
│ └── main.css
├── thold.php
├── thold_daemon.php
├── thold_functions.php
├── thold_graph.php
├── thold_notify.php
├── thold_process.php
├── thold_templates.php
└── thold_webapi.php
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
14 |
15 | **Describe the bug**
16 | A clear and concise description of what the bug is.
17 |
18 | **To Reproduce**
19 | Steps to reproduce the behavior:
20 | 1. Go to '...'
21 | 2. Click on '....'
22 | 3. Scroll down to '....'
23 | 4. See error
24 |
25 | **Expected behavior**
26 | A clear and concise description of what you expected to happen.
27 |
28 | **Screenshots**
29 | If applicable, add screenshots to help explain your problem.
30 |
31 | **Plugin (please complete the following information):**
32 | - Version: [e.g. 1.2]
33 | - Source: [e.g. cacti.net, package, github]
34 | - Identifier: [e.g. apt/yum package name or github commit ref]
35 |
36 | **Desktop (please complete the following information):**
37 | - OS: [e.g. iOS]
38 | - Browser [e.g. chrome, safari]
39 | - Version [e.g. 22]
40 |
41 | **Smartphone (please complete the following information):**
42 | - Device: [e.g. iPhone6]
43 | - OS: [e.g. iOS8.1]
44 | - Browser [e.g. stock browser, safari]
45 | - Version [e.g. 22]
46 |
47 | **Additional context**
48 | Add any other context about the problem here.
49 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
14 |
15 | **Is your feature request related to a problem? Please describe.**
16 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
17 |
18 | **Describe the solution you'd like**
19 | A clear and concise description of what you want to happen.
20 |
21 | **Describe alternatives you've considered**
22 | A clear and concise description of any alternative solutions or features you've considered.
23 |
24 | **Additional context**
25 | Add any other context or screenshots about the feature request here.
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # +-------------------------------------------------------------------------+
2 | # | Copyright (C) 2004-2023 The Cacti Group |
3 | # | |
4 | # | This program is free software; you can redistribute it and/or |
5 | # | modify it under the terms of the GNU General Public License |
6 | # | as published by the Free Software Foundation; either version 2 |
7 | # | of the License, or (at your option) any later version. |
8 | # | |
9 | # | This program is distributed in the hope that it will be useful, |
10 | # | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | # | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | # | GNU General Public License for more details. |
13 | # +-------------------------------------------------------------------------+
14 | # | Cacti: The Complete RRDtool-based Graphing Solution |
15 | # +-------------------------------------------------------------------------+
16 | # | This code is designed, written, and maintained by the Cacti Group. See |
17 | # | about.php and/or the AUTHORS file for specific developer information. |
18 | # +-------------------------------------------------------------------------+
19 | # | http://www.cacti.net/ |
20 | # +-------------------------------------------------------------------------+
21 |
22 | locales/po/*.mo
23 |
--------------------------------------------------------------------------------
/.mdl_style.rb:
--------------------------------------------------------------------------------
1 | # +-------------------------------------------------------------------------+
2 | # | Copyright (C) 2004-2023 The Cacti Group |
3 | # | |
4 | # | This program is free software; you can redistribute it and/or |
5 | # | modify it under the terms of the GNU General Public License |
6 | # | as published by the Free Software Foundation; either version 2 |
7 | # | of the License, or (at your option) any later version. |
8 | # | |
9 | # | This program is distributed in the hope that it will be useful, |
10 | # | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | # | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | # | GNU General Public License for more details. |
13 | # +-------------------------------------------------------------------------+
14 | # | Cacti: The Complete RRDtool-based Graphing Solution |
15 | # +-------------------------------------------------------------------------+
16 | # | This code is designed, written, and maintained by the Cacti Group. See |
17 | # | about.php and/or the AUTHORS file for specific developer information. |
18 | # +-------------------------------------------------------------------------+
19 | # | http://www.cacti.net/ |
20 | # +-------------------------------------------------------------------------+
21 |
22 | # customize style guide
23 | all
24 | rule "MD010", code_blocks: false
25 | rule "MD013", code_blocks: false, tables: false
26 | rule "MD029", style: "ordered"
27 | rule "MD046", style: "fenced"
28 |
29 | # Lesser rules
30 | exclude_rule "MD010" # hard tabs
31 | #exclude_rule "MD013" # line length
32 |
33 | # Rule Exclusions
34 | exclude_rule "MD001" # Headers are useful in other ways
35 | exclude_rule "MD024" # Headers with same name are useful, but break link labeling (Rework needed on affected files before enabling this rule)
36 | exclude_rule "MD041" # YAML header is being flagged as not the first
37 | exclude_rule "MD046" # seems broken
38 |
--------------------------------------------------------------------------------
/.mdlrc:
--------------------------------------------------------------------------------
1 | # +-------------------------------------------------------------------------+
2 | # | Copyright (C) 2004-2023 The Cacti Group |
3 | # | |
4 | # | This program is free software; you can redistribute it and/or |
5 | # | modify it under the terms of the GNU General Public License |
6 | # | as published by the Free Software Foundation; either version 2 |
7 | # | of the License, or (at your option) any later version. |
8 | # | |
9 | # | This program is distributed in the hope that it will be useful, |
10 | # | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | # | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | # | GNU General Public License for more details. |
13 | # +-------------------------------------------------------------------------+
14 | # | Cacti: The Complete RRDtool-based Graphing Solution |
15 | # +-------------------------------------------------------------------------+
16 | # | This code is designed, written, and maintained by the Cacti Group. See |
17 | # | about.php and/or the AUTHORS file for specific developer information. |
18 | # +-------------------------------------------------------------------------+
19 | # | http://www.cacti.net/ |
20 | # +-------------------------------------------------------------------------+
21 |
22 | # mdl cli configuration
23 | style ".mdl_style.rb"
24 | verbose false
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | dist: trusty
3 |
4 | php:
5 | - '5.4'
6 | - '5.5'
7 | - '5.6'
8 | - '7.0'
9 | - '7.1'
10 | - '7.2'
11 |
12 | before_script:
13 | - if find . -name "*.php" -exec php -l {} 2>&1 \; | grep -iv "no syntax errors detected"; then exit 1; fi
14 |
15 | script: true
16 |
17 | install: true
18 |
19 | notifications:
20 | email:
21 | on_success: change
22 | on_failure: always
23 | recipients:
24 | - developers@cacti.net
25 | slack:
26 | secure: UMpmQq5QrMxpZBOdMD43Z2KMBIY+HCif8ps1s837ECs6Ue7nOHeNSwnDWcAoJXbUP8FSev32ONEV26ZsYNk1ZSo+Ux/8vaWXZ1CE5IrSXt3XRxCouHuoPb4qMw1D0cw8UA5ARHdfKo/2ifc30Jtaa2LuE4XrPMGpBEjjNBI7O2p5bwKQPzU17D/bIkkF8BQlEKFDa+x4ff5ABQTyAAicIwNOYyYh3XhEdeQLP1OhIyRzXF9ykE+Xf3N6tlS/ymW0FAVt4wYBCb3A9K3wdsLQhjCKlIthbhuFD/vzqEwibTqUXjDECKgNZHVLWUsdpH+810Y7QFEAgDOKVqMLkvQInzecXWtZveY/mEL4KyazMS3n0OuJ886489jZVIQDfKgj4YL64ighzTuhw+gUd2lIgAU/UKQWxWqH3u50344rV13ZqeoeFO3EUuUpv1xmrJEXuB585PwURfZ5lu/OtO3WCAil8NrzbMxp6ji78/wTmdRZ1htmWOZgkEDX+VrnZsmL+JoHmkXVR+afo0kz05+tml01C5Lgx/gMOF87FtKaaeTvW6G0a4rD4438yklQabo+nyuMt7y7nOzvEVk6kARxlgt7cY7Of2M1w3HiHzzvvEIQNCskhjULS0WdPPPiWjb7PbwJvTiC0qAfFbMWnFOLLqQk7sUuh1/cH4wdpa23g5Y=
27 |
--------------------------------------------------------------------------------
/CACTI-THOLD-MIB:
--------------------------------------------------------------------------------
1 | -- *****************************************************************
2 | -- CACTI-THOLD-MIB: Thold Management Information Base for Cacti
3 | --
4 | -- September 2013, Andreas Braun (aka browniebraun)
5 | --
6 | -- Copyright (c) 2004-2023 by The Cacti Group
7 | -- All rights reserved.
8 | --
9 | -- *****************************************************************
10 |
11 | CACTI-THOLD-MIB DEFINITIONS ::= BEGIN
12 |
13 | IMPORTS
14 | OBJECT-TYPE,
15 | MODULE-IDENTITY,
16 | OBJECT-IDENTITY,
17 | NOTIFICATION-TYPE,
18 | Integer32,
19 | IpAddress
20 | FROM SNMPv2-SMI
21 |
22 | OBJECT-GROUP,
23 | NOTIFICATION-GROUP
24 | FROM SNMPv2-CONF
25 |
26 | TEXTUAL-CONVENTION,
27 | DisplayString
28 | FROM SNMPv2-TC
29 |
30 | cactiPlugins
31 | FROM CACTI-MIB
32 | ;
33 |
34 | thold MODULE-IDENTITY
35 | LAST-UPDATED "201309260000Z"
36 | ORGANIZATION "The Cacti Group"
37 | CONTACT-INFO
38 | "The Cacti Group
39 |
40 | E-mail: developers@cacti.net"
41 | DESCRIPTION
42 | "This modules defines a MIB for THOLD, a threshold
43 | monitoring plugin for Cacti."
44 | REVISION "201309260000Z"
45 | DESCRIPTION
46 | "Initial version of this MIB module."
47 | ::= { cactiPlugins 1 } -- assigned by the Cacti Group
48 |
49 | --
50 | -- TEXTUAL CONVENTIONS
51 | --
52 |
53 | --
54 | -- Event Class
55 | --
56 |
57 | TcEventClass ::= TEXTUAL-CONVENTION
58 | STATUS current
59 | DESCRIPTION
60 | "Represents the classification of an event:
61 |
62 | info - threshold item is in normal state
63 | warning - warning condition fulfilled
64 | alert - alerting condition fulfilled "
65 | SYNTAX INTEGER
66 | {
67 | info(1),
68 | warning(2),
69 | alert(3)
70 | }
71 |
72 | --
73 | -- Event Severity
74 | --
75 |
76 | TcEventSeverity ::= TEXTUAL-CONVENTION
77 | STATUS current
78 | DESCRIPTION
79 | "The following are the severities an THOLD event
80 | can have:
81 |
82 | low - informational event,
83 | event with low impact
84 | medium - warning event,
85 | event with medium impact
86 | high - warning event or alert event,
87 | event with high impact
88 | critical - alert event,
89 | event with critical impact "
90 | SYNTAX INTEGER
91 | {
92 | low(1),
93 | medium(2),
94 | high(3),
95 | critical(4)
96 | }
97 |
98 | --
99 | -- Event Threshold Type
100 | --
101 |
102 | TcEventThresholdType ::= TEXTUAL-CONVENTION
103 | STATUS current
104 | DESCRIPTION
105 | "The monitoring type used to verify a threshold
106 | condition:
107 |
108 | highLow - Monitoring if the current value was below a
109 | specific upper and above a specific lower limit
110 | baseline - Monitoring based on deviation in percentage
111 | for the upper and lower bound threshold against a
112 | time reference in the past
113 | timebased - Monitoring if a breach condition was given for a
114 | specific number of times within a specific amount of time
115 | in the past "
116 | SYNTAX INTEGER
117 | {
118 | highLow(1),
119 | baseline(2),
120 | timebased(3)
121 | }
122 |
123 | --
124 | -- Event Notification Type
125 | --
126 |
127 | TcEventNotificationType ::= TEXTUAL-CONVENTION
128 | STATUS current
129 | DESCRIPTION
130 | "Describes the several conditions detected by THOLD
131 | which will end in a notification / alert:
132 |
133 | restoral - not available (restoral)
134 | triggera - not available (trigger alert)
135 | notifyra - Notify Alert Retrigger
136 | notifywa - Notify Warning
137 | notifyal - Notify Alert
138 | notifyrs - Notify Restoral
139 | triggerw - not available (trigger warning)
140 | notifyaw - Notify Restoral to Warning:
141 | This occurs if conditions for an alert state are no
142 | longer breached, but the thresholds for a warning state
143 | are still exceeded. "
144 | SYNTAX INTEGER
145 | {
146 | restoral(1),
147 | triggera(2),
148 | notifyra(3),
149 | notifywa(4),
150 | notifyal(5),
151 | notifyrs(6),
152 | triggerw(7),
153 | notifyaw(8)
154 | }
155 |
156 | --
157 | -- Event Status
158 | --
159 |
160 | TcEventStatus ::= TEXTUAL-CONVENTION
161 | STATUS current
162 | DESCRIPTION
163 | "Represents the state of a threshold:
164 |
165 | normal - Threshold has not been exceeded
166 | low - Lower threshold condition breached
167 | high - Upper threshold condition breached "
168 | SYNTAX INTEGER
169 | {
170 | normal(1),
171 | low(2),
172 | high(3)
173 | }
174 |
175 | --
176 | -- Event Re-Alert Status
177 | --
178 |
179 | TcEventRealertStatus ::= TEXTUAL-CONVENTION
180 | STATUS current
181 | DESCRIPTION
182 | "Represents the long-term state of a threshold:
183 |
184 | normal - Threshold has not been exceeded
185 | low - Lower threshold condition still breached
186 | high - Upper threshold condition still breached "
187 | SYNTAX INTEGER
188 | {
189 | normal(1),
190 | low(2),
191 | high(3)
192 | }
193 |
194 | --
195 | -- THOLD APPLICATION DATA
196 | --
197 | tholdAppl OBJECT-IDENTITY
198 | STATUS current
199 | DESCRIPTION
200 | "reserved for Thold application data"
201 | ::= { thold 1 }
202 |
203 | --
204 | -- THOLD Statistics
205 | --
206 | tholdStats OBJECT-IDENTITY
207 | STATUS current
208 | DESCRIPTION
209 | "reserved for statistics"
210 | ::= { thold 2 }
211 |
212 | --
213 | -- THOLD Events
214 | --
215 | tholdEvents OBJECT-IDENTITY
216 | STATUS current
217 | DESCRIPTION
218 | "reserved for events"
219 | ::= { thold 3 }
220 |
221 | tholdEventObjects OBJECT-IDENTITY
222 | STATUS current
223 | DESCRIPTION
224 | "reserved for event attributes"
225 | ::= { tholdEvents 1 }
226 |
227 | eventDateRFC822 OBJECT-TYPE
228 | SYNTAX DisplayString (SIZE(1..48))
229 | MAX-ACCESS accessible-for-notify
230 | STATUS current
231 | DESCRIPTION
232 | "The current date/time of when the event was detected by Thold."
233 | ::= { tholdEventObjects 1 }
234 |
235 | eventClass OBJECT-TYPE
236 | SYNTAX TcEventClass
237 | MAX-ACCESS accessible-for-notify
238 | STATUS current
239 | DESCRIPTION
240 | "Represents the classification of an event:
241 |
242 | info - threshold item is in normal state
243 | warning - warning condition fulfilled
244 | alert - alerting condition fulfilled "
245 | DEFVAL { alert }
246 | ::= { tholdEventObjects 2 }
247 |
248 | eventSeverity OBJECT-TYPE
249 | SYNTAX TcEventSeverity
250 | MAX-ACCESS accessible-for-notify
251 | STATUS current
252 | DESCRIPTION
253 | "The following are the severities an THOLD event
254 | can have:
255 |
256 | low - informational event,
257 | event with low impact
258 | medium - warning event,
259 | event with medium impact
260 | high - warning event or alert event,
261 | event with high impact
262 | critical - alert event,
263 | event with critical impact "
264 | DEFVAL { high }
265 | ::= { tholdEventObjects 3 }
266 |
267 | eventCategory OBJECT-TYPE
268 | SYNTAX DisplayString (SIZE(1..255))
269 | MAX-ACCESS accessible-for-notify
270 | STATUS current
271 | DESCRIPTION
272 | "To allow a NMS to categorize different SNMP traps THOLD SNMP traps
273 | this object can be used to define a custom category
274 | like 'disk_usage', 'link_utilization' or 'ping_test'."
275 | DEFVAL { "" }
276 | ::= { tholdEventObjects 4 }
277 |
278 | eventSource OBJECT-TYPE
279 | SYNTAX DisplayString (SIZE(1..255))
280 | MAX-ACCESS accessible-for-notify
281 | STATUS current
282 | DESCRIPTION
283 | "Contains the threshold name to identify the threshold (source)
284 | generating this event."
285 | DEFVAL { "" }
286 | ::= { tholdEventObjects 5 }
287 |
288 | eventDescription OBJECT-TYPE
289 | SYNTAX DisplayString (SIZE(1..1000))
290 | MAX-ACCESS accessible-for-notify
291 | STATUS current
292 | DESCRIPTION
293 | "Contains a customized event description."
294 | DEFVAL { "Threshold exceeded" }
295 | ::= { tholdEventObjects 6 }
296 |
297 | eventDevice OBJECT-TYPE
298 | SYNTAX DisplayString (SIZE(1..255))
299 | MAX-ACCESS accessible-for-notify
300 | STATUS current
301 | DESCRIPTION
302 | "This item describes the device name this event is related to."
303 | DEFVAL { "" }
304 | ::= { tholdEventObjects 7 }
305 |
306 | eventDeviceIp OBJECT-TYPE
307 | SYNTAX IpAddress
308 | MAX-ACCESS accessible-for-notify
309 | STATUS current
310 | DESCRIPTION
311 | "IPv4 address of the device the event is related to."
312 | DEFVAL { "0.0.0.0" }
313 | ::= { tholdEventObjects 8 }
314 |
315 | eventDataSource OBJECT-TYPE
316 | SYNTAX DisplayString (SIZE(1..255))
317 | MAX-ACCESS accessible-for-notify
318 | STATUS current
319 | DESCRIPTION
320 | "Identifies the rrd data source being used for this threshold
321 | monitor."
322 | DEFVAL { "" }
323 | ::= { tholdEventObjects 9 }
324 |
325 | eventCurrentValue OBJECT-TYPE
326 | SYNTAX DisplayString (SIZE(1..255))
327 | MAX-ACCESS accessible-for-notify
328 | STATUS current
329 | DESCRIPTION
330 | "The current value of the data source that caused this event."
331 | DEFVAL { "" }
332 | ::= { tholdEventObjects 10 }
333 |
334 | eventHigh OBJECT-TYPE
335 | SYNTAX DisplayString (SIZE(1..255))
336 | MAX-ACCESS accessible-for-notify
337 | STATUS current
338 | DESCRIPTION
339 | "In relation to eventClass this object describes the upper
340 | limit for a warning or an alerting condition.
341 | If eventCurrentValue is higher than this upper limit
342 | an event will be triggered"
343 | DEFVAL { "" }
344 | ::= { tholdEventObjects 11 }
345 |
346 | eventLow OBJECT-TYPE
347 | SYNTAX DisplayString (SIZE(1..255))
348 | MAX-ACCESS accessible-for-notify
349 | STATUS current
350 | DESCRIPTION
351 | "In relation to eventClass this object describes the lower
352 | limit for a warning or an alerting condition.
353 | If eventCurrentValue is below this limit an event will
354 | be triggered"
355 | DEFVAL { "" }
356 | ::= { tholdEventObjects 12 }
357 |
358 | eventThresholdType OBJECT-TYPE
359 | SYNTAX TcEventThresholdType
360 | MAX-ACCESS accessible-for-notify
361 | STATUS current
362 | DESCRIPTION
363 | "The monitoring type used to verify a threshold
364 | condition:
365 |
366 | highLow - Monitoring if the current value was below a
367 | specific upper and above a specific lower limit
368 | baseline - Monitoring based on deviation in percentage
369 | for the upper and lower bound threshold against a
370 | time reference in the past
371 | timebased - Monitoring if a breach condition was given for a
372 | specific number of times within a specific amount of time
373 | in the past "
374 | DEFVAL { baseline }
375 | ::= { tholdEventObjects 13 }
376 |
377 | eventNotificationType OBJECT-TYPE
378 | SYNTAX TcEventNotificationType
379 | MAX-ACCESS accessible-for-notify
380 | STATUS current
381 | DESCRIPTION
382 | "Describes the several conditions detected by THOLD
383 | which will end in a notification / alert:
384 |
385 | restoral - not available (restoral)
386 | triggera - not available (trigger alert)
387 | notifyra - Notify Alert Retrigger
388 | notifywa - Notify Warning
389 | notifyal - Notify Alert
390 | notifyrs - Notify Restoral
391 | triggerw - not available (trigger warning)
392 | notifyaw - Notify Restoral to Warning:
393 | This occurs if conditions for an alert state are no
394 | longer breached, but the thresholds for a warning state
395 | are still exceeded. "
396 | DEFVAL { notifyal }
397 | ::= { tholdEventObjects 14 }
398 |
399 | eventStatus OBJECT-TYPE
400 | SYNTAX TcEventStatus
401 | MAX-ACCESS accessible-for-notify
402 | STATUS current
403 | DESCRIPTION
404 | "Represents the state of a threshold:
405 |
406 | normal - Threshold has not been exceeded
407 | low - Lower threshold condition breached
408 | high - Upper threshold condition breached "
409 | DEFVAL { high }
410 | ::= { tholdEventObjects 15 }
411 |
412 | eventRealertStatus OBJECT-TYPE
413 | SYNTAX TcEventRealertStatus
414 | MAX-ACCESS accessible-for-notify
415 | STATUS current
416 | DESCRIPTION
417 | "Represents the long-term state of a threshold:
418 |
419 | normal - Threshold has not been exceeded
420 | low - Lower threshold condition still breached
421 | high - Upper threshold condition still breached "
422 | DEFVAL { normal }
423 | ::= { tholdEventObjects 16 }
424 |
425 | eventFailDuration OBJECT-TYPE
426 | SYNTAX Integer32
427 | MAX-ACCESS accessible-for-notify
428 | STATUS current
429 | DESCRIPTION
430 | "Describes the amount of time in seconds the data source
431 | is in a breach condition."
432 | DEFVAL { 0 }
433 | ::= { tholdEventObjects 17 }
434 |
435 | eventFailCount OBJECT-TYPE
436 | SYNTAX Integer32
437 | MAX-ACCESS accessible-for-notify
438 | STATUS current
439 | DESCRIPTION
440 | "Describes the number of times the data source
441 | is in a breach condition."
442 | DEFVAL { 0 }
443 | ::= { tholdEventObjects 18 }
444 |
445 | eventFailDurationTrigger OBJECT-TYPE
446 | SYNTAX Integer32
447 | MAX-ACCESS accessible-for-notify
448 | STATUS current
449 | DESCRIPTION
450 | "Describes the amount of time in seconds the data source
451 | must be in a breach condition for an alert or warning
452 | to be raised. "
453 | DEFVAL { 0 }
454 | ::= { tholdEventObjects 19}
455 |
456 | eventFailCountTrigger OBJECT-TYPE
457 | SYNTAX Integer32
458 | MAX-ACCESS accessible-for-notify
459 | STATUS current
460 | DESCRIPTION
461 | "Describes the number of times the data source
462 | must be in a breach condition for an alert or warning
463 | to be raised. "
464 | DEFVAL { 0 }
465 | ::= { tholdEventObjects 20 }
466 |
467 | --
468 | -- THOLD Event Notifications
469 | --
470 | tholdEventNotifications OBJECT-IDENTITY
471 | STATUS current
472 | DESCRIPTION
473 | "reserved for event attributes"
474 | ::= { tholdEvents 2 }
475 |
476 | tholdNotify NOTIFICATION-TYPE
477 | OBJECTS {
478 | eventDateRFC822,
479 | eventClass,
480 | eventSeverity,
481 | eventCategory,
482 | eventSource,
483 | eventDescription,
484 | eventDevice,
485 | eventDeviceIp,
486 | eventDataSource,
487 | eventCurrentValue,
488 | eventHigh,
489 | eventLow,
490 | eventThresholdType,
491 | eventNotificationType,
492 | eventStatus,
493 | eventRealertStatus,
494 | eventFailDuration,
495 | eventFailCount,
496 | eventFailDurationTrigger,
497 | eventFailCountTrigger
498 | }
499 | STATUS current
500 | DESCRIPTION
501 | "The SNMP trap that is generated as a result of an event with Thold."
502 | ::= { tholdEventNotifications 1 }
503 |
504 | --
505 | -- THOLD MIB Groups
506 | --
507 | tholdMibGroups OBJECT-IDENTITY
508 | STATUS current
509 | DESCRIPTION
510 | "reserved for group definitions"
511 | ::= { thold 4 }
512 |
513 | tholdEventGroup OBJECT-GROUP
514 | OBJECTS {
515 | eventDateRFC822,
516 | eventClass,
517 | eventSeverity,
518 | eventCategory,
519 | eventSource,
520 | eventDescription,
521 | eventDevice,
522 | eventDeviceIp,
523 | eventDataSource,
524 | eventCurrentValue,
525 | eventHigh,
526 | eventLow,
527 | eventThresholdType,
528 | eventNotificationType,
529 | eventStatus,
530 | eventRealertStatus,
531 | eventFailDuration,
532 | eventFailCount,
533 | eventFailDurationTrigger,
534 | eventFailCountTrigger
535 | }
536 | STATUS current
537 | DESCRIPTION
538 | "A collection of objects providing the THOLD event
539 | defaults."
540 | ::= { tholdMibGroups 1 }
541 |
542 | tholdNotifyGroup NOTIFICATION-GROUP
543 | NOTIFICATIONS {
544 | tholdNotify
545 | }
546 | STATUS current
547 | DESCRIPTION
548 | "The notifications relating to the monitoring operation of Thold."
549 | ::= { tholdMibGroups 2 }
550 |
551 | END
--------------------------------------------------------------------------------
/INFO:
--------------------------------------------------------------------------------
1 | ; +-------------------------------------------------------------------------+
2 | ; | Copyright (C) 2004-2024 The Cacti Group |
3 | ; | |
4 | ; | This program is free software; you can redistribute it and/or |
5 | ; | modify it under the terms of the GNU General Public License |
6 | ; | as published by the Free Software Foundation; either version 2 |
7 | ; | of the License, or (at your option) any later version. |
8 | ; | |
9 | ; | This program is distributed in the hope that it will be useful, |
10 | ; | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | ; | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | ; | GNU General Public License for more details. |
13 | ; +-------------------------------------------------------------------------+
14 | ; | Cacti: The Complete RRDtool-based Graphing Solution |
15 | ; +-------------------------------------------------------------------------+
16 | ; | This code is designed, written, and maintained by the Cacti Group. See |
17 | ; | about.php and/or the AUTHORS file for specific developer information. |
18 | ; +-------------------------------------------------------------------------+
19 | ; | http://www.cacti.net/ |
20 | ; +-------------------------------------------------------------------------+
21 |
22 | [info]
23 | name = thold
24 | version = 1.8.2
25 | longname = Thresholds
26 | author = The Cacti Group
27 | email =
28 | homepage = http://www.cacti.net
29 | compat = 1.2.25
30 | capabilities = online_view:1, online_mgmt:1, offline_view:0, offline_mgmt:0, remote_collect:1
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # thold
2 |
3 | The Cacti thold plugin is designed to be a fault management system driven by
4 | Cacti's Graph information. It provides the facility to inspect data in a Cacti
5 | Graph and the underlying RRDfile, and generate alerts for management and
6 | operations personnel. It provides Email, Syslog, and SNMP Trap or Inform
7 | escalations. In addition, it also can notify personnel of Cacti Device status
8 | changes through Email, Syslog, and either SNMP Trap or Inform.
9 |
10 | NOTE: The Thold plugin that is in GitHub is ONLY compatible with Cacti 1.0.0 and
11 | above!
12 |
13 | ## Installation
14 |
15 | To install the plugin, simply copy the plugin_thold directory to Cacti's plugins
16 | directory and rename it to simply 'thold'. Once this is complete, go to Cacti's
17 | Plugin Management section, and Install and Enable the plugin. Once this is
18 | complete, you can grant users permission to view and create Thresholds.
19 |
20 | Once you have installed thold, you should verify that Email support is
21 | functioning in Cacti by going to Cacti's Console and under Configuration select
22 | Settings, and from there the 'Mail/Reporting/DNS'. From there, you can test
23 | your mail settings to validate that users will receive notifications via email.
24 |
25 | After you have completed that, you should go to the 'Thresholds' Settings tab,
26 | and become familiar with its settings. From there, you can provide overall
27 | control of thold, and set defaults for things like Email bodies, weekend
28 | exemptions, alert log retention, logging, etc.
29 |
30 | As with much of Cacti, settings should be documented in line with the actual
31 | setting. If you find that any of these settings are ambiguous, please create a
32 | pull request with your proposed changes.
33 |
34 | ## Usage
35 |
36 | The Cacti 1.0 version of thold is designed to work with Device Templates.
37 | Therefore, when you configure a Device Template, you can add default Threshold
38 | Templates to that Device Template and when a Device in Cacti is created with
39 | that Device Template, all the required Thresholds will be created automatically.
40 | Of course, creating stand-alone Thresholds is still supported.
41 |
42 | Also new in thold version 1.0 is the ability to create multiple Thresholds per
43 | Data Source. So, you can have a Baseline Threshold say measuring the rate of
44 | change of a file system, while at the same having a Hi/Low and Time Based
45 | thresholds to notify you of free space low type of events.
46 |
47 | Most standalone Thresholds are created from the Graph Management interface in
48 | Cacti. This process starts with first creating a Threshold Template for the
49 | specific Graph Template in question, and then from Graph Management selecting
50 | the Graphs that you wish to apply this Template to. Then, from the Cacti
51 | Actions drop down, select 'Create Threshold from Template' and simply select
52 | your desired Threshold Template. Though this method continues to work today, we
53 | believe that with the support of associating Threshold Templates with Device
54 | Templates, that this method will become less popular over time.
55 |
56 | When creating your first Threshold using thold, you need to be first understand
57 | the Threshold Type. They include: High / Low, Time Based, and Baseline
58 | Deviation. The High / Low are the easiest to understand. If the measured value
59 | falls either above or below the High / Low values, for the Min Trigger Duration
60 | specified in the High / Low section, it will trigger an alert. In the Time
61 | Based Threshold type, the measured value must go above or below the High / Low
62 | values so many times in the measurement window, or the 'Time Period Length'.
63 | Lastly, the Baseline Deviation provides a floating window in the 'Time reference
64 | in the past' to measure change. If the change in the measured value either goes
65 | up or down by a certain value in that time period, an alert will be triggered.
66 |
67 | The Re-Alert Cycle is how often you wish to re-inform either via Email, Syslog,
68 | or SNMP Trap or Inform if the Threshold has not resolved itself before then.
69 |
70 | Thold has multiple Data Manipulation types, including: Exact Value, CDEF,
71 | Percentage, and RPN Expression. The simplest form is the Exact Value data
72 | manipulation where thold simply takes the raw value collected from Cacti's Data
73 | Collector, and applies rules to it. In the case of COUNTER type data, thold
74 | will convert that to a relative value automatically. The CDEF data manipulation
75 | allows you to use some, but not all Cacti CDEF's and apply them to Graph Data.
76 | The CDEF's that work, have to leverage one or more of the special types included
77 | in Cacti's CDEF implementation like 'CURRENT_DATASOURCE' to be relative. The
78 | Percentage Data Manipulation requires you to select the 'primary' Data Source as
79 | the Numerator, and then when selecting 'Percentage', you will be able to select
80 | the Denominator of the percentage calculation. The most involved Data
81 | Manipulation is the RPN Expression type. This Data Manipulation type allows you
82 | to use RPN Expressions to determine the value to be evaluated. It can include
83 | other Data Sources in the Cacti graph in addition to the selected Data Source.
84 | It follows closely RRDtool's RPN logic, and most RRDtool RPN functions are
85 | supported.
86 |
87 | If you plan on using the Threshold Daemon to increase the scalability of your
88 | thresholds, note that you must modify and install the thold_daemon.service file
89 | into your systemd configuration, and then start and test the service. If you
90 | fail to perform these steps, thold will appear to not work as expected.
91 |
92 | Lastly, please note that several forks of the thold plugin are available from
93 | different sources. These forks of thold are not necessarily compatible with the
94 | current version of Cacti's thold plugin. Please be aware of this when
95 | installing thold for the first time.
96 |
97 | ## Authors
98 |
99 | The thold plugin has been in development for well over a decade with increasing
100 | functionality and stability over that time. There have been several
101 | contributors to thold over the years. Chief among them are Jimmy Conner, Larry
102 | Adams, and Andreas Braun. We hope that version 1.0 and beyond are the most
103 | stable and robust versions of thold ever published. We are always looking for
104 | new ideas. So, this won't be the last release of thold, you can rest assured of
105 | that.
106 |
107 | -----------------------------------------------
108 | Copyright (c) 2004-2024 - The Cacti Group, Inc.
109 |
--------------------------------------------------------------------------------
/cli_import.php:
--------------------------------------------------------------------------------
1 | $message) {
168 | if (strpos($message_id, 'thold_message') !== false) {
169 | print strip_tags(str_replace('
', PHP_EOL, $message['message'])) . PHP_EOL;
170 | }
171 | }
172 | }
173 | }
174 |
175 | function display_version() {
176 | global $config;
177 | if (!function_exists('plugin_thold_version')) {
178 | include_once($config['base_path'] . '/plugins/thold/setup.php');
179 | }
180 |
181 | $info = plugin_thold_version();
182 | print 'Threshold Command Line Interface, Version ' . $info['version'] . ', ' . COPYRIGHT_YEARS . PHP_EOL;
183 | }
184 |
185 |
186 | /* display_help - displays the usage of the function */
187 | function display_help () {
188 | display_version();
189 |
190 | print PHP_EOL;
191 |
192 | print 'usage: cli_thresholds.php --auto-create=N | [--host-ids=\'N1 N2 ...\'] [--graph-template=N] [--thold-template=N] [--graph-ids=\'N1 N2 ...\']' . PHP_EOL . PHP_EOL;
193 |
194 | print 'There are two usage methods:' . PHP_EOL . PHP_EOL;
195 |
196 | print 'The first requires you to specify the host id of the device and all existing Threshold templates' . PHP_EOL;
197 | print 'are applied to hosts.' . PHP_EOL . PHP_EOL;
198 | print '--auto-create=N - Auto Create all Thresholds for this Device id using Templates associated' . PHP_EOL;
199 | print ' the Devices Device Template.' . PHP_EOL . PHP_EOL;
200 |
201 | print 'The second requires you to specify either a series of Devices, a Graph Template, a Threshold Template' . PHP_EOL;
202 | print 'or a series of Graphs or any combination of the above. However, at least one must be specified.' . PHP_EOL;
203 | print 'Threshold Template and Graph IDs of the Graphs to be impacted.' . PHP_EOL . PHP_EOL;
204 | print '--host-ids=\'N1 N2 ...\' - The Devices ID to create Thresholds for' . PHP_EOL;
205 | print '--graph-template=N - The Graph Template to create Thresholds for' . PHP_EOL;
206 | print '--thold-template=N - The Threshold Template to use for creating Thresholds' . PHP_EOL;
207 | print '--graph-ids=\'N1 N2 ...\' - The Threshold Template to use for creating Thresholds' . PHP_EOL . PHP_EOL;
208 | }
209 |
210 |
--------------------------------------------------------------------------------
/extras/apply_realms.php:
--------------------------------------------------------------------------------
1 |
';
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | /dev/null`
28 | if [ $? -gt 0 ]
29 | then
30 | echo "ERROR: unable to locate realpath"
31 | echo
32 | echo "Linux: Confirm coreutils installed"
33 | echo "Mac: Brew install coreutils"
34 | echo
35 | exit 1
36 | fi
37 | BASE_PATH=`${REALPATH_BIN} ${0} | sed s#/locales/${SCRIPT_NAME}##`
38 |
39 | # locate xgettext for processing
40 | XGETTEXT_BIN=`which xgettext 2>/dev/null`
41 | if [ $? -gt 0 ]
42 | then
43 | echo "ERROR: Unable to locate xgettext"
44 | echo
45 | echo "Linux: Install GNU gettext"
46 | echo "Mac: Brew install GNU gettext"
47 | echo
48 | exit 1
49 | fi
50 |
51 | # Update main gettext POT file with application strings
52 | echo "Updating Cacti language gettext language file..."
53 | cd ${BASE_PATH}
54 |
55 | ${XGETTEXT_BIN} --no-wrap --copyright-holder="The Cacti Group" --package-name="Cacti" --package-version=`cat include/cacti_version` --msgid-bugs-address="developers@cacti.net" -F -k__gettext -k__ -k__n:1,2 -k__x:1c,2 -k__xn:1c,2,3 -k__esc -k__esc_n:1,2 -k__esc_x:1c,2 -k__esc_xn:1c,2,3 -k__date -o locales/po/cacti.pot `find . -maxdepth 2 -name \*.php`
56 |
57 | sed -i 's/FULL NAME /Cacti Developers /g' locales/po/cacti.pot
58 | sed -i 's/LANGUAGE /Cacti Developers /g' locales/po/cacti.pot
59 | sed -i 's/CHARSET/UTF-8/g' locales/po/cacti.pot
60 |
61 | # Merge any changes to POT file into language files
62 | echo "Merging updates to language files..."
63 |
64 | for file in `ls -1 locales/po/*.po`;do
65 | echo "Updating $file from cacti.pot"
66 | msgmerge --backup off --no-wrap --update -F $file locales/po/cacti.pot
67 | done
68 |
69 | for file in `ls -1 locales/po/*.po`;do
70 | ofile=$(basename --suffix=.po ${file})
71 | echo "Converting $file to LC_MESSAGES/${ofile}.mo"
72 | msgfmt ${file} -o locales/LC_MESSAGES/${ofile}.mo
73 | done
74 |
75 | exit 0
76 |
--------------------------------------------------------------------------------
/locales/index.php:
--------------------------------------------------------------------------------
1 | 0) {
213 | if (empty($heartbeat)) {
214 | $last_notification = read_config_option('thold_daemon_down_notify_time');
215 |
216 | if ($curtime - $last_notification > $frequency) {
217 | admin_email('Thold Daemon Not Started', 'WARNING: You have elected to use the Thold Daemon, but it appears not to be running. Please correct this right away');
218 | set_config_option('thold_daemon_down_notify_time', $curtime);
219 | }
220 | } elseif ($now - $heartbeat > 3 * $poller_interval) {
221 | $last_notification = read_config_option('thold_daemon_down_notify_time');
222 |
223 | if ($curtime - $last_notification > $frequency) {
224 | admin_email('Thold Daemon Down', 'WARNING: You have elected to use the Thold Daemon, but it appears have stopped running. Please correct this right away');
225 | set_config_option('thold_daemon_down_notify_time', $curtime);
226 | }
227 | }
228 | }
229 |
230 | $threads = read_config_option('thold_max_concurrent_processes');
231 |
232 | if (read_config_option('remote_storage_method') == 1) {
233 | /* host_status processed by thold server */
234 | $nhosts = thold_update_host_status();
235 |
236 | thold_cleanup_log();
237 |
238 | $total_hosts = db_fetch_cell_prepared('SELECT COUNT(*)
239 | FROM host
240 | WHERE disabled = ""
241 | AND poller_id = ?',
242 | array($config['poller_id']));
243 |
244 | $down_hosts = db_fetch_cell_prepared('SELECT COUNT(*)
245 | FROM host
246 | WHERE status = 1
247 | AND disabled = ""
248 | AND poller_id = ?',
249 | array($config['poller_id']));
250 |
251 | $thresholds = db_fetch_cell_prepared('SELECT COUNT(*)
252 | FROM thold_data
253 | INNER JOIN host
254 | ON host.id = thold_data.host_id
255 | WHERE poller_id = ?
256 | AND disabled = ""',
257 | array($config['poller_id']));
258 | } else {
259 | /* host_status processed by thold server */
260 | $nhosts = thold_update_host_status();
261 |
262 | thold_cleanup_log();
263 |
264 | $total_hosts = db_fetch_cell('SELECT COUNT(*)
265 | FROM host
266 | WHERE disabled=""');
267 |
268 | $down_hosts = db_fetch_cell('SELECT COUNT(*)
269 | FROM host
270 | WHERE status = 1
271 | AND disabled = ""');
272 |
273 | $thresholds = db_fetch_cell('SELECT COUNT(*)
274 | FROM thold_data
275 | INNER JOIN host
276 | ON host.id = thold_data.host_id
277 | WHERE disabled = ""');
278 | }
279 |
280 | thold_prune_old_data();
281 |
282 | /* record the end time */
283 | $end = microtime(true);
284 |
285 | /* log statistics */
286 | $thold_stats = sprintf('Time:%0.2f TotalDevices:%u DownDevices:%u NewDownDevices:%u Threads:%u Thresholds:%u',
287 | $end - $start, $total_hosts, $down_hosts, $nhosts, $threads, $thresholds);
288 |
289 | cacti_log('THOLD POLLER STATS: ' . $thold_stats, false, 'SYSTEM');
290 |
291 | set_config_option('stats_thold_' . $config['poller_id'], $thold_stats);
292 | }
293 | }
294 |
295 | /**
296 | * display_version - displays version information
297 | */
298 | function display_version() {
299 | global $config;
300 |
301 | if (!function_exists('plugin_thold_version')) {
302 | include_once($config['base_path'] . '/plugins/thold/setup.php');
303 | }
304 |
305 | $info = plugin_thold_version();
306 |
307 | print "Cacti Thold Master Process, Version " . $info['version'] . ", " . COPYRIGHT_YEARS . "\n";
308 | }
309 |
310 | /**
311 | * display_help - displays the usage of the function
312 | */
313 | function display_help () {
314 | display_version();
315 |
316 | print "\nusage: poller_thold.php [--debug] [--force]\n\n";
317 | print "This binary run various Threshold data collection and\n";
318 | print "Management function.\n\n";
319 | print "--force - Force all the service checks to run now\n";
320 | print "--debug - Display verbose output during execution\n\n";
321 | }
322 |
323 |
--------------------------------------------------------------------------------
/service/README.md:
--------------------------------------------------------------------------------
1 | # thold daemon installation
2 |
3 | ## Introduction
4 |
5 | The thold daemon was designed to improve Cacti's scalability by allowing the
6 | thold check process to take place out of band. By doing so, the time Cacti
7 | spends checking thresholds can be reduced significantly. This service folder
8 | includes initialization scripts for both systemd and initd based systems. To
9 | install the thold daemon as a service, follow the instructions below.
10 |
11 | ## SystemD Based Systems
12 |
13 | Follow the steps below to install the thold daemon on a SystemD system.
14 |
15 | * Verify the location of the thold_daemon.php in the systemd subfolder of the
16 | location of this README.md file.
17 |
18 | * You may have to change mariadb.service to mysql.service depending on your
19 | installed version of MariaDB or MySQL.
20 |
21 | * Update the to point to you Cacti base path.
22 |
23 | * Copy the `thold_daemon.service` file to systemd directory and then reload the
24 | systemd daemon so that it knows the new service is available.
25 |
26 | ```shell
27 | cp thold_daemon.service /etc/systemd/system
28 | systemctl daemon-reload
29 | ```
30 |
31 | * Edit the `thold_daemon.service` file and update the ExecStart/ExecStop paths
32 | with the location of the `thold_daemon` shell script. By default, this script
33 | is found in the [cacti]/plugin/thold/service/systemd folder, but the service
34 | file is currently hardcoded to expect [cacti] is located at:
35 |
36 | /var/www/html/cacti
37 |
38 | * Ensure that the `thold_daemon` script is marked executable
39 |
40 | ```shell
41 | chmod +x thold_daemon.php
42 | ```
43 |
44 | * Enable and start the service using either the -now parameter:
45 |
46 | ```shell
47 | systemctl enable --now thold_daemon
48 | ```
49 |
50 | or issuing two separate commands if you want to start at a later date:
51 |
52 | ```shell
53 | systemctl enable thold_daemon
54 | systemctl start thold_daemon
55 | ```
56 |
57 | * Running on Windows? Switch to Linux!
58 |
59 | * System V init? Upgrade your Linux!
60 |
61 | -----------------------------------------------
62 | Copyright (c) 2004-2024 - The Cacti Group, Inc.
63 |
--------------------------------------------------------------------------------
/service/index.php:
--------------------------------------------------------------------------------
1 | to your installed Cacti directory
27 | # - Change the mariadb.service to mysql.service if using the MySQL database
28 | #
29 | # Then follow these steps:
30 | #
31 | # - copy this file into /etc/systemd/system directory
32 | # - run 'systemctl daemon-reload'
33 | # - start the service using 'systemctl start thold_daemon'
34 | # - check that the process is running using 'systemctl status thold_daemon'
35 | # - enable the Thold Daemon from Console > Configuration > Settings > Thold/Alerting
36 |
37 | [Unit]
38 | Description=Cacti Threshold Daemon Service
39 | Requires=mariadb.service
40 | After=network.target auditd.service mariadb.service
41 |
42 | [Service]
43 | User=apache
44 | Group=root
45 | Type=forking
46 | ExecStart=/usr/bin/php /plugins/thold/thold_daemon.php
47 | KillMode=process
48 | Restart=on-failure
49 |
50 | [Install]
51 | WantedBy=multi-user.target
52 |
--------------------------------------------------------------------------------
/themes/classic/index.php:
--------------------------------------------------------------------------------
1 | 0) {
119 | print 'The Thold Daemon is still running' . PHP_EOL;
120 | exit(1);
121 | } else {
122 | unregister_process('thold', 'parent', 0);
123 | register_process_start('thold', 'parent', 0, $timeout);
124 | }
125 | }
126 | }
127 |
128 | /* do not run the thold daemon on the remote server in central storage mode */
129 | if (read_config_option('remote_storage_method') != 1 && $config['poller_id'] > 1) {
130 | print 'In Central Storage Mode, the thold_daemon only runs on the main data collector.' . PHP_EOL;
131 | exit(1);
132 | }
133 |
134 | print 'Starting Thold Daemon ... ';
135 |
136 | if (!$foreground) {
137 | if (function_exists('pcntl_fork')) {
138 | // Close the database connection
139 | db_close();
140 |
141 | // Fork the current process to daemonize
142 | $pid = pcntl_fork();
143 |
144 | if ($pid == -1) {
145 | // oha ... something went wrong :(
146 | print '[FAILED]' . PHP_EOL;
147 |
148 | return false;
149 | } elseif ($pid == 0) {
150 | // We are the child reconnect
151 | db_connect_real($database_hostname, $database_username, $database_password, $database_default, $database_type, $database_port, $database_retries, $database_ssl, $database_ssl_key, $database_ssl_cert, $database_ssl_ca);
152 | } else {
153 | cacti_log('NOTE: Thold Daemon Started on ' . gethostname(), false, 'THOLD');
154 |
155 | // We are the parent, output and exit
156 | print '[OK]' . PHP_EOL;
157 |
158 | exit;
159 | }
160 | } else {
161 | // Windows.... awesome! But no worries
162 | print '[WARNING] This system does not support forking.' . PHP_EOL;
163 | }
164 | } else {
165 | print '[NOTE] The Thold Daemon is running in foreground mode.' . PHP_EOL;
166 | }
167 |
168 | sleep(2);
169 |
170 | $processes = read_config_option('thold_max_concurrent_processes');
171 |
172 | thold_truncate_daemon_data();
173 |
174 | thold_prime_distribution($processes);
175 |
176 | thold_daemon_debug('Forking Thold Daemon Child Processes');
177 |
178 | for($i = 1; $i <= $processes; $i++) {
179 | thold_launch_worker($i);
180 | }
181 |
182 | $prev_running = false;
183 | $start_daemon_items = 0;
184 | $counter = 0;
185 |
186 | while (true) {
187 | if (db_check_reconnect()) {
188 | $counter++;
189 |
190 | // force the check for the daemon debug
191 | $daemon_debug = read_config_option('thold_daemon_debug', true);
192 |
193 | if ($counter == 1) {
194 | thold_daemon_debug('Thold Thread Watchdog Start.');
195 |
196 | set_config_option('thold_daemon_heartbeat', microtime(true));
197 | }
198 |
199 | $running = thold_poller_running();
200 |
201 | if ($running && !$prev_running) {
202 | $start = microtime(true);
203 |
204 | thold_daemon_debug('Detected Cacti Poller Start at ' . date('Y-m-d H:i:s'));
205 |
206 | $start_items = db_fetch_cell('SELECT COUNT(*) FROM plugin_thold_daemon_data');
207 | $prev_running = true;
208 | } elseif (!$running && $prev_running) {
209 | $end_items = db_fetch_cell('SELECT COUNT(*) FROM plugin_thold_daemon_data');
210 | $prev_running = false;
211 |
212 | $tholds = db_fetch_cell('SELECT COUNT(*) FROM thold_data WHERE thold_enabled = "on"');
213 |
214 | thold_daemon_debug(sprintf('Detected Cacti Poller End at %s.', date('Y-m-d H:i:s')));
215 | thold_daemon_debug(sprintf('TotalTholds:%u StartingTholds:%u, EndingTholds:%u', $tholds, $start_items, $end_items));
216 |
217 | $end = microtime(true);
218 |
219 | cacti_log(sprintf('THOLD DAEMON STATS: TotalTime:%3.2f TotalTholds:%u StartingItems:%u EndingItems:%u',
220 | $end - $start, $tholds, $start_items, $end_items), false, 'SYSTEM');
221 | } else {
222 | $prev_running = $running;
223 | }
224 |
225 | sleep(1);
226 |
227 | if ($counter == 10) {
228 | $counter = 0;
229 |
230 | $new_processes = read_config_option('thold_max_concurrent_processes', true);
231 |
232 | if ($new_processes != $processes) {
233 | thold_prime_distribution($new_processes, true);
234 | } else {
235 | thold_prime_distribution($new_processes);
236 | }
237 |
238 | thold_heartbeat_processes($processes, $new_processes);
239 |
240 | $processes = $new_processes;
241 |
242 | thold_daemon_debug('Thold Thread Watchdog End. Processed heartbeat.');
243 |
244 | heartbeat_process('thold', 'parent', 0);
245 | }
246 |
247 | } else {
248 | thold_daemon_debug('WARNING: No database connection. Sleeping for 60 seconds.');
249 |
250 | sleep(60);
251 | }
252 | }
253 |
254 | function thold_truncate_daemon_data() {
255 | thold_daemon_debug('Truncating historical Threshold Daemon Data');
256 |
257 | db_execute('TRUNCATE TABLE plugin_thold_daemon_data');
258 | }
259 |
260 | function thold_poller_running() {
261 | return db_fetch_cell('SELECT COUNT(*) FROM poller_time WHERE end_time = "0000-00-00"');
262 | }
263 |
264 | /**
265 | * sig_handler - provides a generic means to catch exceptions to the Cacti log.
266 | *
267 | * @param $signo - (int) the signal that was thrown by the interface.
268 | *
269 | * @returns - null
270 | */
271 | function sig_handler($signo) {
272 | global $config;
273 |
274 | switch ($signo) {
275 | case SIGTERM:
276 | case SIGINT:
277 | /* kill any child processes */
278 | $processes = db_fetch_assoc('SELECT * FROM processes WHERE tasktype = "thold" AND taskname = "child"');
279 |
280 | if (cacti_sizeof($processes)) {
281 | foreach($processes as $p) {
282 | thold_daemon_debug(sprintf('Killing Child Process with the pid of %u', $p['pid']));
283 | posix_kill($p['pid'], SIGTERM);
284 | }
285 | }
286 |
287 | thold_cacti_log('WARNING: Thold Daemon Parent Process with PID[' . getmypid() . '] terminated by user', 0);
288 |
289 | unregister_process('thold', 'parent', 0);
290 |
291 | exit;
292 | default:
293 | /* ignore all other signals */
294 | }
295 | }
296 |
297 | function thold_launch_worker($thread) {
298 | global $config, $debug;
299 |
300 | $path_php = read_config_option('path_php_binary');
301 |
302 | $process = $config['base_path'] .
303 | '/plugins/thold/thold_process.php ' .
304 | ' --thread=' . $thread .
305 | ($debug ? ' --debug':'') .
306 | ' > /dev/null';
307 |
308 | thold_daemon_debug('Starting Process: ' . $path_php . ' ' . $process);
309 |
310 | exec_background($path_php, $process);
311 | }
312 |
313 | function thold_heartbeat_processes($processes, $new_processes) {
314 | global $config;
315 |
316 | $procs = db_fetch_assoc('SELECT *
317 | FROM processes
318 | WHERE tasktype = "thold"
319 | AND taskname = "child"
320 | ORDER BY taskid DESC');
321 |
322 | $running_processes = cacti_sizeof($procs);
323 |
324 | // Check for a crashed process
325 | $process_num = -1;
326 | foreach($procs as $id => $p) {
327 | // Check for crashed processes first
328 | if ($process_num != -1) {
329 | if ($process_num - 1 != $p['taskid']) {
330 | thold_daemon_debug(sprintf('WARNING: Detected Crashed Thold Thread. Relaunching Crashed Thread %s', $process_num - 1));
331 |
332 | thold_launch_worker($process_num -1);
333 |
334 | $running_processes++;
335 | }
336 | } else {
337 | // Check for hung processes next
338 | $lastupdate = strtotime($p['last_update']);
339 | $now = time();
340 | if ($lastupdate + 120 < $now) {
341 | thold_daemon_debug(sprintf('WARNING: Detected Hung Thold Thread. Killing/Relaunching Hung Thread %s', $p['taskid']));
342 |
343 | posix_kill($p['pid'], SIGTERM);
344 |
345 | thold_launch_worker($p['taskid']);
346 | }
347 | }
348 |
349 | $process_num = $p['taskid'];
350 | }
351 |
352 | foreach($procs as $id => $p) {
353 | if (function_exists('posix_getpgid')) {
354 | $running = posix_getpgid($p['pid']);
355 | } elseif (function_exists('posix_kill')) {
356 | $running = posix_kill($p['pid'], 0);
357 | }
358 |
359 | if (!$running) {
360 | thold_daemon_debug(sprintf('WARNING: Thold Daemon Child[%s] Died!', $p['pid']));
361 |
362 | cacti_log(sprintf('WARNING: Thold Daemon Child[%s] Died!', $p['pid']), false, 'THOLD');
363 |
364 | $running_processes--;
365 | unset($procs[$id]);
366 | }
367 | }
368 |
369 | if ($running_processes != $new_processes) {
370 | if ($running_processes > $new_processes) {
371 | thold_daemon_debug(sprintf('Thold Thread Detected Process Count Change. Reducing Process Count by %s', $running_processes - $new_processes));
372 |
373 | foreach($procs as $id => $p) {
374 | posix_kill($p['pid'], SIGTERM);
375 | $running_processes--;
376 | if ($running_processes == $new_processes) {
377 | break;
378 | }
379 | }
380 | } else {
381 | thold_daemon_debug(sprintf('Thold Thread Detected Process Count Change. Increasing Process Count by %s', $new_processes - $running_processes));
382 |
383 | while($running_processes < $new_processes) {
384 | $running_processes++;
385 |
386 | thold_launch_worker($running_processes);
387 | }
388 | }
389 | }
390 | }
391 |
392 | function thold_prime_distribution($processes, $truncate = false) {
393 | thold_daemon_debug('Rebalancing Thread Allocation by Device');
394 |
395 | $seen_processes = db_fetch_cell('SELECT COUNT(DISTINCT thread_id) FROM thold_data');
396 |
397 | if ($truncate || $seen_processes != $processes) {
398 | db_execute('UPDATE thold_data SET thread_id = 0');
399 | }
400 |
401 | $not_set_threads = db_fetch_cell('SELECT COUNT(id) FROM thold_data WHERE thread_id = 0');
402 |
403 | if ($not_set_threads > 0) {
404 | // Get the current distribution of threads
405 | $threads = array_rekey(
406 | db_fetch_assoc('SELECT thread_id, host_id
407 | FROM thold_data
408 | WHERE thread_id > 0'),
409 | 'host_id', 'thread_id'
410 | );
411 |
412 | $tholds = db_fetch_assoc('SELECT id, host_id
413 | FROM thold_data
414 | WHERE thread_id = 0');
415 |
416 | $thread_num = 1;
417 |
418 | foreach($tholds as $t) {
419 | if (!isset($threads[$t['host_id']])) {
420 | $threads[$t['host_id']] = $thread_num;
421 | $thread_num++;
422 | }
423 |
424 | if ($thread_num > $processes) {
425 | $thread_num = 1;
426 | }
427 | }
428 |
429 | foreach($threads as $host_id => $thread) {
430 | db_execute_prepared('UPDATE thold_data
431 | SET thread_id = ?
432 | WHERE host_id = ?',
433 | array($thread, $host_id));
434 | }
435 | }
436 |
437 | thold_daemon_debug('Thread Rebalancing Allocation by Device Completed');
438 | }
439 |
440 | function thold_daemon_debug($string) {
441 | global $debug;
442 |
443 | // Get the cached value
444 | $daemon_debug = read_config_option('thold_daemon_debug');
445 |
446 | if ($debug || $daemon_debug) {
447 | $output = date('Y-m-d H:i:s') . ' DEBUG: ' . trim($string);
448 |
449 | print $output . PHP_EOL;
450 | }
451 | }
452 |
453 | function display_version() {
454 | global $config;
455 |
456 | if (!function_exists('plugin_thold_version')) {
457 | include_once($config['base_path'] . '/plugins/thold/setup.php');
458 | }
459 |
460 | $info = plugin_thold_version();
461 | print 'Threshold Daemon, Version ' . $info['version'] . ', ' . COPYRIGHT_YEARS . PHP_EOL;
462 | }
463 |
464 |
465 | /* display_help - displays the usage of the function */
466 | function display_help () {
467 | display_version();
468 |
469 | print PHP_EOL . 'usage: thold_daemon.php [ --foreground | -f ] [ --debug ]' . PHP_EOL . PHP_EOL;
470 | print 'The Threshold Daemon processor for the Thold Plugin.' . PHP_EOL;
471 | }
472 |
473 |
--------------------------------------------------------------------------------
/thold_notify.php:
--------------------------------------------------------------------------------
1 | 0) {
179 | $currentval = thold_build_cdef($thold_data['cdef'], $currentval, $thold_data['local_data_id'], $thold_data['data_template_rrd_id']);
180 | }
181 |
182 | break;
183 | case 2:
184 | if ($thold_data['percent_ds'] != '') {
185 | $currentval = thold_calculate_percent($thold_data, $currentval, $rrd_reindexed);
186 | }
187 |
188 | break;
189 | case 3:
190 | if ($thold_data['expression'] != '') {
191 | $currentval = thold_calculate_expression($thold_data, $currentval, $rrd_reindexed, $rrd_time_reindexed);
192 | }
193 |
194 | break;
195 | case 4:
196 | if ($thold_data['upper_ds'] != '') {
197 | $currentval = thold_calculate_lower_upper($thold_data, $currentval, $rrd_reindexed);
198 | }
199 |
200 | break;
201 | }
202 |
203 | if (is_numeric($currentval)) {
204 | $currentval = round($currentval, 4);
205 | } else {
206 | $currentval = '';
207 | }
208 |
209 | if (isset($item[$thold_data['name']])) {
210 | $lasttime = $item[$thold_data['name']];
211 | } else {
212 | $lasttime = $currenttime - $thold_data['rrd_step'];
213 | }
214 |
215 | thold_daemon_debug(sprintf('Checked Name:%s, Graph:%s, Value:%s, Time:%s', $thold_data['thold_name'], $thold_data['local_graph_id'], $currentval, $currenttime), $thread);
216 |
217 | db_execute_prepared('UPDATE thold_data
218 | SET tcheck = 1, lastread = ?,
219 | lasttime = FROM_UNIXTIME(?), oldvalue = ?
220 | WHERE id = ?',
221 | array($currentval, $currenttime, $lasttime, $thold_data['thold_id'])
222 | );
223 | }
224 |
225 | $tholds = thold_get_thresholds_tholdcheck($thread, $start_time);
226 |
227 | $total_tholds = cacti_sizeof($tholds);
228 |
229 | thold_daemon_debug(sprintf('Found %u Thresholds to check for breech.', $total_tholds), $thread);
230 |
231 | if ($total_tholds) {
232 | foreach ($tholds as $thold) {
233 | thold_check_threshold($thold);
234 |
235 | db_execute_prepared('UPDATE thold_data
236 | SET tcheck = 0
237 | WHERE id = ?',
238 | array($thold['id'])
239 | );
240 | }
241 | }
242 |
243 | $end = microtime(true);
244 |
245 | if (read_config_option('remote_storage_method') == 1) {
246 | db_execute_prepared('DELETE ptdd
247 | FROM plugin_thold_daemon_data AS ptdd
248 | INNER JOIN thold_data AS td
249 | ON ptdd.id = td.id
250 | WHERE ptdd.poller_id = ?
251 | AND td.thread_id = ?
252 | AND ptdd.time <= FROM_UNIXTIME(?)',
253 | array($config['poller_id'], $thread, $start_time));
254 | } else {
255 | db_execute_prepared('DELETE ptdd
256 | FROM plugin_thold_daemon_data AS ptdd
257 | INNER JOIN thold_data AS td
258 | ON ptdd.id = td.id
259 | WHERE td.thread_id = ?
260 | AND ptdd.time <= FROM_UNIXTIME(?)',
261 | array($thread, $start_time));
262 | }
263 | } else {
264 | sleep(5);
265 |
266 | $cnn_id = thold_db_reconnect($cnn_id);
267 |
268 | heartbeat_process('thold', 'child', $thread);
269 | }
270 | } else {
271 | thold_daemon_debug('WARNING: Thold Database Connection Down. Sleeping 60 Seconds', $thread);
272 | sleep(60);
273 | }
274 | }
275 |
276 | /**
277 | * sig_handler - provides a generic means to catch exceptions to the Cacti log.
278 | *
279 | * @param $signo - (int) the signal that was thrown by the interface.
280 | *
281 | * @returns - null
282 | */
283 | function sig_handler($signo) {
284 | global $thread;
285 |
286 | switch ($signo) {
287 | case SIGTERM:
288 | case SIGINT:
289 | thold_cacti_log('WARNING: Thold Daemon Child Process with PID[' . getmypid() . '] terminated by user', $thread);
290 | unregister_process('thold', 'child', $thread);
291 |
292 | exit;
293 | break;
294 | default:
295 | /* ignore all other signals */
296 | }
297 | }
298 |
299 | function thold_daemon_debug($message, $thread) {
300 | global $debug;
301 |
302 | $daemon_debug = read_config_option('thold_daemon_debug');
303 |
304 | if ($debug || $daemon_debug) {
305 | thold_cacti_log($message, $thread);
306 | }
307 | }
308 |
309 | function thold_get_thresholds_tholdcheck($thread, $start_time) {
310 | global $config;
311 |
312 | /* check all thresholds */
313 | if (read_config_option('remote_storage_method') == 1) {
314 | $sql_query = "SELECT td.*, h.hostname,
315 | h.description, h.notes AS dnotes, h.snmp_engine_id
316 | FROM plugin_thold_daemon_data AS tdd
317 | INNER JOIN thold_data AS td
318 | ON td.id = tdd.id
319 | LEFT JOIN data_template_rrd AS dtr
320 | ON dtr.id = td.data_template_rrd_id
321 | LEFT JOIN host as h
322 | ON td.host_id = h.id
323 | WHERE td.thread_id = ?
324 | AND tdd.poller_id = ?
325 | AND tdd.time <= FROM_UNIXTIME(?)
326 | AND td.thold_enabled = 'on'
327 | AND td.thold_per_enabled = 'on'
328 | AND td.tcheck = 1
329 | AND h.status = 3";
330 |
331 | $tholds = api_plugin_hook_function('thold_get_live_hosts',
332 | db_fetch_assoc_prepared($sql_query, array($thread, $config['poller_id'], $start_time))
333 | );
334 | } else {
335 | $sql_query = "SELECT td.*, h.hostname,
336 | h.description, h.notes AS dnotes, h.snmp_engine_id
337 | FROM plugin_thold_daemon_data AS tdd
338 | INNER JOIN thold_data AS td
339 | ON td.id = tdd.id
340 | LEFT JOIN data_template_rrd AS dtr
341 | ON dtr.id = td.data_template_rrd_id
342 | LEFT JOIN host as h
343 | ON td.host_id = h.id
344 | WHERE td.thread_id = ?
345 | AND tdd.time <= FROM_UNIXTIME(?)
346 | AND td.thold_enabled = 'on'
347 | AND td.thold_per_enabled = 'on'
348 | AND td.tcheck = 1
349 | AND h.status = 3";
350 |
351 | $tholds = api_plugin_hook_function('thold_get_live_hosts',
352 | db_fetch_assoc_prepared($sql_query, array($thread, $start_time))
353 | );
354 | }
355 |
356 | return $tholds;
357 | }
358 |
359 | function thold_get_thresholds_precheck($thread, $start_time) {
360 | global $config;
361 |
362 | if (read_config_option('remote_storage_method') == 1) {
363 | $sql_query = "SELECT tdd.id, tdd.rrd_reindexed, tdd.rrd_time_reindexed,
364 | td.id AS thold_id, td.name_cache AS thold_name, td.local_graph_id,
365 | td.percent_ds, td.expression, td.upper_ds, td.data_type, td.cdef, td.local_data_id,
366 | td.data_template_rrd_id, td.lastread,
367 | UNIX_TIMESTAMP(td.lasttime) AS lasttime, td.oldvalue,
368 | dtr.data_source_name AS name, dtr.data_source_type_id,
369 | dtd.rrd_step, dtr.rrd_maximum
370 | FROM plugin_thold_daemon_data AS tdd
371 | INNER JOIN thold_data AS td
372 | ON td.id = tdd.id
373 | LEFT JOIN data_template_rrd AS dtr
374 | ON dtr.id = td.data_template_rrd_id
375 | LEFT JOIN data_template_data AS dtd
376 | ON dtd.local_data_id = td.local_data_id
377 | WHERE td.thread_id = ?
378 | AND tdd.poller_id = ?
379 | AND tdd.time <= FROM_UNIXTIME(?)
380 | AND dtr.data_source_name != ''";
381 |
382 | $tholds = db_fetch_assoc_prepared($sql_query, array($thread, $config['poller_id'], $start_time));
383 | } else {
384 | $sql_query = "SELECT tdd.id, tdd.rrd_reindexed, tdd.rrd_time_reindexed,
385 | td.id AS thold_id, td.name_cache AS thold_name, td.local_graph_id,
386 | td.percent_ds, td.expression, td.upper_ds, td.data_type, td.cdef, td.local_data_id,
387 | td.data_template_rrd_id, td.lastread,
388 | UNIX_TIMESTAMP(td.lasttime) AS lasttime, td.oldvalue,
389 | dtr.data_source_name AS name, dtr.data_source_type_id,
390 | dtd.rrd_step, dtr.rrd_maximum
391 | FROM plugin_thold_daemon_data AS tdd
392 | INNER JOIN thold_data AS td
393 | ON td.id = tdd.id
394 | LEFT JOIN data_template_rrd AS dtr
395 | ON dtr.id = td.data_template_rrd_id
396 | LEFT JOIN data_template_data AS dtd
397 | ON dtd.local_data_id = td.local_data_id
398 | WHERE td.thread_id = ?
399 | AND tdd.time <= FROM_UNIXTIME(?)
400 | AND dtr.data_source_name != ''";
401 |
402 | $tholds = db_fetch_assoc_prepared($sql_query, array($thread, $start_time));
403 | }
404 |
405 | return $tholds;
406 | }
407 |
408 | function thold_db_connection(){
409 | global $cnn_id;
410 |
411 | if (is_object($cnn_id)) {
412 | // Avoid showing errors
413 | restore_error_handler();
414 | set_error_handler('thold_error_handler');
415 |
416 | $cacti_version = db_fetch_cell('SELECT cacti FROM version');
417 |
418 | // Restore Cacti's Error handler
419 | restore_error_handler();
420 | set_error_handler('CactiErrorHandler');
421 |
422 | return is_null($cacti_version) ? false : true;
423 | }
424 |
425 | return false;
426 | }
427 |
428 | function thold_db_reconnect($cnn_id = null) {
429 | chdir(dirname(__FILE__));
430 |
431 | include('../../include/config.php');
432 |
433 | if (is_object($cnn_id)) {
434 | db_close($cnn_id);
435 | }
436 |
437 | // Avoid showing errors
438 | restore_error_handler();
439 | set_error_handler('thold_error_handler');
440 |
441 | // Connect to the database server
442 | $cnn_id = db_connect_real($database_hostname, $database_username, $database_password, $database_default, $database_type, $database_port, $database_ssl);
443 |
444 | // Restore Cacti's Error handler
445 | restore_error_handler();
446 | set_error_handler('CactiErrorHandler');
447 |
448 | return $cnn_id;
449 | }
450 |
451 | function thold_cli_debug($string) {
452 | global $debug;
453 |
454 | if ($debug) {
455 | $output = date('Y-m-d H:i:s') . ' DEBUG: ' . trim($string);
456 |
457 | print $output . PHP_EOL;
458 | }
459 | }
460 |
461 | function display_version() {
462 | global $config;
463 |
464 | if (!function_exists('plugin_thold_version')) {
465 | include_once($config['base_path'] . '/plugins/thold/setup.php');
466 | }
467 |
468 | $info = plugin_thold_version();
469 | print 'Threshold Processor, Version ' . $info['version'] . ', ' . COPYRIGHT_YEARS . PHP_EOL;
470 | }
471 |
472 | /* display_help - displays the usage of the function */
473 | function display_help () {
474 | display_version();
475 |
476 | print PHP_EOL . 'usage: thold_process.php --thread=N [--debug]' . PHP_EOL . PHP_EOL;
477 | print 'The main Threshold Processor for the Thold Plugin.' . PHP_EOL;
478 | }
479 |
480 |
--------------------------------------------------------------------------------